Coverage Report

Created: 2026-06-10 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/lib/daemon.c
Line
Count
Source
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 '/', then it is treated as an absolute path.
57
 * Otherwise, it is taken relative to RUNDIR, which is $(prefix)/var/run
58
 * 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
    char *device = "/dev/null";
108
109
0
    if (!null_fd) {
110
0
        null_fd = open(device, O_RDWR);
111
0
        if (null_fd < 0) {
112
0
            int error = errno;
113
0
            VLOG_ERR("could not open %s: %s", device, ovs_strerror(error));
114
0
            null_fd = -error;
115
0
        }
116
0
    }
117
118
0
    return null_fd;
119
0
}
120
121
/* Close standard file descriptors (except any that the client has requested we
122
 * leave open by calling daemon_save_fd()).  If we're started from e.g. an SSH
123
 * session, then this keeps us from holding that session open artificially. */
124
void
125
close_standard_fds(void)
126
0
{
127
0
    int null_fd = get_null_fd();
128
0
    if (null_fd >= 0) {
129
0
        int fd;
130
131
0
        for (fd = 0; fd < 3; fd++) {
132
0
            if (!save_fds[fd]) {
133
0
                dup2(null_fd, fd);
134
0
            }
135
0
        }
136
0
    }
137
138
    /* Disable logging to stderr to avoid wasting CPU time. */
139
    vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF);
140
0
}