blob: 6216b95c3da22266af399f81a864c4bbe3f635e5 [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>
27
28#include <linux/prctl.h>
29
30#include "private/android_filesystem_config.h"
31#include "CommandListener.h"
32#include "LogBuffer.h"
33#include "LogListener.h"
34
35static int drop_privs() {
Mark Salyzyn882f8562013-12-26 15:13:36 -080036 struct sched_param param;
37 memset(&param, 0, sizeof(param));
38
39 if (sched_setscheduler((pid_t) 0, SCHED_BATCH, &param) < 0) {
40 return -1;
41 }
42
Mark Salyzyn0175b072014-02-26 09:50:16 -080043 if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
44 return -1;
45 }
46
47 if (setgid(AID_LOGD) != 0) {
48 return -1;
49 }
50
51 if (setuid(AID_LOGD) != 0) {
52 return -1;
53 }
54
55 struct __user_cap_header_struct capheader;
56 struct __user_cap_data_struct capdata[2];
57 memset(&capheader, 0, sizeof(capheader));
58 memset(&capdata, 0, sizeof(capdata));
59 capheader.version = _LINUX_CAPABILITY_VERSION_3;
60 capheader.pid = 0;
61
62 capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
63 capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
64 capdata[0].inheritable = 0;
65 capdata[1].inheritable = 0;
66
67 if (capset(&capheader, &capdata[0]) < 0) {
68 return -1;
69 }
70
71 return 0;
72}
73
74// Foreground waits for exit of the three main persistent threads that
75// are started here. The three threads are created to manage UNIX
76// domain client sockets for writing, reading and controlling the user
77// space logger. Additional transitory per-client threads are created
78// for each reader once they register.
79int main() {
80 if (drop_privs() != 0) {
81 return -1;
82 }
83
84 // Serves the purpose of managing the last logs times read on a
85 // socket connection, and as a reader lock on a range of log
86 // entries.
87
88 LastLogTimes *times = new LastLogTimes();
89
90 // LogBuffer is the object which is responsible for holding all
91 // log entries.
92
93 LogBuffer *logBuf = new LogBuffer(times);
94
95 // LogReader listens on /dev/socket/logdr. When a client
96 // connects, log entries in the LogBuffer are written to the client.
97
98 LogReader *reader = new LogReader(logBuf);
99 if (reader->startListener()) {
100 exit(1);
101 }
102
103 // LogListener listens on /dev/socket/logdw for client
104 // initiated log messages. New log entries are added to LogBuffer
105 // and LogReader is notified to send updates to connected clients.
106
107 LogListener *swl = new LogListener(logBuf, reader);
Mark Salyzyn581edc12013-11-20 13:38:52 -0800108 // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
109 if (swl->startListener(300)) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800110 exit(1);
111 }
112
113 // Command listener listens on /dev/socket/logd for incoming logd
114 // administrative commands.
115
116 CommandListener *cl = new CommandListener(logBuf, reader, swl);
117 if (cl->startListener()) {
118 exit(1);
119 }
120
121 pause();
122 exit(0);
123}
124