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(¶m, 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, ¶m) < 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(¶m, 0, sizeof(param)); 381 pthread_attr_setschedparam(&attr, ¶m); 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