• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 19520565317

19 Nov 2025 11:19PM UTC coverage: 72.548% (+0.1%) from 72.449%
19520565317

push

github

web-flow
core: Verify inherited FDs are writable for stdout/stderr (#39674)

When inheriting file descriptors for stdout/stderr (either from stdin or
when making stderr inherit from stdout), we previously just assumed they
would be writable and dup'd them. This could lead to broken setups if
the inherited FD was actually opened read-only.

Before dup'ing any inherited FDs to stdout/stderr, verify they are
actually writable using the new fd_is_writable() helper. If not, fall
back to /dev/null (or reopen the terminal in the TTY case) with a
warning, rather than silently creating a broken setup where output
operations would fail.

31 of 44 new or added lines in 3 files covered. (70.45%)

813 existing lines in 43 files now uncovered.

308541 of 425291 relevant lines covered (72.55%)

1188151.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

36.73
/src/libudev/libudev-queue.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
/***
3
  Copyright © 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
4
***/
5

6
#include <sys/inotify.h>
7
#include <unistd.h>
8

9
#include "libudev.h"
10

11
#include "alloc-util.h"
12
#include "errno-util.h"
13
#include "fd-util.h"
14
#include "io-util.h"
15

16
/**
17
 * SECTION:libudev-queue
18
 * @short_description: access to currently active events
19
 *
20
 * This exports the current state of the udev processing queue.
21
 */
22

23
/**
24
 * udev_queue:
25
 *
26
 * Opaque object representing the current event queue in the udev daemon.
27
 */
28
struct udev_queue {
29
        struct udev *udev;
30
        unsigned n_ref;
31
        int fd;
32
};
33

34
/**
35
 * udev_queue_new:
36
 * @udev: udev library context
37
 *
38
 * The initial refcount is 1, and needs to be decremented to
39
 * release the resources of the udev queue context.
40
 *
41
 * Returns: the udev queue context, or #NULL on error.
42
 **/
43
_public_ struct udev_queue* udev_queue_new(struct udev *udev) {
2,080✔
44
        struct udev_queue *udev_queue;
2,080✔
45

46
        udev_queue = new(struct udev_queue, 1);
2,080✔
47
        if (!udev_queue)
2,080✔
UNCOV
48
                return_with_errno(NULL, ENOMEM);
×
49

50
        *udev_queue = (struct udev_queue) {
2,080✔
51
                .udev = udev,
52
                .n_ref = 1,
53
                .fd = -EBADF,
54
        };
55

56
        return udev_queue;
2,080✔
57
}
58

59
static struct udev_queue* udev_queue_free(struct udev_queue *udev_queue) {
2,080✔
60
        assert(udev_queue);
2,080✔
61

62
        safe_close(udev_queue->fd);
2,080✔
63
        return mfree(udev_queue);
2,080✔
64
}
65

66
static int udev_queue_is_empty(void) {
1✔
67
        return access("/run/udev/queue", F_OK) < 0 ?
1✔
68
                (errno == ENOENT ? true : -errno) : false;
1✔
69
}
70

71
/**
72
 * udev_queue_ref:
73
 * @udev_queue: udev queue context
74
 *
75
 * Take a reference of a udev queue context.
76
 *
77
 * Returns: the same udev queue context.
78
 **/
79

80
/**
81
 * udev_queue_unref:
82
 * @udev_queue: udev queue context
83
 *
84
 * Drop a reference of a udev queue context. If the refcount reaches zero,
85
 * the resources of the queue context will be released.
86
 *
87
 * Returns: #NULL
88
 **/
89
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_queue, udev_queue, udev_queue_free);
2,080✔
90

91
/**
92
 * udev_queue_get_udev:
93
 * @udev_queue: udev queue context
94
 *
95
 * Retrieve the udev library context the queue context was created with.
96
 *
97
 * Returns: the udev library context.
98
 **/
UNCOV
99
_public_ struct udev* udev_queue_get_udev(struct udev_queue *udev_queue) {
×
UNCOV
100
        assert_return_errno(udev_queue, NULL, EINVAL);
×
101

UNCOV
102
        return udev_queue->udev;
×
103
}
104

105
/**
106
 * udev_queue_get_kernel_seqnum:
107
 * @udev_queue: udev queue context
108
 *
109
 * This function is deprecated.
110
 *
111
 * Returns: 0.
112
 **/
