blob: b6c860a4a71977c494b9f437d66f97dc4447dc52 [file] [log] [blame]
Peter Qiu5dd242d2014-10-14 12:23:21 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <vector>
6
7#include <base/bind.h>
8#include <base/command_line.h>
9#include <base/logging.h>
10#include <chromeos/minijail/minijail.h>
11#include <chromeos/syslog_logging.h>
12
13#include "apmanager/daemon.h"
14
15using std::vector;
16
17namespace {
18
19namespace switches {
20
21// Don't daemon()ize; run in foreground.
22const char kForeground[] = "foreground";
23// Flag that causes apmanager to show the help message and exit.
24const char kHelp[] = "help";
25
26// The help message shown if help flag is passed to the program.
27const char kHelpMessage[] = "\n"
28 "Available Switches: \n"
29 " --foreground\n"
30 " Don\'t daemon()ize; run in foreground.\n";
31} // namespace switches
32
33} // namespace
34
35namespace {
36
37const char kLoggerCommand[] = "/usr/bin/logger";
38const char kLoggerUser[] = "syslog";
39
40} // namespace
41
42// Always logs to the syslog and logs to stderr if
43// we are running in the foreground.
44void SetupLogging(chromeos::Minijail* minijail,
45 bool foreground,
46 const char* daemon_name) {
47 int log_flags = 0;
48 log_flags |= chromeos::kLogToSyslog;
49 log_flags |= chromeos::kLogHeader;
50 if (foreground) {
51 log_flags |= chromeos::kLogToStderr;
52 }
53 chromeos::InitLog(log_flags);
54
55 if (!foreground) {
56 vector<char*> logger_command_line;
57 int logger_stdin_fd;
58 logger_command_line.push_back(const_cast<char*>(kLoggerCommand));
59 logger_command_line.push_back(const_cast<char*>("--priority"));
60 logger_command_line.push_back(const_cast<char*>("daemon.err"));
61 logger_command_line.push_back(const_cast<char*>("--tag"));
62 logger_command_line.push_back(const_cast<char*>(daemon_name));
63 logger_command_line.push_back(nullptr);
64
65 struct minijail* jail = minijail->New();
66 minijail->DropRoot(jail, kLoggerUser, kLoggerUser);
67
68 if (!minijail->RunPipeAndDestroy(jail, logger_command_line,
69 nullptr, &logger_stdin_fd)) {
70 LOG(ERROR) << "Unable to spawn logger. "
71 << "Writes to stderr will be discarded.";
72 return;
73 }
74
75 // Note that we don't set O_CLOEXEC here. This means that stderr
76 // from any child processes will, by default, be logged to syslog.
77 if (dup2(logger_stdin_fd, fileno(stderr)) != fileno(stderr)) {
78 LOG(ERROR) << "Failed to redirect stderr to syslog: "
79 << strerror(errno);
80 }
81 close(logger_stdin_fd);
82 }
83}
84
85void DropPrivileges(chromeos::Minijail* minijail) {
Peter Qiu8e785b92014-11-24 10:01:08 -080086 // TODO(zqiu): Need to figure out the right set of privileges to allow
87 // hostapd to configure interfaces.
Peter Qiu5dd242d2014-10-14 12:23:21 -070088 struct minijail* jail = minijail->New();
89 minijail->DropRoot(jail, apmanager::Daemon::kAPManagerUserName,
90 apmanager::Daemon::kAPManagerGroupName);
91 minijail_enter(jail);
92 minijail->Destroy(jail);
93}
94
95void OnStartup(const char* daemon_name, CommandLine* cl) {
96 chromeos::Minijail* minijail = chromeos::Minijail::GetInstance();
97 SetupLogging(minijail, cl->HasSwitch(switches::kForeground), daemon_name);
98
99 LOG(INFO) << __func__ << ": Dropping privileges";
100
Peter Qiubf8e36c2014-12-03 22:59:45 -0800101 // TODO(zqiu): temporary, until we figure out the exact privileges required
102 // to start required daemons (hostapd and dnsmasq).
Peter Qiu5dd242d2014-10-14 12:23:21 -0700103 // Now that the daemon has all the resources it needs to run, we can drop
104 // privileges further.
Peter Qiubf8e36c2014-12-03 22:59:45 -0800105 // DropPrivileges(minijail);
Peter Qiu5dd242d2014-10-14 12:23:21 -0700106}
107
108int main(int argc, char* argv[]) {
109 CommandLine::Init(argc, argv);
110 CommandLine* cl = CommandLine::ForCurrentProcess();
111
112 if (cl->HasSwitch(switches::kHelp)) {
113 LOG(INFO) << switches::kHelpMessage;
114 return 0;
115 }
116
117 const int nochdir = 0, noclose = 0;
118 if (!cl->HasSwitch(switches::kForeground))
119 PLOG_IF(FATAL, daemon(nochdir, noclose) == -1) << "Failed to daemonize";
120
121 apmanager::Daemon daemon(base::Bind(&OnStartup, argv[0], cl));
122
123 daemon.Run();
124
125 return 0;
126}