main.cpp revision 85620a1bfff1824687fd1cb14c8e1a9b2683c061
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(¶m, 0, sizeof(param)); 38 39 if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 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