main.cpp revision 882f856668331488d9bbaec429de7aac5d7978c9
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 <sched.h>
21#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() {
36    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
43    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);
108    if (swl->startListener()) {
109        exit(1);
110    }
111
112    // Command listener listens on /dev/socket/logd for incoming logd
113    // administrative commands.
114
115    CommandListener *cl = new CommandListener(logBuf, reader, swl);
116    if (cl->startListener()) {
117        exit(1);
118    }
119
120    pause();
121    exit(0);
122}
123
124