Home | History | Annotate | Download | only in logd
      1 /*
      2  * Copyright (C) 2012-2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <dirent.h>
     18 #include <errno.h>
     19 #include <fcntl.h>
     20 #include <poll.h>
     21 #include <sched.h>
     22 #include <semaphore.h>
     23 #include <signal.h>
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <sys/capability.h>
     28 #include <sys/klog.h>
     29 #include <sys/prctl.h>
     30 #include <sys/resource.h>
     31 #include <sys/stat.h>
     32 #include <sys/types.h>
     33 #include <syslog.h>
     34 #include <unistd.h>
     35 
     36 #include <memory>
     37 
     38 #include <cutils/properties.h>
     39 #include <cutils/sched_policy.h>
     40 #include <cutils/sockets.h>
     41 #include <log/event_tag_map.h>
     42 #include <private/android_filesystem_config.h>
     43 #include <utils/threads.h>
     44 
     45 #include "CommandListener.h"
     46 #include "LogBuffer.h"
     47 #include "LogListener.h"
     48 #include "LogAudit.h"
     49 #include "LogKlog.h"
     50 
     51 #define KMSG_PRIORITY(PRI)                            \
     52     '<',                                              \
     53     '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
     54     '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, \
     55     '>'
     56 
     57 //
     58 //  The service is designed to be run by init, it does not respond well
     59 // to starting up manually. When starting up manually the sockets will
     60 // fail to open typically for one of the following reasons:
     61 //     EADDRINUSE if logger is running.
     62 //     EACCESS if started without precautions (below)
     63 //
     64 // Here is a cookbook procedure for starting up logd manually assuming
     65 // init is out of the way, pedantically all permissions and selinux
     66 // security is put back in place:
     67 //
     68 //    setenforce 0
     69 //    rm /dev/socket/logd*
     70 //    chmod 777 /dev/socket
     71 //        # here is where you would attach the debugger or valgrind for example
     72 //    runcon u:r:logd:s0 /system/bin/logd </dev/null >/dev/null 2>&1 &
     73 //    sleep 1
     74 //    chmod 755 /dev/socket
     75 //    chown logd.logd /dev/socket/logd*
     76 //    restorecon /dev/socket/logd*
     77 //    setenforce 1
     78 //
     79 // If minimalism prevails, typical for debugging and security is not a concern:
     80 //
     81 //    setenforce 0
     82 //    chmod 777 /dev/socket
     83 //    logd
     84 //
     85 
     86 static int drop_privs() {
     87     struct sched_param param;
     88     memset(&param, 0, sizeof(param));
     89 
     90     if (set_sched_policy(0, SP_BACKGROUND) < 0) {
     91         return -1;
     92     }
     93 
     94     if (sched_setscheduler((pid_t) 0, SCHED_BATCH, &param) < 0) {
     95         return -1;
     96     }
     97 
     98     if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
     99         return -1;
    100     }
    101 
    102     if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
    103         return -1;
    104     }
    105 
    106     if (setgroups(0, NULL) == -1) {
    107         return -1;
    108     }
    109 
    110     if (setgid(AID_LOGD) != 0) {
    111         return -1;
    112     }
    113 
    114     if (setuid(AID_LOGD) != 0) {
    115         return -1;
    116     }
    117 
    118     struct __user_cap_header_struct capheader;
    119     struct __user_cap_data_struct capdata[2];
    120     memset(&capheader, 0, sizeof(capheader));
    121     memset(&capdata, 0, sizeof(capdata));
    122     capheader.version = _LINUX_CAPABILITY_VERSION_3;
    123     capheader.pid = 0;
    124 
    125     capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
    126     capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL);
    127 
    128     capdata[0].effective = capdata[0].permitted;
    129     capdata[1].effective = capdata[1].permitted;
    130     capdata[0].inheritable = 0;
    131     capdata[1].inheritable = 0;
    132 
    133     if (capset(&capheader, &capdata[0]) < 0) {
    134         return -1;
    135     }
    136 
    137     return 0;
    138 }
    139 
    140 // Property helper
    141 static bool property_get_bool(const char *key, bool def) {
    142     char property[PROPERTY_VALUE_MAX];
    143     property_get(key, property, "");
    144 
    145     if (!strcasecmp(property, "true")) {
    146         return true;
    147     }
    148     if (!strcasecmp(property, "false")) {
    149         return false;
    150     }
    151 
    152     return def;
    153 }
    154 
    155 // Remove the static, and use this variable
    156 // globally for debugging if necessary. eg:
    157 //   write(fdDmesg, "I am here\n", 10);
    158 static int fdDmesg = -1;
    159 
    160 static sem_t uidName;
    161 static uid_t uid;
    162 static char *name;
    163 
    164 static sem_t reinit;
    165 static bool reinit_running = false;
    166 static LogBuffer *logBuf = NULL;
    167 
    168 static void *reinit_thread_start(void * /*obj*/) {
    169     prctl(PR_SET_NAME, "logd.daemon");
    170     set_sched_policy(0, SP_BACKGROUND);
    171     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);
    172 
    173     setgid(AID_SYSTEM);
    174     setuid(AID_SYSTEM);
    175 
    176     while (reinit_running && !sem_wait(&reinit) && reinit_running) {
    177 
    178         // uidToName Privileged Worker
    179         if (uid) {
    180             name = NULL;
    181 
    182             FILE *fp = fopen("/data/system/packages.list", "r");
    183             if (fp) {
    184                 // This simple parser is sensitive to format changes in
    185                 // frameworks/base/services/core/java/com/android/server/pm/Settings.java
    186                 // A dependency note has been added to that file to correct
    187                 // this parser.
    188 
    189                 char *buffer = NULL;
    190                 size_t len;
    191                 while (getline(&buffer, &len, fp) > 0) {
    192                     char *userId = strchr(buffer, ' ');
    193                     if (!userId) {
    194                         continue;
    195                     }
    196                     *userId = '\0';
    197                     unsigned long value = strtoul(userId + 1, NULL, 10);
    198                     if (value != uid) {
    199                         continue;
    200                     }
    201                     name = strdup(buffer);
    202                     break;
    203                 }
    204                 free(buffer);
    205                 fclose(fp);
    206             }
    207             uid = 0;
    208             sem_post(&uidName);
    209             continue;
    210         }
    211 
    212         if (fdDmesg >= 0) {
    213             static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
    214                 'l', 'o', 'g', 'd', '.', 'd', 'a', 'e', 'm', 'o', 'n', ':',
    215                 ' ', 'r', 'e', 'i', 'n', 'i', 't', '\n' };
    216             write(fdDmesg, reinit_message, sizeof(reinit_message));
    217         }
    218 
    219         // Anything that reads persist.<property>
    220         if (logBuf) {
    221             logBuf->init();
    222         }
    223     }
    224 
    225     return NULL;
    226 }
    227 
    228 static sem_t sem_name;
    229 
    230 char *android::uidToName(uid_t u) {
    231     if (!u || !reinit_running) {
    232         return NULL;
    233     }
    234 
    235     sem_wait(&sem_name);
    236 
    237     // Not multi-thread safe, we use sem_name to protect
    238     uid = u;
    239 
    240     name = NULL;
    241     sem_post(&reinit);
    242     sem_wait(&uidName);
    243     char *ret = name;
    244 
    245     sem_post(&sem_name);
    246 
    247     return ret;
    248 }
    249 
    250 // Serves as a global method to trigger reinitialization
    251 // and as a function that can be provided to signal().
    252 void reinit_signal_handler(int /*signal*/) {
    253     sem_post(&reinit);
    254 }
    255 
    256 // tagToName converts an events tag into a name
    257 const char *android::tagToName(uint32_t tag) {
    258     static const EventTagMap *map;
    259 
    260     if (!map) {
    261         sem_wait(&sem_name);
    262         if (!map) {
    263             map = android_openEventTagMap(EVENT_TAG_MAP_FILE);
    264         }
    265         sem_post(&sem_name);
    266         if (!map) {
    267             return NULL;
    268         }
    269     }
    270     return android_lookupEventTag(map, tag);
    271 }
    272 
    273 static bool property_get_bool_svelte(const char *key) {
    274     bool not_user;
    275     {
    276         char property[PROPERTY_VALUE_MAX];
    277         property_get("ro.build.type", property, "");
    278         not_user = !!strcmp(property, "user");
    279     }
    280     return property_get_bool(key, not_user
    281             && !property_get_bool("ro.config.low_ram", false));
    282 }
    283 
    284 static void readDmesg(LogAudit *al, LogKlog *kl) {
    285     if (!al && !kl) {
    286         return;
    287     }
    288 
    289     int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
    290     if (len <= 0) {
    291         return;
    292     }
    293 
    294     len += 1024; // Margin for additional input race or trailing nul
    295     std::unique_ptr<char []> buf(new char[len]);
    296 
    297     int rc = klogctl(KLOG_READ_ALL, buf.get(), len);
    298     if (rc <= 0) {
    299         return;
    300     }
    301 
    302     if (rc < len) {
    303         len = rc + 1;
    304     }
    305     buf[len - 1] = '\0';
    306 
    307     if (kl) {
    308         kl->synchronize(buf.get());
    309     }
    310 
    311     for (char *ptr = NULL, *tok = buf.get();
    312          (rc >= 0) && ((tok = log_strtok_r(tok, &ptr)));
    313          tok = NULL) {
    314         if (al) {
    315             rc = al->log(tok);
    316         }
    317         if (kl) {
    318             rc = kl->log(tok);
    319         }
    320     }
    321 }
    322 
    323 // Foreground waits for exit of the main persistent threads
    324 // that are started here. The threads are created to manage
    325 // UNIX domain client sockets for writing, reading and
    326 // controlling the user space logger, and for any additional
    327 // logging plugins like auditd and restart control. Additional
    328 // transitory per-client threads are created for each reader.
    329 int main(int argc, char *argv[]) {
    330     int fdPmesg = -1;
    331     bool klogd = property_get_bool_svelte("logd.klogd");
    332     if (klogd) {
    333         fdPmesg = open("/proc/kmsg", O_RDONLY | O_NDELAY);
    334     }
    335     fdDmesg = open("/dev/kmsg", O_WRONLY);
    336 
    337     // issue reinit command. KISS argument parsing.
    338     if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) {
    339         int sock = TEMP_FAILURE_RETRY(
    340             socket_local_client("logd",
    341                                 ANDROID_SOCKET_NAMESPACE_RESERVED,
    342                                 SOCK_STREAM));
    343         if (sock < 0) {
    344             return -errno;
    345         }
    346         static const char reinit[] = "reinit";
    347         ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinit, sizeof(reinit)));
    348         if (ret < 0) {
    349             return -errno;
    350         }
    351         struct pollfd p;
    352         memset(&p, 0, sizeof(p));
    353         p.fd = sock;
    354         p.events = POLLIN;
    355         ret = TEMP_FAILURE_RETRY(poll(&p, 1, 100));
    356         if (ret < 0) {
    357             return -errno;
    358         }
    359         if ((ret == 0) || !(p.revents & POLLIN)) {
    360             return -ETIME;
    361         }
    362         static const char success[] = "success";
    363         char buffer[sizeof(success) - 1];
    364         memset(buffer, 0, sizeof(buffer));
    365         ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer)));
    366         if (ret < 0) {
    367             return -errno;
    368         }
    369         return strncmp(buffer, success, sizeof(success) - 1) != 0;
    370     }
    371 
    372     // Reinit Thread
    373     sem_init(&reinit, 0, 0);
    374     sem_init(&uidName, 0, 0);
    375     sem_init(&sem_name, 0, 1);
    376     pthread_attr_t attr;
    377     if (!pthread_attr_init(&attr)) {
    378         struct sched_param param;
    379 
    380         memset(&param, 0, sizeof(param));
    381         pthread_attr_setschedparam(&attr, &param);
    382         pthread_attr_setschedpolicy(&attr, SCHED_BATCH);
    383         if (!pthread_attr_setdetachstate(&attr,
    384                                          PTHREAD_CREATE_DETACHED)) {
    385             pthread_t thread;
    386             reinit_running = true;
    387             if (pthread_create(&thread, &attr, reinit_thread_start, NULL)) {
    388                 reinit_running = false;
    389             }
    390         }
    391         pthread_attr_destroy(&attr);
    392     }
    393 
    394     if (drop_privs() != 0) {
    395         return -1;
    396     }
    397 
    398     // Serves the purpose of managing the last logs times read on a
    399     // socket connection, and as a reader lock on a range of log
    400     // entries.
    401 
    402     LastLogTimes *times = new LastLogTimes();
    403 
    404     // LogBuffer is the object which is responsible for holding all
    405     // log entries.
    406 
    407     logBuf = new LogBuffer(times);
    408 
    409     signal(SIGHUP, reinit_signal_handler);
    410 
    411     if (property_get_bool_svelte("logd.statistics")) {
    412         logBuf->enableStatistics();
    413     }
    414 
    415     // LogReader listens on /dev/socket/logdr. When a client
    416     // connects, log entries in the LogBuffer are written to the client.
    417 
    418     LogReader *reader = new LogReader(logBuf);
    419     if (reader->startListener()) {
    420         exit(1);
    421     }
    422 
    423     // LogListener listens on /dev/socket/logdw for client
    424     // initiated log messages. New log entries are added to LogBuffer
    425     // and LogReader is notified to send updates to connected clients.
    426 
    427     LogListener *swl = new LogListener(logBuf, reader);
    428     // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
    429     if (swl->startListener(300)) {
    430         exit(1);
    431     }
    432 
    433     // Command listener listens on /dev/socket/logd for incoming logd
    434     // administrative commands.
    435 
    436     CommandListener *cl = new CommandListener(logBuf, reader, swl);
    437     if (cl->startListener()) {
    438         exit(1);
    439     }
    440 
    441     // LogAudit listens on NETLINK_AUDIT socket for selinux
    442     // initiated log messages. New log entries are added to LogBuffer
    443     // and LogReader is notified to send updates to connected clients.
    444 
    445     bool auditd = property_get_bool("logd.auditd", true);
    446 
    447     LogAudit *al = NULL;
    448     if (auditd) {
    449         bool dmesg = property_get_bool("logd.auditd.dmesg", true);
    450         al = new LogAudit(logBuf, reader, dmesg ? fdDmesg : -1);
    451     }
    452 
    453     LogKlog *kl = NULL;
    454     if (klogd) {
    455         kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != NULL);
    456     }
    457 
    458     readDmesg(al, kl);
    459 
    460     // failure is an option ... messages are in dmesg (required by standard)
    461 
    462     if (kl && kl->startListener()) {
    463         delete kl;
    464     }
    465 
    466     if (al && al->startListener()) {
    467         delete al;
    468     }
    469 
    470     TEMP_FAILURE_RETRY(pause());
    471 
    472     exit(0);
    473 }
    474