Loading logd/logd.rc +2 −1 Original line number Original line Diff line number Diff line Loading @@ -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 Loading logd/main.cpp +20 −105 Original line number Original line Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 = {}; Loading @@ -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) { Loading @@ -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; } } Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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. Loading Loading
logd/logd.rc +2 −1 Original line number Original line Diff line number Diff line Loading @@ -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 Loading
logd/main.cpp +20 −105 Original line number Original line Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 = {}; Loading @@ -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) { Loading @@ -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; } } Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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. Loading