blob: 7346e2fa90eb842e3765d3721c959862511642be [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
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>
Mark Salyzyn882f8562013-12-26 15:13:36 -080020#include <sched.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080021#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/capability.h>
25#include <sys/stat.h>
26#include <sys/types.h>
Mark Salyzyne457b742014-02-19 17:18:31 -080027#include <unistd.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080028
29#include <linux/prctl.h>
30
Mark Salyzyne457b742014-02-19 17:18:31 -080031#include <cutils/properties.h>
32
Mark Salyzyn0175b072014-02-26 09:50:16 -080033#include "private/android_filesystem_config.h"
34#include "CommandListener.h"
35#include "LogBuffer.h"
36#include "LogListener.h"
William Roberts29d238d2013-02-08 09:45:26 +090037#include "LogAudit.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080038
39static int drop_privs() {
Mark Salyzyn882f8562013-12-26 15:13:36 -080040 struct sched_param param;
41 memset(&param, 0, sizeof(param));
42
43 if (sched_setscheduler((pid_t) 0, SCHED_BATCH, &param) < 0) {
44 return -1;
45 }
46
Mark Salyzyn0175b072014-02-26 09:50:16 -080047 if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
48 return -1;
49 }
50
51 if (setgid(AID_LOGD) != 0) {
52 return -1;
53 }
54
55 if (setuid(AID_LOGD) != 0) {
56 return -1;
57 }
58
59 struct __user_cap_header_struct capheader;
60 struct __user_cap_data_struct capdata[2];
61 memset(&capheader, 0, sizeof(capheader));
62 memset(&capdata, 0, sizeof(capdata));
63 capheader.version = _LINUX_CAPABILITY_VERSION_3;
64 capheader.pid = 0;
65
66 capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
William Roberts29d238d2013-02-08 09:45:26 +090067 capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL);
68
69 capdata[0].effective = capdata[0].permitted;
70 capdata[1].effective = capdata[1].permitted;
Mark Salyzyn0175b072014-02-26 09:50:16 -080071 capdata[0].inheritable = 0;
72 capdata[1].inheritable = 0;
73
74 if (capset(&capheader, &capdata[0]) < 0) {
75 return -1;
76 }
77
78 return 0;
79}
80
81// Foreground waits for exit of the three main persistent threads that
82// are started here. The three threads are created to manage UNIX
83// domain client sockets for writing, reading and controlling the user
84// space logger. Additional transitory per-client threads are created
85// for each reader once they register.
86int main() {
Mark Salyzyne9bebd02014-04-03 09:55:26 -070087 int fdDmesg = -1;
88 char dmesg[PROPERTY_VALUE_MAX];
89 property_get("logd.auditd.dmesg", dmesg, "1");
90 if (atol(dmesg)) {
91 fdDmesg = open("/dev/kmsg", O_WRONLY);
92 }
93
Mark Salyzyn0175b072014-02-26 09:50:16 -080094 if (drop_privs() != 0) {
95 return -1;
96 }
97
98 // Serves the purpose of managing the last logs times read on a
99 // socket connection, and as a reader lock on a range of log
100 // entries.
101
102 LastLogTimes *times = new LastLogTimes();
103
104 // LogBuffer is the object which is responsible for holding all
105 // log entries.
106
107 LogBuffer *logBuf = new LogBuffer(times);
108
Mark Salyzyne457b742014-02-19 17:18:31 -0800109 char dgram_qlen_statistics[PROPERTY_VALUE_MAX];
110 property_get("logd.dgram_qlen.statistics", dgram_qlen_statistics, "");
111 if (atol(dgram_qlen_statistics)) {
112 logBuf->enableDgramQlenStatistics();
113 }
114
Mark Salyzyn0175b072014-02-26 09:50:16 -0800115 // LogReader listens on /dev/socket/logdr. When a client
116 // connects, log entries in the LogBuffer are written to the client.
117
118 LogReader *reader = new LogReader(logBuf);
119 if (reader->startListener()) {
120 exit(1);
121 }
122
123 // LogListener listens on /dev/socket/logdw for client
124 // initiated log messages. New log entries are added to LogBuffer
125 // and LogReader is notified to send updates to connected clients.
126
127 LogListener *swl = new LogListener(logBuf, reader);
Mark Salyzyn581edc12013-11-20 13:38:52 -0800128 // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
129 if (swl->startListener(300)) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800130 exit(1);
131 }
132
133 // Command listener listens on /dev/socket/logd for incoming logd
134 // administrative commands.
135
136 CommandListener *cl = new CommandListener(logBuf, reader, swl);
137 if (cl->startListener()) {
138 exit(1);
139 }
140
William Roberts29d238d2013-02-08 09:45:26 +0900141 // LogAudit listens on NETLINK_AUDIT socket for selinux
142 // initiated log messages. New log entries are added to LogBuffer
143 // and LogReader is notified to send updates to connected clients.
144
145 // failure is an option ... messages are in dmesg (required by standard)
Mark Salyzyne9bebd02014-04-03 09:55:26 -0700146 LogAudit *al = new LogAudit(logBuf, reader, fdDmesg);
William Roberts29d238d2013-02-08 09:45:26 +0900147 if (al->startListener()) {
148 delete al;
Mark Salyzyne9bebd02014-04-03 09:55:26 -0700149 close(fdDmesg);
William Roberts29d238d2013-02-08 09:45:26 +0900150 }
151
Mark Salyzyn0175b072014-02-26 09:50:16 -0800152 pause();
153 exit(0);
154}
155