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

Commit b7a25ef1 authored by Tom Cherry's avatar Tom Cherry Committed by Gerrit Code Review
Browse files

Merge "logd: don't drop user/groups/capabilities/priority in drop_privs()"

parents d949bf8d 0b2a011c
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -6,7 +6,8 @@ service logd /system/bin/logd
    file /dev/kmsg w
    file /dev/kmsg w
    user logd
    user logd
    group logd system package_info readproc
    group logd system package_info readproc
    capabilities SYSLOG AUDIT_CONTROL SETGID
    capabilities SYSLOG AUDIT_CONTROL
    priority 10
    writepid /dev/cpuset/system-background/tasks
    writepid /dev/cpuset/system-background/tasks


service logd-reinit /system/bin/logd --reinit
service logd-reinit /system/bin/logd --reinit
+20 −105
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#include <dirent.h>
#include <dirent.h>
#include <errno.h>
#include <errno.h>
#include <fcntl.h>
#include <fcntl.h>
#include <linux/capability.h>
#include <poll.h>
#include <poll.h>
#include <sched.h>
#include <sched.h>
#include <semaphore.h>
#include <semaphore.h>
@@ -57,35 +58,10 @@
    '<', '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
    '<', '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
        '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, '>'
        '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, '>'


//
// The service is designed to be run by init, it does not respond well to starting up manually. Init
// The service is designed to be run by init, it does not respond well
// has a 'sigstop' feature that sends SIGSTOP to a service immediately before calling exec().  This
// to starting up manually. When starting up manually the sockets will
// allows debuggers, etc to be attached to logd at the very beginning, while still having init
// fail to open typically for one of the following reasons:
// handle the user, groups, capabilities, files, etc setup.
//     EADDRINUSE if logger is running.
//     EACCESS if started without precautions (below)
//
// Here is a cookbook procedure for starting up logd manually assuming
// init is out of the way, pedantically all permissions and SELinux
// security is put back in place:
//
//    setenforce 0
//    rm /dev/socket/logd*
//    chmod 777 /dev/socket
//        # here is where you would attach the debugger or valgrind for example
//    runcon u:r:logd:s0 /system/bin/logd </dev/null >/dev/null 2>&1 &
//    sleep 1
//    chmod 755 /dev/socket
//    chown logd.logd /dev/socket/logd*
//    restorecon /dev/socket/logd*
//    setenforce 1
//
// If minimalism prevails, typical for debugging and security is not a concern:
//
//    setenforce 0
//    chmod 777 /dev/socket
//    logd
//

