Coverage Report

Created: 2024-09-08 06:43

/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
}