diff options
| author | Treehugger Robot <treehugger-gerrit@google.com> | 2016-11-04 14:38:22 +0000 |
|---|---|---|
| committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-11-04 14:38:23 +0000 |
| commit | fc3e90689ecc452b3f0e05144df1580ad78d5d0d (patch) | |
| tree | efc3d46b61302c57fa3aac8844dfced3f77aad6f /logd | |
| parent | fc08963f85471302976b263459f613b1d02cef7b (diff) | |
| parent | 107e29ac1b1c297a0d4ee35c4978e79f47013e2c (diff) | |
| download | system_core-fc3e90689ecc452b3f0e05144df1580ad78d5d0d.tar.gz system_core-fc3e90689ecc452b3f0e05144df1580ad78d5d0d.tar.bz2 system_core-fc3e90689ecc452b3f0e05144df1580ad78d5d0d.zip | |
Merge changes I432016e2,Id208b11b,Ia6a38729,Icdaf9e35,I842a7a64, ...
* changes:
logd: if eng build, be a bit more permissive about failures
libcutils: klog inherit android_get_control_file("/dev/kmsg")
logd: start logd service in logd uid
logd: auditd + klogd control CAPS
logd: drop capabilities in logd --reinit and logd.daemon
logd: drop libminijail dependency
logd: start logd services in logd gid
logd: set executable's capabilities in file system
logd: inherit android_get_control_file()
init: service file keyword
libcutils: add android_get_control_file()
libcutils: add android_get_control_socket() test
Diffstat (limited to 'logd')
| -rw-r--r-- | logd/Android.mk | 2 | ||||
| -rw-r--r-- | logd/logd.rc | 7 | ||||
| -rw-r--r-- | logd/main.cpp | 181 |
3 files changed, 130 insertions, 60 deletions
diff --git a/logd/Android.mk b/logd/Android.mk index 81637d21b..7fe48d746 100644 --- a/logd/Android.mk +++ b/logd/Android.mk @@ -29,7 +29,7 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libbase \ libpackagelistparser \ - libminijail + libcap # This is what we want to do: # event_logtags = $(shell \ diff --git a/logd/logd.rc b/logd/logd.rc index 31ed4df34..54349dd67 100644 --- a/logd/logd.rc +++ b/logd/logd.rc @@ -2,10 +2,15 @@ service logd /system/bin/logd socket logd stream 0666 logd logd socket logdr seqpacket 0666 logd logd socket logdw dgram 0222 logd logd - group root system readproc + file /proc/kmsg r + file /dev/kmsg w + user logd + group logd system readproc writepid /dev/cpuset/system-background/tasks service logd-reinit /system/bin/logd --reinit oneshot disabled + user logd + group logd writepid /dev/cpuset/system-background/tasks diff --git a/logd/main.cpp b/logd/main.cpp index 1ac1415ed..d698976d0 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -39,13 +39,12 @@ #include <android-base/macros.h> #include <cutils/properties.h> #include <cutils/sched_policy.h> +#include <cutils/files.h> #include <cutils/sockets.h> -#include <libminijail.h> #include <log/event_tag_map.h> #include <packagelistparser/packagelistparser.h> #include <private/android_filesystem_config.h> #include <private/android_logger.h> -#include <scoped_minijail.h> #include <utils/threads.h> #include "CommandListener.h" @@ -90,34 +89,81 @@ // logd // -static int drop_privs() { +static int drop_privs(bool klogd, bool auditd) { + // Tricky, if ro.build.type is "eng" then this is true because of the + // side effect that ro.debuggable == 1 as well, else it is false. + bool eng = __android_logger_property_get_bool("ro.build.type", BOOL_DEFAULT_FALSE); + struct sched_param param; memset(¶m, 0, sizeof(param)); if (set_sched_policy(0, SP_BACKGROUND) < 0) { - return -1; + android::prdebug("failed to set background scheduling policy"); + if (!eng) return -1; } if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) { - return -1; + android::prdebug("failed to set batch scheduler"); + if (!eng) return -1; } if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) { - return -1; + android::prdebug("failed to set background cgroup"); + if (!eng) return -1; } - if (prctl(PR_SET_DUMPABLE, 0) < 0) { + if (!eng && (prctl(PR_SET_DUMPABLE, 0) < 0)) { android::prdebug("failed to clear PR_SET_DUMPABLE"); return -1; } + if (prctl(PR_SET_KEEPCAPS, 1) < 0) { + android::prdebug("failed to set PR_SET_KEEPCAPS"); + if (!eng) return -1; + } + + std::unique_ptr<struct _cap_struct, int(*)(void *)> caps(cap_init(), cap_free); + 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); + if (!eng) return -1; + } + gid_t groups[] = { AID_READPROC }; - ScopedMinijail j(minijail_new()); - minijail_set_supplementary_gids(j.get(), arraysize(groups), groups); - minijail_change_uid(j.get(), AID_LOGD); - minijail_change_gid(j.get(), AID_LOGD); - minijail_use_caps(j.get(), CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_AUDIT_CONTROL)); - minijail_enter(j.get()); + + if (setgroups(arraysize(groups), groups) == -1) { + android::prdebug("failed to set AID_READPROC groups"); + if (!eng) return -1; + } + + if (setgid(AID_LOGD) != 0) { + android::prdebug("failed to set AID_LOGD gid"); + if (!eng) return -1; + } + + if (setuid(AID_LOGD) != 0) { + android::prdebug("failed to set AID_LOGD uid"); + if (!eng) return -1; + } + + if (cap_set_flag(caps.get(), CAP_PERMITTED, 1, cap_value, CAP_CLEAR) < 0) return -1; + if (cap_set_flag(caps.get(), CAP_EFFECTIVE, 1, cap_value, CAP_CLEAR) < 0) return -1; + if (cap_set_proc(caps.get()) < 0) { + android::prdebug("failed to clear CAP_SETGID (%d)", errno); + if (!eng) return -1; + } + return 0; } @@ -189,11 +235,16 @@ static void *reinit_thread_start(void * /*obj*/) { set_sched_policy(0, SP_BACKGROUND); setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND); - // If we are AID_ROOT, we should drop to AID_SYSTEM, if we are anything - // else, we have even lesser privileges and accept our fate. Not worth - // checking for error returns setting this thread's privileges. - (void)setgid(AID_SYSTEM); - (void)setuid(AID_SYSTEM); + cap_t caps = cap_init(); + (void)cap_clear(caps); + (void)cap_set_proc(caps); + (void)cap_free(caps); + + // If we are AID_ROOT, we should drop to AID_LOGD+AID_SYSTEM, if we are + // anything else, we have even lesser privileges and accept our fate. Not + // worth checking for error returns setting this thread's privileges. + (void)setgid(AID_SYSTEM); // readonly access to /data/system/packages.list + (void)setuid(AID_LOGD); // access to everything logd. while (reinit_running && !sem_wait(&reinit) && reinit_running) { @@ -311,6 +362,39 @@ static void readDmesg(LogAudit *al, LogKlog *kl) { } } +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("logd", + ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_STREAM)); + if (sock < 0) return -errno; + + static const char reinitStr[] = "reinit"; + ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinitStr, sizeof(reinitStr))); + if (ret < 0) return -errno; + + struct pollfd p; + memset(&p, 0, sizeof(p)); + p.fd = sock; + p.events = POLLIN; + ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000)); + if (ret < 0) return -errno; + if ((ret == 0) || !(p.revents & POLLIN)) return -ETIME; + + static const char success[] = "success"; + char buffer[sizeof(success) - 1]; + memset(buffer, 0, sizeof(buffer)); + ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); + if (ret < 0) return -errno; + + return strncmp(buffer, success, sizeof(success) - 1) != 0; +} + // Foreground waits for exit of the main persistent threads // that are started here. The threads are created to manage // UNIX domain client sockets for writing, reading and @@ -318,6 +402,17 @@ static void readDmesg(LogAudit *al, LogKlog *kl) { // logging plugins like auditd and restart control. Additional // transitory per-client threads are created for each reader. int main(int argc, char *argv[]) { + // issue reinit command. KISS argument parsing. + if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { + return issueReinit(); + } + + static const char dev_kmsg[] = "/dev/kmsg"; + fdDmesg = android_get_control_file(dev_kmsg); + if (fdDmesg < 0) { + fdDmesg = TEMP_FAILURE_RETRY(open(dev_kmsg, O_WRONLY | O_CLOEXEC)); + } + int fdPmesg = -1; bool klogd = __android_logger_property_get_bool("logd.kernel", BOOL_DEFAULT_TRUE | @@ -325,43 +420,13 @@ int main(int argc, char *argv[]) { BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE); if (klogd) { - fdPmesg = open("/proc/kmsg", O_RDONLY | O_NDELAY); - } - fdDmesg = open("/dev/kmsg", O_WRONLY); - - // issue reinit command. KISS argument parsing. - if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { - int sock = TEMP_FAILURE_RETRY( - socket_local_client("logd", - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_STREAM)); - if (sock < 0) { - return -errno; + static const char proc_kmsg[] = "/proc/kmsg"; + fdPmesg = android_get_control_file(proc_kmsg); + if (fdPmesg < 0) { + fdPmesg = TEMP_FAILURE_RETRY(open(proc_kmsg, + O_RDONLY | O_NDELAY | O_CLOEXEC)); } - static const char reinit[] = "reinit"; - ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinit, sizeof(reinit))); - if (ret < 0) { - return -errno; - } - struct pollfd p; - memset(&p, 0, sizeof(p)); - p.fd = sock; - p.events = POLLIN; - ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000)); - if (ret < 0) { - return -errno; - } - if ((ret == 0) || !(p.revents & POLLIN)) { - return -ETIME; - } - static const char success[] = "success"; - char buffer[sizeof(success) - 1]; - memset(buffer, 0, sizeof(buffer)); - ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); - if (ret < 0) { - return -errno; - } - return strncmp(buffer, success, sizeof(success) - 1) != 0; + if (fdPmesg < 0) android::prdebug("Failed to open %s\n", proc_kmsg); } // Reinit Thread @@ -386,7 +451,10 @@ int main(int argc, char *argv[]) { pthread_attr_destroy(&attr); } - if (drop_privs() != 0) { + bool auditd = __android_logger_property_get_bool("logd.auditd", + BOOL_DEFAULT_TRUE | + BOOL_DEFAULT_FLAG_PERSIST); + if (drop_privs(klogd, auditd) != 0) { return -1; } @@ -441,9 +509,6 @@ int main(int argc, char *argv[]) { // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients. - bool auditd = __android_logger_property_get_bool("logd.auditd", - BOOL_DEFAULT_TRUE | - BOOL_DEFAULT_FLAG_PERSIST); LogAudit *al = NULL; if (auditd) { al = new LogAudit(logBuf, reader, |