static int drop_privs(bool klogd, bool auditd) {
static int drop_privs(bool klogd, bool auditd) {
    sched_param param = {};
    sched_param param = {};


@@ -99,11 +75,6 @@ static int drop_privs(bool klogd, bool auditd) {
        return -1;
        return -1;
    }
    }


    if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
        android::prdebug("failed to set background cgroup");
        return -1;
    }

    if (!__android_logger_property_get_bool("ro.debuggable",
    if (!__android_logger_property_get_bool("ro.debuggable",
                                            BOOL_DEFAULT_FALSE) &&
                                            BOOL_DEFAULT_FALSE) &&
        prctl(PR_SET_DUMPABLE, 0) == -1) {
        prctl(PR_SET_DUMPABLE, 0) == -1) {
@@ -111,52 +82,26 @@ static int drop_privs(bool klogd, bool auditd) {
        return -1;
        return -1;
    }
    }


    std::unique_ptr<struct _cap_struct, int (*)(void*)> caps(cap_init(),
    std::unique_ptr<struct _cap_struct, int (*)(void*)> caps(cap_init(), cap_free);
                                                             cap_free);
    if (cap_clear(caps.get()) < 0) {
    if (cap_clear(caps.get()) < 0) return -1;
    cap_value_t cap_value[] = { CAP_SETGID,  // must be first for below
                                klogd ? CAP_SYSLOG : CAP_SETGID,
                                auditd ? CAP_AUDIT_CONTROL : CAP_SETGID };
    if (cap_set_flag(caps.get(), CAP_PERMITTED, arraysize(cap_value), cap_value,
                     CAP_SET) < 0) {
        return -1;
    }
    if (cap_set_flag(caps.get(), CAP_EFFECTIVE, arraysize(cap_value), cap_value,
                     CAP_SET) < 0) {
        return -1;
    }
    if (cap_set_proc(caps.get()) < 0) {
        android::prdebug(
            "failed to set CAP_SETGID, CAP_SYSLOG or CAP_AUDIT_CONTROL (%d)",
            errno);
        return -1;
        return -1;
    }
    }

    std::vector<cap_value_t> cap_value;
    gid_t groups[] = { AID_READPROC };
    if (klogd) {

        cap_value.emplace_back(CAP_SYSLOG);
    if (setgroups(arraysize(groups), groups) == -1) {
        android::prdebug("failed to set AID_READPROC groups");
        return -1;
    }

    if (setgid(AID_LOGD) != 0) {
        android::prdebug("failed to set AID_LOGD gid");
        return -1;
    }
    }

    if (auditd) {
    if (setuid(AID_LOGD) != 0) {
        cap_value.emplace_back(CAP_AUDIT_CONTROL);
        android::prdebug("failed to set AID_LOGD uid");
        return -1;
    }
    }


    if (cap_set_flag(caps.get(), CAP_PERMITTED, 1, cap_value, CAP_CLEAR) < 0) {
    if (cap_set_flag(caps.get(), CAP_PERMITTED, cap_value.size(), cap_value.data(), CAP_SET) < 0) {
        return -1;
        return -1;
    }
    }
    if (cap_set_flag(caps.get(), CAP_EFFECTIVE, 1, cap_value, CAP_CLEAR) < 0) {
    if (cap_set_flag(caps.get(), CAP_EFFECTIVE, cap_value.size(), cap_value.data(), CAP_SET) < 0) {
        return -1;
        return -1;
    }
    }
    if (cap_set_proc(caps.get()) < 0) {
    if (cap_set_proc(caps.get()) < 0) {
        android::prdebug("failed to clear CAP_SETGID (%d)", errno);
        android::prdebug("failed to set CAP_SYSLOG or CAP_AUDIT_CONTROL (%d)", errno);
        return -1;
        return -1;
    }
    }


@@ -227,30 +172,6 @@ static bool package_list_parser_cb(pkg_info* info, void* /* userdata */) {


static void* reinit_thread_start(void* /*obj*/) {
static void* reinit_thread_start(void* /*obj*/) {
    prctl(PR_SET_NAME, "logd.daemon");
    prctl(PR_SET_NAME, "logd.daemon");
    set_sched_policy(0, SP_BACKGROUND);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);

    // We should drop to AID_LOGD, if we are anything else, we have
    // even lesser privileges and accept our fate.
    gid_t groups[] = {
        AID_SYSTEM,        // search access to /data/system path
        AID_PACKAGE_INFO,  // readonly access to /data/system/packages.list
    };
    if (setgroups(arraysize(groups), groups) == -1) {
        android::prdebug(
            "logd.daemon: failed to set AID_SYSTEM AID_PACKAGE_INFO groups");
    }
    if (setgid(AID_LOGD) != 0) {
        android::prdebug("logd.daemon: failed to set AID_LOGD gid");
    }
    if (setuid(AID_LOGD) != 0) {
        android::prdebug("logd.daemon: failed to set AID_LOGD uid");
    }

    cap_t caps = cap_init();
    (void)cap_clear(caps);
    (void)cap_set_proc(caps);
    (void)cap_free(caps);


    while (reinit_running && !sem_wait(&reinit) && reinit_running) {
    while (reinit_running && !sem_wait(&reinit) && reinit_running) {
        // uidToName Privileged Worker
        // uidToName Privileged Worker
@@ -373,11 +294,6 @@ static void readDmesg(LogAudit* al, LogKlog* kl) {
}
}


static int issueReinit() {
static int issueReinit() {
    cap_t caps = cap_init();
    (void)cap_clear(caps);
    (void)cap_set_proc(caps);
    (void)cap_free(caps);

    int sock = TEMP_FAILURE_RETRY(socket_local_client(
    int sock = TEMP_FAILURE_RETRY(socket_local_client(
        "logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM));
        "logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM));
    if (sock < 0) return -errno;
    if (sock < 0) return -errno;
@@ -440,6 +356,11 @@ int main(int argc, char* argv[]) {
        if (fdPmesg < 0) android::prdebug("Failed to open %s\n", proc_kmsg);
        if (fdPmesg < 0) android::prdebug("Failed to open %s\n", proc_kmsg);
    }
    }


    bool auditd = __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE);
    if (drop_privs(klogd, auditd) != 0) {
        return EXIT_FAILURE;
    }

    // Reinit Thread
    // Reinit Thread
    sem_init(&reinit, 0, 0);
    sem_init(&reinit, 0, 0);
    sem_init(&uidName, 0, 0);
    sem_init(&uidName, 0, 0);
@@ -461,12 +382,6 @@ int main(int argc, char* argv[]) {
        pthread_attr_destroy(&attr);
        pthread_attr_destroy(&attr);
    }
    }


    bool auditd =
        __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE);
    if (drop_privs(klogd, auditd) != 0) {
        return EXIT_FAILURE;
    }

    // Serves the purpose of managing the last logs times read on a
    // Serves the purpose of managing the last logs times read on a
    // socket connection, and as a reader lock on a range of log
    // socket connection, and as a reader lock on a range of log
    // entries.
    // entries.