• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android-base/macros.h>
39 #include <cutils/android_get_control_file.h>
40 #include <cutils/properties.h>
41 #include <cutils/sockets.h>
42 #include <log/event_tag_map.h>
43 #include <packagelistparser/packagelistparser.h>
44 #include <private/android_filesystem_config.h>
45 #include <private/android_logger.h>
46 #include <processgroup/sched_policy.h>
47 #include <utils/threads.h>
48 
49 #include "CommandListener.h"
50 #include "LogAudit.h"
51 #include "LogBuffer.h"
52 #include "LogKlog.h"
53 #include "LogListener.h"
54 #include "LogUtils.h"
55 
56 #define KMSG_PRIORITY(PRI)                                 \
57     '<', '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
58         '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, '>'
59 
60 //
61 // The service is designed to be run by init, it does not respond well
62 // to starting up manually. When starting up manually the sockets will
63 // fail to open typically for one of the following reasons:
64 //     EADDRINUSE if logger is running.
65 //     EACCESS if started without precautions (below)
66 //
67 // Here is a cookbook procedure for starting up logd manually assuming
68 // init is out of the way, pedantically all permissions and SELinux
69 // security is put back in place:
70 //
71 //    setenforce 0
72 //    rm /dev/socket/logd*
73 //    chmod 777 /dev/socket
74 //        # here is where you would attach the debugger or valgrind for example
75 //    runcon u:r:logd:s0 /system/bin/logd </dev/null >/dev/null 2>&1 &
76 //    sleep 1
77 //    chmod 755 /dev/socket
78 //    chown logd.logd /dev/socket/logd*
79 //    restorecon /dev/socket/logd*
80 //    setenforce 1
81 //
82 // If minimalism prevails, typical for debugging and security is not a concern:
83 //
84 //    setenforce 0
85 //    chmod 777 /dev/socket
86 //    logd
87 //
88 
drop_privs(bool klogd,bool auditd)89 static int drop_privs(bool klogd, bool auditd) {
90     sched_param param = {};
91 
92     if (set_sched_policy(0, SP_BACKGROUND) < 0) {
93         android::prdebug("failed to set background scheduling policy");
94         return -1;
95     }
96 
97     if (sched_setscheduler((pid_t)0, SCHED_BATCH, &param) < 0) {
98         android::prdebug("failed to set batch scheduler");
99         return -1;
100     }
101 
102     if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
103         android::prdebug("failed to set background cgroup");
104         return -1;
105     }
106 
107     if (!__android_logger_property_get_bool("ro.debuggable",
108                                             BOOL_DEFAULT_FALSE) &&
109         prctl(PR_SET_DUMPABLE, 0) == -1) {
110         android::prdebug("failed to clear PR_SET_DUMPABLE");
111         return -1;
112     }
113 
114     std::unique_ptr<struct _cap_struct, int (*)(void*)> caps(cap_init(),
115                                                              cap_free);
116     if (cap_clear(caps.get()) < 0) return -1;
117     cap_value_t cap_value[] = { CAP_SETGID,  // must be first for below
118                                 klogd ? CAP_SYSLOG : CAP_SETGID,
119                                 auditd ? CAP_AUDIT_CONTROL : CAP_SETGID };
120     if (cap_set_flag(caps.get(), CAP_PERMITTED, arraysize(cap_value), cap_value,
121                      CAP_SET) < 0) {
122         return -1;
123     }
124     if (cap_set_flag(caps.get(), CAP_EFFECTIVE, arraysize(cap_value), cap_value,
125                      CAP_SET) < 0) {
126         return -1;
127     }
128     if (cap_set_proc(caps.get()) < 0) {
129         android::prdebug(
130             "failed to set CAP_SETGID, CAP_SYSLOG or CAP_AUDIT_CONTROL (%d)",
131             errno);
132         return -1;
133     }
134 
135     gid_t groups[] = { AID_READPROC };
136 
137     if (setgroups(arraysize(groups), groups) == -1) {
138         android::prdebug("failed to set AID_READPROC groups");
139         return -1;
140     }
141 
142     if (setgid(AID_LOGD) != 0) {
143         android::prdebug("failed to set AID_LOGD gid");
144         return -1;
145     }
146 
147     if (setuid(AID_LOGD) != 0) {
148         android::prdebug("failed to set AID_LOGD uid");
149         return -1;
150     }
151 
152     if (cap_set_flag(caps.get(), CAP_PERMITTED, 1, cap_value, CAP_CLEAR) < 0) {
153         return -1;
154     }
155     if (cap_set_flag(caps.get(), CAP_EFFECTIVE, 1, cap_value, CAP_CLEAR) < 0) {
156         return -1;
157     }
158     if (cap_set_proc(caps.get()) < 0) {
159         android::prdebug("failed to clear CAP_SETGID (%d)", errno);
160         return -1;
161     }
162 
163     return 0;
164 }
165 
166 // Property helper
check_flag(const char * prop,const char * flag)167 static bool check_flag(const char* prop, const char* flag) {
168     const char* cp = strcasestr(prop, flag);
169     if (!cp) {
170         return false;
171     }
172     // We only will document comma (,)
173     static const char sep[] = ",:;|+ \t\f";
174     if ((cp != prop) && !strchr(sep, cp[-1])) {
175         return false;
176     }
177     cp += strlen(flag);
178     return !*cp || !!strchr(sep, *cp);
179 }
180 
181 static int fdDmesg = -1;
prdebug(const char * fmt,...)182 void android::prdebug(const char* fmt, ...) {
183     if (fdDmesg < 0) {
184         return;
185     }
186 
187     static const char message[] = {
188         KMSG_PRIORITY(LOG_DEBUG), 'l', 'o', 'g', 'd', ':', ' '
189     };
190     char buffer[256];
191     memcpy(buffer, message, sizeof(message));
192 
193     va_list ap;
194     va_start(ap, fmt);
195     int n = vsnprintf(buffer + sizeof(message),
196                       sizeof(buffer) - sizeof(message), fmt, ap);
197     va_end(ap);
198     if (n > 0) {
199         buffer[sizeof(buffer) - 1] = '\0';
200         if (!strchr(buffer, '\n')) {
201             buffer[sizeof(buffer) - 2] = '\0';
202             strlcat(buffer, "\n", sizeof(buffer));
203         }
204         write(fdDmesg, buffer, strlen(buffer));
205     }
206 }
207 
208 static sem_t uidName;
209 static uid_t uid;
210 static char* name;
211 
212 static sem_t reinit;
213 static bool reinit_running = false;
214 static LogBuffer* logBuf = nullptr;
215 
package_list_parser_cb(pkg_info * info,void *)216 static bool package_list_parser_cb(pkg_info* info, void* /* userdata */) {
217     bool rc = true;
218     if (info->uid == uid) {
219         name = strdup(info->name);
220         // false to stop processing
221         rc = false;
222     }
223 
224     packagelist_free(info);
225     return rc;
226 }
227 
reinit_thread_start(void *)228 static void* reinit_thread_start(void* /*obj*/) {
229     prctl(PR_SET_NAME, "logd.daemon");
230     set_sched_policy(0, SP_BACKGROUND);
231     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);
232 
233     // We should drop to AID_LOGD, if we are anything else, we have
234     // even lesser privileges and accept our fate.
235     gid_t groups[] = {
236         AID_SYSTEM,        // search access to /data/system path
237         AID_PACKAGE_INFO,  // readonly access to /data/system/packages.list
238     };
239     if (setgroups(arraysize(groups), groups) == -1) {
240         android::prdebug(
241             "logd.daemon: failed to set AID_SYSTEM AID_PACKAGE_INFO groups");
242     }
243     if (setgid(AID_LOGD) != 0) {
244         android::prdebug("logd.daemon: failed to set AID_LOGD gid");
245     }
246     if (setuid(AID_LOGD) != 0) {
247         android::prdebug("logd.daemon: failed to set AID_LOGD uid");
248     }
249 
250     cap_t caps = cap_init();
251     (void)cap_clear(caps);
252     (void)cap_set_proc(caps);
253     (void)cap_free(caps);
254 
255     while (reinit_running && !sem_wait(&reinit) && reinit_running) {
256         // uidToName Privileged Worker
257         if (uid) {
258             name = nullptr;
259 
260             // if we got the perms wrong above, this would spam if we reported
261             // problems with acquisition of an uid name from the packages.
262             (void)packagelist_parse(package_list_parser_cb, nullptr);
263 
264             uid = 0;
265             sem_post(&uidName);
266             continue;
267         }
268 
269         if (fdDmesg >= 0) {
270             static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
271                                                    'l',
272                                                    'o',
273                                                    'g',
274                                                    'd',
275                                                    '.',
276                                                    'd',
277                                                    'a',
278                                                    'e',
279                                                    'm',
280                                                    'o',
281                                                    'n',
282                                                    ':',
283                                                    ' ',
284                                                    'r',
285                                                    'e',
286                                                    'i',
287                                                    'n',
288                                                    'i',
289                                                    't',
290                                                    '\n' };
291             write(fdDmesg, reinit_message, sizeof(reinit_message));
292         }
293 
294         // Anything that reads persist.<property>
295         if (logBuf) {
296             logBuf->init();
297             logBuf->initPrune(nullptr);
298         }
299         android::ReReadEventLogTags();
300     }
301 
302     return nullptr;
303 }
304 
305 static sem_t sem_name;
306 
uidToName(uid_t u)307 char* android::uidToName(uid_t u) {
308     if (!u || !reinit_running) {
309         return nullptr;
310     }
311 
312     sem_wait(&sem_name);
313 
314     // Not multi-thread safe, we use sem_name to protect
315     uid = u;
316 
317     name = nullptr;
318     sem_post(&reinit);
319     sem_wait(&uidName);
320     char* ret = name;
321 
322     sem_post(&sem_name);
323 
324     return ret;
325 }
326 
327 // Serves as a global method to trigger reinitialization
328 // and as a function that can be provided to signal().
reinit_signal_handler(int)329 void reinit_signal_handler(int /*signal*/) {
330     sem_post(&reinit);
331 }
332 
readDmesg(LogAudit * al,LogKlog * kl)333 static void readDmesg(LogAudit* al, LogKlog* kl) {
334     if (!al && !kl) {
335         return;
336     }
337 
338     int rc = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
339     if (rc <= 0) {
340         return;
341     }
342 
343     // Margin for additional input race or trailing nul
344     ssize_t len = rc + 1024;
345     std::unique_ptr<char[]> buf(new char[len]);
346 
347     rc = klogctl(KLOG_READ_ALL, buf.get(), len);
348     if (rc <= 0) {
349         return;
350     }
351 
352     if (rc < len) {
353         len = rc + 1;
354     }
355     buf[--len] = '\0';
356 
357     if (kl && kl->isMonotonic()) {
358         kl->synchronize(buf.get(), len);
359     }
360 
361     ssize_t sublen;
362     for (char *ptr = nullptr, *tok = buf.get();
363          (rc >= 0) && !!(tok = android::log_strntok_r(tok, len, ptr, sublen));
364          tok = nullptr) {
365         if ((sublen <= 0) || !*tok) continue;
366         if (al) {
367             rc = al->log(tok, sublen);
368         }
369         if (kl) {
370             rc = kl->log(tok, sublen);
371         }
372     }
373 }
374 
issueReinit()375 static int issueReinit() {
376     cap_t caps = cap_init();
377     (void)cap_clear(caps);
378     (void)cap_set_proc(caps);
379     (void)cap_free(caps);
380 
381     int sock = TEMP_FAILURE_RETRY(socket_local_client(
382         "logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM));
383     if (sock < 0) return -errno;
384 
385     static const char reinitStr[] = "reinit";
386     ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinitStr, sizeof(reinitStr)));
387     if (ret < 0) return -errno;
388 
389     struct pollfd p;
390     memset(&p, 0, sizeof(p));
391     p.fd = sock;
392     p.events = POLLIN;
393     ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000));
394     if (ret < 0) return -errno;
395     if ((ret == 0) || !(p.revents & POLLIN)) return -ETIME;
396 
397     static const char success[] = "success";
398     char buffer[sizeof(success) - 1];
399     memset(buffer, 0, sizeof(buffer));
400     ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer)));
401     if (ret < 0) return -errno;
402 
403     return strncmp(buffer, success, sizeof(success) - 1) != 0;
404 }
405 
406 // Foreground waits for exit of the main persistent threads
407 // that are started here. The threads are created to manage
408 // UNIX domain client sockets for writing, reading and
409 // controlling the user space logger, and for any additional
410 // logging plugins like auditd and restart control. Additional
411 // transitory per-client threads are created for each reader.
main(int argc,char * argv[])412 int main(int argc, char* argv[]) {
413     // logd is written under the assumption that the timezone is UTC.
414     // If TZ is not set, persist.sys.timezone is looked up in some time utility
415     // libc functions, including mktime. It confuses the logd time handling,
416     // so here explicitly set TZ to UTC, which overrides the property.
417     setenv("TZ", "UTC", 1);
418     // issue reinit command. KISS argument parsing.
419     if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) {
420         return issueReinit();
421     }
422 
423     static const char dev_kmsg[] = "/dev/kmsg";
424     fdDmesg = android_get_control_file(dev_kmsg);
425     if (fdDmesg < 0) {
426         fdDmesg = TEMP_FAILURE_RETRY(open(dev_kmsg, O_WRONLY | O_CLOEXEC));
427     }
428 
429     int fdPmesg = -1;
430     bool klogd = __android_logger_property_get_bool(
431         "ro.logd.kernel",
432         BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
433     if (klogd) {
434         static const char proc_kmsg[] = "/proc/kmsg";
435         fdPmesg = android_get_control_file(proc_kmsg);
436         if (fdPmesg < 0) {
437             fdPmesg = TEMP_FAILURE_RETRY(
438                 open(proc_kmsg, O_RDONLY | O_NDELAY | O_CLOEXEC));
439         }
440         if (fdPmesg < 0) android::prdebug("Failed to open %s\n", proc_kmsg);
441     }
442 
443     // Reinit Thread
444     sem_init(&reinit, 0, 0);
445     sem_init(&uidName, 0, 0);
446     sem_init(&sem_name, 0, 1);
447     pthread_attr_t attr;
448     if (!pthread_attr_init(&attr)) {
449         struct sched_param param;
450 
451         memset(&param, 0, sizeof(param));
452         pthread_attr_setschedparam(&attr, &param);
453         pthread_attr_setschedpolicy(&attr, SCHED_BATCH);
454         if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
455             pthread_t thread;
456             reinit_running = true;
457             if (pthread_create(&thread, &attr, reinit_thread_start, nullptr)) {
458                 reinit_running = false;
459             }
460         }
461         pthread_attr_destroy(&attr);
462     }
463 
464     bool auditd =
465         __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE);
466     if (drop_privs(klogd, auditd) != 0) {
467         return EXIT_FAILURE;
468     }
469 
470     // Serves the purpose of managing the last logs times read on a
471     // socket connection, and as a reader lock on a range of log
472     // entries.
473 
474     LastLogTimes* times = new LastLogTimes();
475 
476     // LogBuffer is the object which is responsible for holding all
477     // log entries.
478 
479     logBuf = new LogBuffer(times);
480 
481     signal(SIGHUP, reinit_signal_handler);
482 
483     if (__android_logger_property_get_bool(
484             "logd.statistics", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_PERSIST |
485                                    BOOL_DEFAULT_FLAG_ENG |
486                                    BOOL_DEFAULT_FLAG_SVELTE)) {
487         logBuf->enableStatistics();
488     }
489 
490     // LogReader listens on /dev/socket/logdr. When a client
491     // connects, log entries in the LogBuffer are written to the client.
492 
493     LogReader* reader = new LogReader(logBuf);
494     if (reader->startListener()) {
495         return EXIT_FAILURE;
496     }
497 
498     // LogListener listens on /dev/socket/logdw for client
499     // initiated log messages. New log entries are added to LogBuffer
500     // and LogReader is notified to send updates to connected clients.
501 
502     LogListener* swl = new LogListener(logBuf, reader);
503     // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
504     if (swl->startListener(600)) {
505         return EXIT_FAILURE;
506     }
507 
508     // Command listener listens on /dev/socket/logd for incoming logd
509     // administrative commands.
510 
511     CommandListener* cl = new CommandListener(logBuf, reader, swl);
512     if (cl->startListener()) {
513         return EXIT_FAILURE;
514     }
515 
516     // LogAudit listens on NETLINK_AUDIT socket for selinux
517     // initiated log messages. New log entries are added to LogBuffer
518     // and LogReader is notified to send updates to connected clients.
519 
520     LogAudit* al = nullptr;
521     if (auditd) {
522         al = new LogAudit(logBuf, reader,
523                           __android_logger_property_get_bool(
524                               "ro.logd.auditd.dmesg", BOOL_DEFAULT_TRUE)
525                               ? fdDmesg
526                               : -1);
527     }
528 
529     LogKlog* kl = nullptr;
530     if (klogd) {
531         kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != nullptr);
532     }
533 
534     readDmesg(al, kl);
535 
536     // failure is an option ... messages are in dmesg (required by standard)
537 
538     if (kl && kl->startListener()) {
539         delete kl;
540     }
541 
542     if (al && al->startListener()) {
543         delete al;
544     }
545 
546     TEMP_FAILURE_RETRY(pause());
547 
548     return EXIT_SUCCESS;
549 }
550