Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28e09852 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "uevent"

* changes:
  libcutils: Work around the lack of __mulodi4
  libcutils: Make uevent_kernel_* namespace-aware
parents dbef1eeb fae195b1
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -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: {
@@ -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: {
@@ -145,6 +160,9 @@ cc_library {
                "arch-x86_64/android_memset16.S",
                "arch-x86_64/android_memset32.S",
            ],
            sanitize: {
                misc_undefined: ["integer"],
            },
        },
    },

+8 −0
Original line number Diff line number Diff line
@@ -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 */

+67 −23
Original line number Diff line number Diff line
@@ -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>
@@ -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);
}
@@ -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);
@@ -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;
    }
@@ -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;
@@ -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) {
@@ -131,3 +173,5 @@ int uevent_open_socket(int buf_sz, bool passcred)

    return s;
}

}  // extern "C"