UNCOV
113
_public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) {
×
UNCOV
114
        return 0;
×
115
}
116

117
/**
118
 * udev_queue_get_udev_seqnum:
119
 * @udev_queue: udev queue context
120
 *
121
 * This function is deprecated.
122
 *
123
 * Returns: 0.
124
 **/
UNCOV
125
_public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) {
×
UNCOV
126
        return 0;
×
127
}
128

129
/**
130
 * udev_queue_get_udev_is_active:
131
 * @udev_queue: udev queue context
132
 *
133
 * Check if udev is active on the system.
134
 *
135
 * Returns: a flag indicating if udev is active.
136
 **/
137
_public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) {
2,079✔
138
        return access("/run/udev/control", F_OK) >= 0;
2,079✔
139
}
140

141
/**
142
 * udev_queue_get_queue_is_empty:
143
 * @udev_queue: udev queue context
144
 *
145
 * Check if udev is currently processing any events.
146
 *
147
 * Returns: a flag indicating if udev is currently handling events.
148
 **/
149
_public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) {
1✔
150
        return udev_queue_is_empty() > 0;
1✔
151
}
152

153
/**
154
 * udev_queue_get_seqnum_sequence_is_finished:
155
 * @udev_queue: udev queue context
156
 * @start: first event sequence number
157
 * @end: last event sequence number
158
 *
159
 * This function is deprecated, and equivalent to udev_queue_get_queue_is_empty().
160
 *
161
 * Returns: a flag indicating if udev is currently handling events.
162
 **/
UNCOV
163
_public_ int udev_queue_get_seqnum_sequence_is_finished(
×
164
                struct udev_queue *udev_queue,
165
                unsigned long long int start,
166
                unsigned long long int end) {
167

UNCOV
168
        return udev_queue_is_empty() > 0;
×
169
}
170

171
/**
172
 * udev_queue_get_seqnum_is_finished:
173
 * @udev_queue: udev queue context
174
 * @seqnum: sequence number
175
 *
176
 * This function is deprecated, and equivalent to udev_queue_get_queue_is_empty().
177
 *
178
 * Returns: a flag indicating if udev is currently handling events.
179
 **/
UNCOV
180
_public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) {
×
UNCOV
181
        return udev_queue_is_empty() > 0;
×
182
}
183

184
/**
185
 * udev_queue_get_queued_list_entry:
186
 * @udev_queue: udev queue context
187
 *
188
 * This function is deprecated.
189
 *
190
 * Returns: NULL.
191
 **/
UNCOV
192
_public_ struct udev_list_entry* udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) {
×
UNCOV
193
        return_with_errno(NULL, ENODATA);
×
194
}
195

196
/**
197
 * udev_queue_get_fd:
198
 * @udev_queue: udev queue context
199
 *
200
 * Returns: a file descriptor to watch for a queue to become empty.
201
 */
UNCOV
202
_public_ int udev_queue_get_fd(struct udev_queue *udev_queue) {
×
203
        _cleanup_close_ int fd = -EBADF;
×
204

UNCOV
205
        assert_return(udev_queue, -EINVAL);
×
206

207
        if (udev_queue->fd >= 0)
×
208
                return udev_queue->fd;
209

210
        fd = inotify_init1(IN_CLOEXEC);
×
211
        if (fd < 0)
×
UNCOV
212
                return -errno;
×
213

UNCOV
214
        if (inotify_add_watch(fd, "/run/udev" , IN_DELETE) < 0)
×
UNCOV
215
                return -errno;
×
216

UNCOV
217
        return udev_queue->fd = TAKE_FD(fd);
×
218
}
219

220
/**
221
 * udev_queue_flush:
222
 * @udev_queue: udev queue context
223
 *
224
 * Returns: the result of clearing the watch for queue changes.
225
 */
UNCOV
226
_public_ int udev_queue_flush(struct udev_queue *udev_queue) {
×
227
        int r;
×
228

UNCOV
229
        assert_return(udev_queue, -EINVAL);
×
230

231
        if (udev_queue->fd < 0)
×
232
                return -EINVAL;
233

UNCOV
234
        r = flush_fd(udev_queue->fd);
×
UNCOV
235
        if (r < 0)
×
UNCOV
236
                return r;
×
237

238
        return 0;
239
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc