10175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn/* 20175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Copyright (C) 2012-2013 The Android Open Source Project 30175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * 40175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 50175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * you may not use this file except in compliance with the License. 60175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * You may obtain a copy of the License at 70175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * 80175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 90175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * 100175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Unless required by applicable law or agreed to in writing, software 110175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 120175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * See the License for the specific language governing permissions and 140175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * limitations under the License. 150175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn */ 160175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 170175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <dirent.h> 180175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <errno.h> 190175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <fcntl.h> 20882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn#include <sched.h> 210175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <stdio.h> 220175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <stdlib.h> 230175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <string.h> 240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/capability.h> 25c11146efdf41b2f2b5cabc00acbb90ee11fd1c8dElliott Hughes#include <sys/prctl.h> 260175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/stat.h> 270175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/types.h> 28e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn#include <unistd.h> 290175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 30e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn#include <cutils/properties.h> 31e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn 320175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "private/android_filesystem_config.h" 330175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "CommandListener.h" 340175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "LogBuffer.h" 350175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "LogListener.h" 3629d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts#include "LogAudit.h" 370175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 38dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// 39dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// The service is designed to be run by init, it does not respond well 40dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// to starting up manually. When starting up manually the sockets will 41dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// fail to open typically for one of the following reasons: 42dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// EADDRINUSE if logger is running. 43dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// EACCESS if started without precautions (below) 44dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// 45dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// Here is a cookbook procedure for starting up logd manually assuming 46dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// init is out of the way, pedantically all permissions and selinux 47dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// security is put back in place: 48dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// 49dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// setenforce 0 50dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// rm /dev/socket/logd* 51dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// chmod 777 /dev/socket 52dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// # here is where you would attach the debugger or valgrind for example 53dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// runcon u:r:logd:s0 /system/bin/logd </dev/null >/dev/null 2>&1 & 54dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// sleep 1 55dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// chmod 755 /dev/socket 56dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// chown logd.logd /dev/socket/logd* 57dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// restorecon /dev/socket/logd* 58dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// setenforce 1 59dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// 60dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// If minimalism prevails, typical for debugging and security is not a concern: 61dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// 62dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// setenforce 0 63dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// chmod 777 /dev/socket 64dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// logd 65dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn// 66dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynstatic int drop_privs() { 68882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn struct sched_param param; 69882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn memset(¶m, 0, sizeof(param)); 70882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn 71882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) { 72882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn return -1; 73882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn } 74882f856668331488d9bbaec429de7aac5d7978c9Mark Salyzyn 750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (prctl(PR_SET_KEEPCAPS, 1) < 0) { 760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return -1; 770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 780175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 790175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (setgid(AID_LOGD) != 0) { 800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return -1; 810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 830175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (setuid(AID_LOGD) != 0) { 840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return -1; 850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn struct __user_cap_header_struct capheader; 880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn struct __user_cap_data_struct capdata[2]; 890175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn memset(&capheader, 0, sizeof(capheader)); 900175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn memset(&capdata, 0, sizeof(capdata)); 910175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn capheader.version = _LINUX_CAPABILITY_VERSION_3; 920175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn capheader.pid = 0; 930175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 940175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG); 9529d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL); 9629d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts 9729d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts capdata[0].effective = capdata[0].permitted; 9829d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts capdata[1].effective = capdata[1].permitted; 990175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn capdata[0].inheritable = 0; 1000175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn capdata[1].inheritable = 0; 1010175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1020175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (capset(&capheader, &capdata[0]) < 0) { 1030175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return -1; 1040175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1050175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1060175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return 0; 1070175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 1080175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 109e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn// Property helper 110e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzynstatic bool property_get_bool(const char *key, bool def) { 111e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn char property[PROPERTY_VALUE_MAX]; 112e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn property_get(key, property, ""); 113e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn 114e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn if (!strcasecmp(property, "true")) { 115e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn return true; 116e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn } 117e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn if (!strcasecmp(property, "false")) { 118e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn return false; 119e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn } 120e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn 121e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn return def; 122e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn} 123e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn 1240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// Foreground waits for exit of the three main persistent threads that 1250175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// are started here. The three threads are created to manage UNIX 1260175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// domain client sockets for writing, reading and controlling the user 1270175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// space logger. Additional transitory per-client threads are created 1280175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// for each reader once they register. 1290175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynint main() { 130e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn bool auditd = property_get_bool("logd.auditd", true); 131e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn 132e9bebd0eb1845f0c6009ce2edc5aeb47bf89e397Mark Salyzyn int fdDmesg = -1; 133e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn if (auditd && property_get_bool("logd.auditd.dmesg", true)) { 134e9bebd0eb1845f0c6009ce2edc5aeb47bf89e397Mark Salyzyn fdDmesg = open("/dev/kmsg", O_WRONLY); 135e9bebd0eb1845f0c6009ce2edc5aeb47bf89e397Mark Salyzyn } 136e9bebd0eb1845f0c6009ce2edc5aeb47bf89e397Mark Salyzyn 1370175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (drop_privs() != 0) { 1380175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return -1; 1390175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1400175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1410175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // Serves the purpose of managing the last logs times read on a 1420175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // socket connection, and as a reader lock on a range of log 1430175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // entries. 1440175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1450175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LastLogTimes *times = new LastLogTimes(); 1460175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1470175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // LogBuffer is the object which is responsible for holding all 1480175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // log entries. 1490175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1500175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogBuffer *logBuf = new LogBuffer(times); 1510175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 152e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn if (property_get_bool("logd.statistics.dgram_qlen", false)) { 153e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn logBuf->enableDgramQlenStatistics(); 154e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn } 155a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn { 156a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn char property[PROPERTY_VALUE_MAX]; 157a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn property_get("ro.build.type", property, ""); 158a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn if (property_get_bool("logd.statistics", 159a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn !!strcmp(property, "user") 160a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn && !property_get_bool("ro.config.low_ram", false))) { 161a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn logBuf->enableStatistics(); 162a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn } 163a0e53540daa67142abd93756fad38a69eab8fbceMark Salyzyn } 164e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn 1650175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // LogReader listens on /dev/socket/logdr. When a client 1660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // connects, log entries in the LogBuffer are written to the client. 1670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1680175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogReader *reader = new LogReader(logBuf); 1690175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (reader->startListener()) { 1700175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn exit(1); 1710175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // LogListener listens on /dev/socket/logdw for client 1740175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // initiated log messages. New log entries are added to LogBuffer 1750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // and LogReader is notified to send updates to connected clients. 1760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogListener *swl = new LogListener(logBuf, reader); 178581edc1b6c3799238cfb674dfddb97db44f2818eMark Salyzyn // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value 179581edc1b6c3799238cfb674dfddb97db44f2818eMark Salyzyn if (swl->startListener(300)) { 1800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn exit(1); 1810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1830175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // Command listener listens on /dev/socket/logd for incoming logd 1840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn // administrative commands. 1850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn CommandListener *cl = new CommandListener(logBuf, reader, swl); 1870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cl->startListener()) { 1880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn exit(1); 1890175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1900175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 19129d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts // LogAudit listens on NETLINK_AUDIT socket for selinux 19229d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts // initiated log messages. New log entries are added to LogBuffer 19329d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts // and LogReader is notified to send updates to connected clients. 19429d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts 195e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn if (auditd) { 196e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn // failure is an option ... messages are in dmesg (required by standard) 197e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn LogAudit *al = new LogAudit(logBuf, reader, fdDmesg); 198e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn if (al->startListener()) { 199e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn delete al; 200e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn close(fdDmesg); 201e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn } 20229d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts } 20329d238d2a8e12c131a4cfbccb912e525cca6b10dWilliam Roberts 2040175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn pause(); 2050175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn exit(0); 2060175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 2070175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 208