1 // 2 // Copyright (C) 2014 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 <vector> 18 19 #include <base/bind.h> 20 #include <base/command_line.h> 21 #include <base/logging.h> 22 #include <brillo/minijail/minijail.h> 23 #include <brillo/syslog_logging.h> 24 25 #include "apmanager/daemon.h" 26 27 using std::vector; 28 29 namespace { 30 31 namespace switches { 32 33 // Don't daemon()ize; run in foreground. 34 const char kForeground[] = "foreground"; 35 // Flag that causes apmanager to show the help message and exit. 36 const char kHelp[] = "help"; 37 38 // The help message shown if help flag is passed to the program. 39 const char kHelpMessage[] = "\n" 40 "Available Switches: \n" 41 " --foreground\n" 42 " Don\'t daemon()ize; run in foreground.\n"; 43 } // namespace switches 44 45 } // namespace 46 47 namespace { 48 49 #if !defined(__ANDROID__) 50 const char kLoggerCommand[] = "/usr/bin/logger"; 51 const char kLoggerUser[] = "syslog"; 52 #endif // __ANDROID__ 53 54 const char kSeccompFilePath[] = "/usr/share/policy/apmanager-seccomp.policy"; 55 56 } // namespace 57 58 // Always logs to the syslog and logs to stderr if 59 // we are running in the foreground. 60 void SetupLogging(brillo::Minijail* minijail, 61 bool foreground, 62 const char* daemon_name) { 63 int log_flags = 0; 64 log_flags |= brillo::kLogToSyslog; 65 log_flags |= brillo::kLogHeader; 66 if (foreground) { 67 log_flags |= brillo::kLogToStderr; 68 } 69 brillo::InitLog(log_flags); 70 71 #if !defined(__ANDROID__) 72 // Logger utility doesn't exist on Android, so do not run it on Android. 73 // TODO(zqiu): add support to redirect stderr logs from child processes 74 // to Android logging facility. 75 if (!foreground) { 76 vector<char*> logger_command_line; 77 int logger_stdin_fd; 78 logger_command_line.push_back(const_cast<char*>(kLoggerCommand)); 79 logger_command_line.push_back(const_cast<char*>("--priority")); 80 logger_command_line.push_back(const_cast<char*>("daemon.err")); 81 logger_command_line.push_back(const_cast<char*>("--tag")); 82 logger_command_line.push_back(const_cast<char*>(daemon_name)); 83 logger_command_line.push_back(nullptr); 84 85 struct minijail* jail = minijail->New(); 86 minijail->DropRoot(jail, kLoggerUser, kLoggerUser); 87 88 if (!minijail->RunPipeAndDestroy(jail, logger_command_line, 89 nullptr, &logger_stdin_fd)) { 90 LOG(ERROR) << "Unable to spawn logger. " 91 << "Writes to stderr will be discarded."; 92 return; 93 } 94 95 // Note that we don't set O_CLOEXEC here. This means that stderr 96 // from any child processes will, by default, be logged to syslog. 97 if (dup2(logger_stdin_fd, fileno(stderr)) != fileno(stderr)) { 98 LOG(ERROR) << "Failed to redirect stderr to syslog: " 99 << strerror(errno); 100 } 101 close(logger_stdin_fd); 102 } 103 #endif // __ANDROID__ 104 } 105 106 void DropPrivileges(brillo::Minijail* minijail) { 107 struct minijail* jail = minijail->New(); 108 minijail->DropRoot(jail, apmanager::Daemon::kAPManagerUserName, 109 apmanager::Daemon::kAPManagerGroupName); 110 // Permissions needed for the daemon and its child processes for managing 111 // network interfaces and binding to network sockets. 112 minijail->UseCapabilities(jail, CAP_TO_MASK(CAP_NET_ADMIN) | 113 CAP_TO_MASK(CAP_NET_RAW) | 114 CAP_TO_MASK(CAP_NET_BIND_SERVICE)); 115 minijail->UseSeccompFilter(jail, kSeccompFilePath); 116 minijail_enter(jail); 117 minijail->Destroy(jail); 118 } 119 120 void OnStartup(const char* daemon_name, base::CommandLine* cl) { 121 brillo::Minijail* minijail = brillo::Minijail::GetInstance(); 122 SetupLogging(minijail, cl->HasSwitch(switches::kForeground), daemon_name); 123 124 LOG(INFO) << __func__ << ": Dropping privileges"; 125 126 // TODO(zqiu): apmanager is currently started as the "system" user on Android, 127 // so there is no need to drop privileges to the "system" user again. 128 // Drop user privileges when we're running apmanager under a different 129 // user/group. 130 #if !defined(__ANDROID__) 131 // Now that the daemon has all the resources it needs to run, we can drop 132 // privileges further. 133 DropPrivileges(minijail); 134 #endif // __ANDROID 135 } 136 137 int main(int argc, char* argv[]) { 138 base::CommandLine::Init(argc, argv); 139 base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); 140 141 if (cl->HasSwitch(switches::kHelp)) { 142 LOG(INFO) << switches::kHelpMessage; 143 return 0; 144 } 145 146 apmanager::Daemon daemon(base::Bind(&OnStartup, argv[0], cl)); 147 148 daemon.Run(); 149 150 return 0; 151 } 152