/src/openvswitch/lib/daemon.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2014 Nicira, Inc. |
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 | | #include <config.h> |
17 | | #include "daemon.h" |
18 | | #include "daemon-private.h" |
19 | | #include <errno.h> |
20 | | #include <fcntl.h> |
21 | | #include <unistd.h> |
22 | | #include "util.h" |
23 | | #include "ovs-thread.h" |
24 | | #include "openvswitch/vlog.h" |
25 | | |
26 | | VLOG_DEFINE_THIS_MODULE(daemon); |
27 | | |
28 | | /* For each of the standard file descriptors, whether to replace it by |
29 | | * /dev/null (if false) or keep it for the daemon to use (if true). */ |
30 | | static bool save_fds[3]; |
31 | | |
32 | | /* Self Confinement is a security feature that introduces additional |
33 | | * layer of defense where OVS in self-denying manner would refuse to connect |
34 | | * to or create unix domain sockets outside designated 'run' directory even |
35 | | * if remote (or local) OVSDB manager asked it to do so. This feature may |
36 | | * be disabled if Mandatory Access Control is used. */ |
37 | | static bool self_confine = true; |
38 | | |
39 | | /* Will daemonize() really detach? */ |
40 | | bool |
41 | | get_detach(void) |
42 | 0 | { |
43 | 0 | return detach; |
44 | 0 | } |
45 | | |
46 | | /* If configured with set_pidfile() or set_detach(), creates the pid file and |
47 | | * detaches from the foreground session. */ |
48 | | void |
49 | | daemonize(void) |
50 | 0 | { |
51 | 0 | daemonize_start(false, false); |
52 | 0 | daemonize_complete(); |
53 | 0 | } |
54 | | |
55 | | /* Sets up a following call to daemonize() to create a pidfile named 'name'. |
56 | | * If 'name' begins with '/' (or contains ':' in windows), then it is treated |
57 | | * as an absolute path. Otherwise, it is taken relative to RUNDIR, |
58 | | * which is $(prefix)/var/run by default. |
59 | | * |
60 | | * If 'name' is null, then program_name followed by ".pid" is used. */ |
61 | | void |
62 | | set_pidfile(const char *name) |
63 | 0 | { |
64 | 0 | assert_single_threaded(); |
65 | 0 | free(pidfile); |
66 | 0 | pidfile = make_pidfile_name(name); |
67 | 0 | } |
68 | | |
69 | | /* Disables self confinement. */ |
70 | | void |
71 | | daemon_disable_self_confinement(void) |
72 | 0 | { |
73 | 0 | self_confine = false; |
74 | 0 | } |
75 | | |
76 | | /* Returns true, if self-confinement should be enforced. |
77 | | * Otherwise, returns false. */ |
78 | | bool |
79 | | daemon_should_self_confine(void) |
80 | 0 | { |
81 | 0 | return self_confine; |
82 | 0 | } |
83 | | |
84 | | /* A daemon doesn't normally have any use for the file descriptors for stdin, |
85 | | * stdout, and stderr after it detaches. To keep these file descriptors from |
86 | | * e.g. holding an SSH session open, by default detaching replaces each of |
87 | | * these file descriptors by /dev/null. But a few daemons expect the user to |
88 | | * redirect stdout or stderr to a file, in which case it is desirable to keep |
89 | | * these file descriptors. This function, therefore, disables replacing 'fd' |
90 | | * by /dev/null when the daemon detaches. */ |
91 | | void |
92 | | daemon_save_fd(int fd) |
93 | 0 | { |
94 | 0 | ovs_assert(fd == STDIN_FILENO || |
95 | 0 | fd == STDOUT_FILENO || |
96 | 0 | fd == STDERR_FILENO); |
97 | 0 | save_fds[fd] = true; |
98 | 0 | } |
99 | | |
100 | | /* Returns a readable and writable fd for /dev/null, if successful, otherwise |
101 | | * a negative errno value. The caller must not close the returned fd (because |
102 | | * the same fd will be handed out to subsequent callers). */ |
103 | | static int |
104 | | get_null_fd(void) |
105 | 0 | { |
106 | 0 | static int null_fd; |
107 | 0 | #ifndef _WIN32 |
108 | 0 | char *device = "/dev/null"; |
109 | | #else |
110 | | char *device = "nul"; |
111 | | #endif |
112 | |
|
113 | 0 | if (!null_fd) { |
114 | 0 | null_fd = open(device, O_RDWR); |
115 | 0 | if (null_fd < 0) { |
116 | 0 | int error = errno; |
117 | 0 | VLOG_ERR("could not open %s: %s", device, ovs_strerror(error)); |
118 | 0 | null_fd = -error; |
119 | 0 | } |
120 | 0 | } |
121 | |
|
122 | 0 | return null_fd; |
123 | 0 | } |
124 | | |
125 | | /* Close standard file descriptors (except any that the client has requested we |
126 | | * leave open by calling daemon_save_fd()). If we're started from e.g. an SSH |
127 | | * session, then this keeps us from holding that session open artificially. */ |
128 | | void |
129 | | close_standard_fds(void) |
130 | 0 | { |
131 | 0 | int null_fd = get_null_fd(); |
132 | 0 | if (null_fd >= 0) { |
133 | 0 | int fd; |
134 | |
|
135 | 0 | for (fd = 0; fd < 3; fd++) { |
136 | 0 | if (!save_fds[fd]) { |
137 | 0 | dup2(null_fd, fd); |
138 | 0 | } |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | | /* Disable logging to stderr to avoid wasting CPU time. */ |
143 | 0 | vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF); |
144 | 0 | } |