Loading libcutils/Android.bp +22 −4 Original line number Diff line number Diff line Loading @@ -112,25 +112,34 @@ cc_library { "properties.cpp", "qtaguid.c", "trace-dev.c", "uevent.c", "uevent.cpp", ], sanitize: { misc_undefined: ["integer"], }, }, android_arm: { srcs: ["arch-arm/memset32.S"], sanitize: { misc_undefined: ["integer"], }, }, android_arm64: { srcs: ["arch-arm64/android_memset.S"], sanitize: { misc_undefined: ["integer"], }, }, android_mips: { srcs: ["arch-mips/android_memset.c"], sanitize: { misc_undefined: ["integer"], }, }, android_mips64: { srcs: ["arch-mips/android_memset.c"], sanitize: { misc_undefined: ["integer"], }, }, android_x86: { Loading @@ -138,6 +147,12 @@ cc_library { "arch-x86/android_memset16.S", "arch-x86/android_memset32.S", ], // TODO: This is to work around b/29412086. // Remove once __mulodi4 is available and move the "sanitize" block // to the android target. sanitize: { misc_undefined: [], }, }, android_x86_64: { Loading @@ -145,6 +160,9 @@ cc_library { "arch-x86_64/android_memset16.S", "arch-x86_64/android_memset32.S", ], sanitize: { misc_undefined: ["integer"], }, }, }, Loading libcutils/include/private/android_filesystem_config.h +8 −0 Original line number Diff line number Diff line Loading @@ -170,6 +170,14 @@ #define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ #define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */ /* * This is a magic number in the kernel and not something that was picked * arbitrarily. This value is returned whenever a uid that has no mapping in the * user namespace is returned to userspace: * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/highuid.h?h=v4.4#n40 */ #define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */ #define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ #define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ Loading libcutils/uevent.c→libcutils/uevent.cpp +67 −23 Original line number Diff line number Diff line Loading @@ -17,7 +17,8 @@ #include <cutils/uevent.h> #include <errno.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <sys/socket.h> Loading @@ -26,11 +27,60 @@ #include <linux/netlink.h> #include <fstream> #include <private/android_filesystem_config.h> namespace { // Returns the uid of root in the current user namespace. // Returns AID_OVERFLOWUID if the root user is not mapped in the current // namespace. // Returns 0 if the kernel is not user namespace-aware (for backwards // compatibility) or if AID_OVERFLOWUID could not be validated to match what the // kernel would return. uid_t GetRootUid() { constexpr uid_t kParentRootUid = 0; std::ifstream uid_map_file("/proc/self/uid_map"); if (!uid_map_file) { // The kernel does not support user namespaces. return kParentRootUid; } uid_t current_namespace_uid, parent_namespace_uid; uint32_t length; while (uid_map_file >> current_namespace_uid >> parent_namespace_uid >> length) { // Since kParentRootUid is 0, it should be the first entry in the mapped // range. if (parent_namespace_uid != kParentRootUid || length < 1) continue; return current_namespace_uid; } // Sanity check: verify that the overflow UID is the one to be returned by // the kernel. std::ifstream overflowuid_file("/proc/sys/kernel/overflowuid"); if (!overflowuid_file) { // It's better to return 0 in case we cannot make sure that the overflow // UID matches. return kParentRootUid; } uid_t kernel_overflow_uid; if (!(overflowuid_file >> kernel_overflow_uid) || kernel_overflow_uid != AID_OVERFLOWUID) return kParentRootUid; // root is unmapped, use the kernel "overflow" uid. return AID_OVERFLOWUID; } } // namespace extern "C" { /** * Like recv(), but checks that messages actually originate from the kernel. */ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) { ssize_t uevent_kernel_multicast_recv(int socket, void* buffer, size_t length) { uid_t uid = -1; return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid); } Loading @@ -44,25 +94,19 @@ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) * returns -1, sets errno to EIO, and sets "user" to the UID associated with the * message. If the peer UID cannot be determined, "user" is set to -1." */ ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid) { ssize_t uevent_kernel_multicast_uid_recv(int socket, void* buffer, size_t length, uid_t* uid) { return uevent_kernel_recv(socket, buffer, length, true, uid); } ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require_group, uid_t *uid) { ssize_t uevent_kernel_recv(int socket, void* buffer, size_t length, bool require_group, uid_t* uid) { static const uid_t root_uid = GetRootUid(); struct iovec iov = {buffer, length}; struct sockaddr_nl addr; char control[CMSG_SPACE(sizeof(struct ucred))]; struct msghdr hdr = { &addr, sizeof(addr), &iov, 1, control, sizeof(control), 0, &addr, sizeof(addr), &iov, 1, control, sizeof(control), 0, }; struct ucred* cred; *uid = -1; ssize_t n = recvmsg(socket, &hdr, 0); Loading @@ -76,9 +120,9 @@ ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require goto out; } struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg); cred = (struct ucred*)CMSG_DATA(cmsg); *uid = cred->uid; if (cred->uid != 0) { if (cred->uid != root_uid) { /* ignoring netlink message from non-root user */ goto out; } Loading @@ -101,8 +145,7 @@ out: return -1; } int uevent_open_socket(int buf_sz, bool passcred) { int uevent_open_socket(int buf_sz, bool passcred) { struct sockaddr_nl addr; int on = passcred; int s; Loading @@ -113,8 +156,7 @@ int uevent_open_socket(int buf_sz, bool passcred) addr.nl_groups = 0xffffffff; s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT); if(s < 0) return -1; if (s < 0) return -1; /* buf_sz should be less than net.core.rmem_max for this to succeed */ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0) { Loading @@ -131,3 +173,5 @@ int uevent_open_socket(int buf_sz, bool passcred) return s; } } // extern "C" Loading
libcutils/Android.bp +22 −4 Original line number Diff line number Diff line Loading @@ -112,25 +112,34 @@ cc_library { "properties.cpp", "qtaguid.c", "trace-dev.c", "uevent.c", "uevent.cpp", ], sanitize: { misc_undefined: ["integer"], }, }, android_arm: { srcs: ["arch-arm/memset32.S"], sanitize: { misc_undefined: ["integer"], }, }, android_arm64: { srcs: ["arch-arm64/android_memset.S"], sanitize: { misc_undefined: ["integer"], }, }, android_mips: { srcs: ["arch-mips/android_memset.c"], sanitize: { misc_undefined: ["integer"], }, }, android_mips64: { srcs: ["arch-mips/android_memset.c"], sanitize: { misc_undefined: ["integer"], }, }, android_x86: { Loading @@ -138,6 +147,12 @@ cc_library { "arch-x86/android_memset16.S", "arch-x86/android_memset32.S", ], // TODO: This is to work around b/29412086. // Remove once __mulodi4 is available and move the "sanitize" block // to the android target. sanitize: { misc_undefined: [], }, }, android_x86_64: { Loading @@ -145,6 +160,9 @@ cc_library { "arch-x86_64/android_memset16.S", "arch-x86_64/android_memset32.S", ], sanitize: { misc_undefined: ["integer"], }, }, }, Loading
libcutils/include/private/android_filesystem_config.h +8 −0 Original line number Diff line number Diff line Loading @@ -170,6 +170,14 @@ #define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ #define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */ /* * This is a magic number in the kernel and not something that was picked * arbitrarily. This value is returned whenever a uid that has no mapping in the * user namespace is returned to userspace: * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/highuid.h?h=v4.4#n40 */ #define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */ #define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ #define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ Loading
libcutils/uevent.c→libcutils/uevent.cpp +67 −23 Original line number Diff line number Diff line Loading @@ -17,7 +17,8 @@ #include <cutils/uevent.h> #include <errno.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <sys/socket.h> Loading @@ -26,11 +27,60 @@ #include <linux/netlink.h> #include <fstream> #include <private/android_filesystem_config.h> namespace { // Returns the uid of root in the current user namespace. // Returns AID_OVERFLOWUID if the root user is not mapped in the current // namespace. // Returns 0 if the kernel is not user namespace-aware (for backwards // compatibility) or if AID_OVERFLOWUID could not be validated to match what the // kernel would return. uid_t GetRootUid() { constexpr uid_t kParentRootUid = 0; std::ifstream uid_map_file("/proc/self/uid_map"); if (!uid_map_file) { // The kernel does not support user namespaces. return kParentRootUid; } uid_t current_namespace_uid, parent_namespace_uid; uint32_t length; while (uid_map_file >> current_namespace_uid >> parent_namespace_uid >> length) { // Since kParentRootUid is 0, it should be the first entry in the mapped // range. if (parent_namespace_uid != kParentRootUid || length < 1) continue; return current_namespace_uid; } // Sanity check: verify that the overflow UID is the one to be returned by // the kernel. std::ifstream overflowuid_file("/proc/sys/kernel/overflowuid"); if (!overflowuid_file) { // It's better to return 0 in case we cannot make sure that the overflow // UID matches. return kParentRootUid; } uid_t kernel_overflow_uid; if (!(overflowuid_file >> kernel_overflow_uid) || kernel_overflow_uid != AID_OVERFLOWUID) return kParentRootUid; // root is unmapped, use the kernel "overflow" uid. return AID_OVERFLOWUID; } } // namespace extern "C" { /** * Like recv(), but checks that messages actually originate from the kernel. */ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) { ssize_t uevent_kernel_multicast_recv(int socket, void* buffer, size_t length) { uid_t uid = -1; return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid); } Loading @@ -44,25 +94,19 @@ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) * returns -1, sets errno to EIO, and sets "user" to the UID associated with the * message. If the peer UID cannot be determined, "user" is set to -1." */ ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid) { ssize_t uevent_kernel_multicast_uid_recv(int socket, void* buffer, size_t length, uid_t* uid) { return uevent_kernel_recv(socket, buffer, length, true, uid); } ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require_group, uid_t *uid) { ssize_t uevent_kernel_recv(int socket, void* buffer, size_t length, bool require_group, uid_t* uid) { static const uid_t root_uid = GetRootUid(); struct iovec iov = {buffer, length}; struct sockaddr_nl addr; char control[CMSG_SPACE(sizeof(struct ucred))]; struct msghdr hdr = { &addr, sizeof(addr), &iov, 1, control, sizeof(control), 0, &addr, sizeof(addr), &iov, 1, control, sizeof(control), 0, }; struct ucred* cred; *uid = -1; ssize_t n = recvmsg(socket, &hdr, 0); Loading @@ -76,9 +120,9 @@ ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require goto out; } struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg); cred = (struct ucred*)CMSG_DATA(cmsg); *uid = cred->uid; if (cred->uid != 0) { if (cred->uid != root_uid) { /* ignoring netlink message from non-root user */ goto out; } Loading @@ -101,8 +145,7 @@ out: return -1; } int uevent_open_socket(int buf_sz, bool passcred) { int uevent_open_socket(int buf_sz, bool passcred) { struct sockaddr_nl addr; int on = passcred; int s; Loading @@ -113,8 +156,7 @@ int uevent_open_socket(int buf_sz, bool passcred) addr.nl_groups = 0xffffffff; s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT); if(s < 0) return -1; if (s < 0) return -1; /* buf_sz should be less than net.core.rmem_max for this to succeed */ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0) { Loading @@ -131,3 +173,5 @@ int uevent_open_socket(int buf_sz, bool passcred) return s; } } // extern "C"