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 <cstdbool> 37 #include <memory> 38 39 #include <cutils/properties.h> 40 #include <cutils/sched_policy.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 <utils/threads.h> 46 47 #include "CommandListener.h" 48 #include "LogBuffer.h" 49 #include "LogListener.h" 50 #include "LogAudit.h" 51 #include "LogKlog.h" 52 #include "LogUtils.h" 53 54 #define KMSG_PRIORITY(PRI) \ 55 '<', \ 56 '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \ 57 '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, \ 58 '>' 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 89 static int drop_privs() { 90 struct sched_param param; 91 memset(¶m, 0, sizeof(param)); 92 93 if (set_sched_policy(0, SP_BACKGROUND) < 0) { 94 return -1; 95 } 96 97 if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) { 98 return -1; 99 } 100 101 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) { 102 return -1; 103 } 104 105 if (prctl(PR_SET_KEEPCAPS, 1) < 0) { 106 return -1; 107 } 108 109 gid_t groups[] = { AID_READPROC }; 110 111 if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) == -1) { 112 return -1; 113 } 114 115 if (setgid(AID_LOGD) != 0) { 116 return -1; 117 } 118 119 if (setuid(AID_LOGD) != 0) { 120 return -1; 121 } 122 123 struct __user_cap_header_struct capheader; 124 struct __user_cap_data_struct capdata[2]; 125 memset(&capheader, 0, sizeof(capheader)); 126 memset(&capdata, 0, sizeof(capdata)); 127 capheader.version = _LINUX_CAPABILITY_VERSION_3; 128 capheader.pid = 0; 129 130 capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG); 131 capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL); 132 133 capdata[0].effective = capdata[0].permitted; 134 capdata[1].effective = capdata[1].permitted; 135 capdata[0].inheritable = 0; 136 capdata[1].inheritable = 0; 137 138 if (capset(&capheader, &capdata[0]) < 0) { 139 return -1; 140 } 141 142 return 0; 143 } 144 145 // Property helper 146 static bool check_flag(const char *prop, const char *flag) { 147 const char *cp = strcasestr(prop, flag); 148 if (!cp) { 149 return false; 150 } 151 // We only will document comma (,) 152 static const char sep[] = ",:;|+ \t\f"; 153 if ((cp != prop) && !strchr(sep, cp[-1])) { 154 return false; 155 } 156 cp += strlen(flag); 157 return !*cp || !!strchr(sep, *cp); 158 } 159 160 bool property_get_bool(const char *key, int flag) { 161 char def[PROPERTY_VALUE_MAX]; 162 char property[PROPERTY_VALUE_MAX]; 163 def[0] = '\0'; 164 if (flag & BOOL_DEFAULT_FLAG_PERSIST) { 165 char newkey[PROPERTY_KEY_MAX]; 166 snprintf(newkey, sizeof(newkey), "ro.%s", key); 167 property_get(newkey, property, ""); 168 // persist properties set by /data require inoculation with 169 // logd-reinit. They may be set in init.rc early and function, but 170 // otherwise are defunct unless reset. Do not rely on persist 171 // properties for startup-only keys unless you are willing to restart 172 // logd daemon (not advised). 173 snprintf(newkey, sizeof(newkey), "persist.%s", key); 174 property_get(newkey, def, property); 175 } 176 177 property_get(key, property, def); 178 179 if (check_flag(property, "true")) { 180 return true; 181 } 182 if (check_flag(property, "false")) { 183 return false; 184 } 185 if (check_flag(property, "eng")) { 186 flag |= BOOL_DEFAULT_FLAG_ENG; 187 } 188 // this is really a "not" flag 189 if (check_flag(property, "svelte")) { 190 flag |= BOOL_DEFAULT_FLAG_SVELTE; 191 } 192 193 // Sanity Check 194 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) { 195 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE; 196 flag |= BOOL_DEFAULT_TRUE; 197 } 198 199 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) 200 && property_get_bool("ro.config.low_ram", 201 BOOL_DEFAULT_FALSE)) { 202 return false; 203 } 204 if (flag & BOOL_DEFAULT_FLAG_ENG) { 205 property_get("ro.build.type", property, ""); 206 if (!strcmp(property, "user")) { 207 return false; 208 } 209 } 210 211 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE; 212 } 213 214 // Remove the static, and use this variable 215 // globally for debugging if necessary. eg: 216 // write(fdDmesg, "I am here\n", 10); 217 static int fdDmesg = -1; 218 219 static sem_t uidName; 220 static uid_t uid; 221 static char *name; 222 223 static sem_t reinit; 224 static bool reinit_running = false; 225 static LogBuffer *logBuf = NULL; 226 227 static bool package_list_parser_cb(pkg_info *info, void * /* userdata */) { 228 229 bool rc = true; 230 if (info->uid == uid) { 231 name = strdup(info->name); 232 // false to stop processing 233 rc = false; 234 } 235 236 packagelist_free(info); 237 return rc; 238 } 239 240 static void *reinit_thread_start(void * /*obj*/) { 241 prctl(PR_SET_NAME, "logd.daemon"); 242 set_sched_policy(0, SP_BACKGROUND); 243 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND); 244 245 // If we are AID_ROOT, we should drop to AID_SYSTEM, if we are anything 246 // else, we have even lesser privileges and accept our fate. Not worth 247 // checking for error returns setting this thread's privileges. 248 (void)setgid(AID_SYSTEM); 249 (void)setuid(AID_SYSTEM); 250 251 while (reinit_running && !sem_wait(&reinit) && reinit_running) { 252 253 // uidToName Privileged Worker 254 if (uid) { 255 name = NULL; 256 257 packagelist_parse(package_list_parser_cb, NULL); 258 259 uid = 0; 260 sem_post(&uidName); 261 continue; 262 } 263 264 if (fdDmesg >= 0) { 265 static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO), 266 'l', 'o', 'g', 'd', '.', 'd', 'a', 'e', 'm', 'o', 'n', ':', 267 ' ', 'r', 'e', 'i', 'n', 'i', 't', '\n' }; 268 write(fdDmesg, reinit_message, sizeof(reinit_message)); 269 } 270 271 // Anything that reads persist.<property> 272 if (logBuf) { 273 logBuf->init(); 274 logBuf->initPrune(NULL); 275 } 276 } 277 278 return NULL; 279 } 280 281 static sem_t sem_name; 282 283 char *android::uidToName(uid_t u) { 284 if (!u || !reinit_running) { 285 return NULL; 286 } 287 288 sem_wait(&sem_name); 289 290 // Not multi-thread safe, we use sem_name to protect 291 uid = u; 292 293 name = NULL; 294 sem_post(&reinit); 295 sem_wait(&uidName); 296 char *ret = name; 297 298 sem_post(&sem_name); 299 300 return ret; 301 } 302 303 // Serves as a global method to trigger reinitialization 304 // and as a function that can be provided to signal(). 305 void reinit_signal_handler(int /*signal*/) { 306 sem_post(&reinit); 307 } 308 309 // tagToName converts an events tag into a name 310 const char *android::tagToName(uint32_t tag) { 311 static const EventTagMap *map; 312 313 if (!map) { 314 sem_wait(&sem_name); 315 if (!map) { 316 map = android_openEventTagMap(EVENT_TAG_MAP_FILE); 317 } 318 sem_post(&sem_name); 319 if (!map) { 320 return NULL; 321 } 322 } 323 return android_lookupEventTag(map, tag); 324 } 325 326 static void readDmesg(LogAudit *al, LogKlog *kl) { 327 if (!al && !kl) { 328 return; 329 } 330 331 int rc = klogctl(KLOG_SIZE_BUFFER, NULL, 0); 332 if (rc <= 0) { 333 return; 334 } 335 336 size_t len = rc + 1024; // Margin for additional input race or trailing nul 337 std::unique_ptr<char []> buf(new char[len]); 338 339 rc = klogctl(KLOG_READ_ALL, buf.get(), len); 340 if (rc <= 0) { 341 return; 342 } 343 344 if ((size_t)rc < len) { 345 len = rc + 1; 346 } 347 buf[--len] = '\0'; 348 349 if (kl && kl->isMonotonic()) { 350 kl->synchronize(buf.get(), len); 351 } 352 353 size_t sublen; 354 for (char *ptr = NULL, *tok = buf.get(); 355 (rc >= 0) && ((tok = log_strntok_r(tok, &len, &ptr, &sublen))); 356 tok = NULL) { 357 if (al) { 358 rc = al->log(tok, sublen); 359 } 360 if (kl) { 361 rc = kl->log(tok, sublen); 362 } 363 } 364 } 365 366 // Foreground waits for exit of the main persistent threads 367 // that are started here. The threads are created to manage 368 // UNIX domain client sockets for writing, reading and 369 // controlling the user space logger, and for any additional 370 // logging plugins like auditd and restart control. Additional 371 // transitory per-client threads are created for each reader. 372 int main(int argc, char *argv[]) { 373 int fdPmesg = -1; 374 bool klogd = property_get_bool("logd.kernel", 375 BOOL_DEFAULT_TRUE | 376 BOOL_DEFAULT_FLAG_PERSIST | 377 BOOL_DEFAULT_FLAG_ENG | 378 BOOL_DEFAULT_FLAG_SVELTE); 379 if (klogd) { 380 fdPmesg = open("/proc/kmsg", O_RDONLY | O_NDELAY); 381 } 382 fdDmesg = open("/dev/kmsg", O_WRONLY); 383 384 // issue reinit command. KISS argument parsing. 385 if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { 386 int sock = TEMP_FAILURE_RETRY( 387 socket_local_client("logd", 388 ANDROID_SOCKET_NAMESPACE_RESERVED, 389 SOCK_STREAM)); 390 if (sock < 0) { 391 return -errno; 392 } 393 static const char reinit[] = "reinit"; 394 ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinit, sizeof(reinit))); 395 if (ret < 0) { 396 return -errno; 397 } 398 struct pollfd p; 399 memset(&p, 0, sizeof(p)); 400 p.fd = sock; 401 p.events = POLLIN; 402 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000)); 403 if (ret < 0) { 404 return -errno; 405 } 406 if ((ret == 0) || !(p.revents & POLLIN)) { 407 return -ETIME; 408 } 409 static const char success[] = "success"; 410 char buffer[sizeof(success) - 1]; 411 memset(buffer, 0, sizeof(buffer)); 412 ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); 413 if (ret < 0) { 414 return -errno; 415 } 416 return strncmp(buffer, success, sizeof(success) - 1) != 0; 417 } 418 419 // Reinit Thread 420 sem_init(&reinit, 0, 0); 421 sem_init(&uidName, 0, 0); 422 sem_init(&sem_name, 0, 1); 423 pthread_attr_t attr; 424 if (!pthread_attr_init(&attr)) { 425 struct sched_param param; 426 427 memset(¶m, 0, sizeof(param)); 428 pthread_attr_setschedparam(&attr, ¶m); 429 pthread_attr_setschedpolicy(&attr, SCHED_BATCH); 430 if (!pthread_attr_setdetachstate(&attr, 431 PTHREAD_CREATE_DETACHED)) { 432 pthread_t thread; 433 reinit_running = true; 434 if (pthread_create(&thread, &attr, reinit_thread_start, NULL)) { 435 reinit_running = false; 436 } 437 } 438 pthread_attr_destroy(&attr); 439 } 440 441 if (drop_privs() != 0) { 442 return -1; 443 } 444 445 // Serves the purpose of managing the last logs times read on a 446 // socket connection, and as a reader lock on a range of log 447 // entries. 448 449 LastLogTimes *times = new LastLogTimes(); 450 451 // LogBuffer is the object which is responsible for holding all 452 // log entries. 453 454 logBuf = new LogBuffer(times); 455 456 signal(SIGHUP, reinit_signal_handler); 457 458 if (property_get_bool("logd.statistics", 459 BOOL_DEFAULT_TRUE | 460 BOOL_DEFAULT_FLAG_PERSIST | 461 BOOL_DEFAULT_FLAG_ENG | 462 BOOL_DEFAULT_FLAG_SVELTE)) { 463 logBuf->enableStatistics(); 464 } 465 466 // LogReader listens on /dev/socket/logdr. When a client 467 // connects, log entries in the LogBuffer are written to the client. 468 469 LogReader *reader = new LogReader(logBuf); 470 if (reader->startListener()) { 471 exit(1); 472 } 473 474 // LogListener listens on /dev/socket/logdw for client 475 // initiated log messages. New log entries are added to LogBuffer 476 // and LogReader is notified to send updates to connected clients. 477 478 LogListener *swl = new LogListener(logBuf, reader); 479 // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value 480 if (swl->startListener(600)) { 481 exit(1); 482 } 483 484 // Command listener listens on /dev/socket/logd for incoming logd 485 // administrative commands. 486 487 CommandListener *cl = new CommandListener(logBuf, reader, swl); 488 if (cl->startListener()) { 489 exit(1); 490 } 491 492 // LogAudit listens on NETLINK_AUDIT socket for selinux 493 // initiated log messages. New log entries are added to LogBuffer 494 // and LogReader is notified to send updates to connected clients. 495 496 bool auditd = property_get_bool("logd.auditd", 497 BOOL_DEFAULT_TRUE | 498 BOOL_DEFAULT_FLAG_PERSIST); 499 LogAudit *al = NULL; 500 if (auditd) { 501 al = new LogAudit(logBuf, reader, 502 property_get_bool("logd.auditd.dmesg", 503 BOOL_DEFAULT_TRUE | 504 BOOL_DEFAULT_FLAG_PERSIST) 505 ? fdDmesg 506 : -1); 507 } 508 509 LogKlog *kl = NULL; 510 if (klogd) { 511 kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != NULL); 512 } 513 514 readDmesg(al, kl); 515 516 // failure is an option ... messages are in dmesg (required by standard) 517 518 if (kl && kl->startListener()) { 519 delete kl; 520 } 521 522 if (al && al->startListener()) { 523 delete al; 524 } 525 526 TEMP_FAILURE_RETRY(pause()); 527 528 exit(0); 529 } 530