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

systemd / systemd / 15263807472

26 May 2025 08:53PM UTC coverage: 72.046% (-0.002%) from 72.048%
15263807472

push

github

yuwata
src/core/manager.c: log preset activity on first boot

This gives us a little more information about what units were enabled
or disabled on that first boot and will be useful for OS developers
tracking down the source of unit state.

An example with this enabled looks like:

```
NET: Registered PF_VSOCK protocol family
systemd[1]: Applying preset policy.
systemd[1]: Unit /etc/systemd/system/dnsmasq.service is masked, ignoring.
systemd[1]: Unit /etc/systemd/system/systemd-repart.service is masked, ignoring.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket'.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir.mount' → '/etc/systemd/system/var-mnt-workdir.mount'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir\x2dtmp.mount' → '/etc/systemd/system/var-mnt-workdir\x2dtmp.mount'.
systemd[1]: Created symlink '/etc/systemd/system/afterburn-sshkeys.target.requires/afterburn-sshkeys@core.service' → '/usr/lib/systemd/system/afterburn-sshkeys@.service'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket' → '/usr/lib/systemd/system/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket' → '/usr/lib/systemd/system/systemd-resolved-monitor.socket'.
systemd[1]: Populated /etc with preset unit settings.
```

Considering it only happens on first boot and not on every boot I think
the extra information is worth the extra verbosity in the logs just for
that boot.

5 of 6 new or added lines in 1 file covered. (83.33%)

5463 existing lines in 165 files now uncovered.

299151 of 415222 relevant lines covered (72.05%)

702386.45 hits per line

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

89.05
/src/basic/pidfd-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <sys/ioctl.h>
4
#include <threads.h>
5
#include <unistd.h>
6

7
#include "errno-util.h"
8
#include "fd-util.h"
9
#include "fileio.h"
10
#include "missing_fs.h"
11
#include "missing_magic.h"
12
#include "mountpoint-util.h"
13
#include "parse-util.h"
14
#include "pidfd-util.h"
15
#include "process-util.h"
16
#include "stat-util.h"
17
#include "stdio-util.h"
18
#include "string-util.h"
19

20
static int have_pidfs = -1;
21

22
static int pidfd_check_pidfs(int pid_fd) {
40,028✔
23

24
        /* NB: the passed fd *must* be acquired via pidfd_open(), i.e. must be a true pidfd! */
25

26
        if (have_pidfs >= 0)
40,028✔
27
                return have_pidfs;
28

29
        return (have_pidfs = fd_is_fs_type(pid_fd, PID_FS_MAGIC));
18,797✔
30
}
31

32
int pidfd_get_namespace(int fd, unsigned long ns_type_cmd) {
8,279✔
33
        static bool cached_supported = true;
8,279✔
34

35
        /* Obtain the namespace fd from pidfd directly through ioctl(PIDFD_GET_*_NAMESPACE).
36
         *
37
         * Returns -EOPNOTSUPP if ioctl on pidfds are not supported, -ENOPKG if the requested namespace
38
         * is disabled in kernel. (The errno used are different from what kernel returns via ioctl(),
39
         * see below) */
40

41
        assert(fd >= 0);
8,279✔
42

43
        /* If we know ahead of time that pidfs is unavailable, shortcut things. But otherwise we don't
44
         * call pidfd_check_pidfs() here, which is kinda extraneous and our own cache is required
45
         * anyways (pidfs is introduced in kernel 6.9 while ioctl support there is added in 6.11). */
46
        if (have_pidfs == 0 || !cached_supported)
8,279✔
47
                return -EOPNOTSUPP;
48

49
        int nsfd = ioctl(fd, ns_type_cmd);
7,781✔
50
        if (nsfd < 0) {
7,781✔
51
                /* Kernel returns EOPNOTSUPP if the ns type in question is disabled. Hence we need to look
52
                 * at precise errno instead of generic ERRNO_IS_(IOCTL_)NOT_SUPPORTED. */
53
                if (IN_SET(errno, ENOTTY, EINVAL)) {
48✔
54
                        cached_supported = false;
48✔
55
                        return -EOPNOTSUPP;
48✔
56
                }
UNCOV
57
                if (errno == EOPNOTSUPP) /* Translate to something more recognizable */
×
58
                        return -ENOPKG;
59

60
                return -errno;
×
61
        }
62

63
        return nsfd;
64
}
65

66
static int pidfd_get_info(int fd, struct pidfd_info *info) {
52,347✔
67
        static bool cached_supported = true;
52,347✔
68

69
        assert(fd >= 0);
52,347✔
70
        assert(info);
52,347✔
71

72
        if (have_pidfs == 0 || !cached_supported)
52,347✔
73
                return -EOPNOTSUPP;
74

75
        if (ioctl(fd, PIDFD_GET_INFO, info) < 0) {
37,615✔
76
                if (ERRNO_IS_IOCTL_NOT_SUPPORTED(errno)) {
3,159✔
77
                        cached_supported = false;
2,593✔
78
                        return -EOPNOTSUPP;
2,593✔
79
                }
80

81
                return -errno;
566✔
82
        }
83

84
        return 0;
85
}
86

87
static int pidfd_get_pid_fdinfo(int fd, pid_t *ret) {
15,923✔
88
        char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
15,923✔
89
        _cleanup_free_ char *p = NULL;
15,923✔
90
        int r;
15,923✔
91

92
        assert(fd >= 0);
15,923✔
93

94
        xsprintf(path, "/proc/self/fdinfo/%i", fd);
15,923✔
95

96
        r = get_proc_field(path, "Pid", &p);
15,923✔
97
        if (r == -ENOENT)
15,923✔
98
                return -EBADF;
99
        if (r == -ENODATA) /* not a pidfd? */
15,923✔
100
                return -ENOTTY;
101
        if (r < 0)
15,923✔
102
                return r;
103

104
        if (streq(p, "0"))
15,923✔
105
                return -EREMOTE; /* PID is in foreign PID namespace? */
106
        if (streq(p, "-1"))
15,923✔
107
                return -ESRCH;   /* refers to reaped process? */
108

109
        return parse_pid(p, ret);
14,409✔
110
}
111

112
static int pidfd_get_pid_ioctl(int fd, pid_t *ret) {
49,879✔
113
        struct pidfd_info info = { .mask = PIDFD_INFO_PID };
49,879✔
114
        int r;
49,879✔
115

116
        assert(fd >= 0);
49,879✔
117

118
        r = pidfd_get_info(fd, &info);
49,879✔
119
        if (r < 0)
49,879✔
120
                return r;
49,879✔
121

122
        assert(FLAGS_SET(info.mask, PIDFD_INFO_PID));
33,390✔
123

124
        if (ret)
33,390✔
125
                *ret = info.pid;
33,390✔
126
        return 0;
127
}
128

129
int pidfd_get_pid(int fd, pid_t *ret) {
49,879✔
130
        int r;
49,879✔
131

132
        /* Converts a pidfd into a pid. We try ioctl(PIDFD_GET_INFO) (kernel 6.13+) first,
133
         * /proc/self/fdinfo/ as fallback. Well known errors:
134
         *
135
         *    -EBADF   → fd invalid
136
         *    -ESRCH   → fd valid, but process is already reaped
137
         *
138
         * pidfd_get_pid_fdinfo() might additionally fail for other reasons:
139
         *
140
         *    -ENOSYS  → /proc/ not mounted
141
         *    -ENOTTY  → fd valid, but not a pidfd
142
         *    -EREMOTE → fd valid, but pid is in another namespace we cannot translate to the local one
143
         *               (when using PIDFD_GET_INFO this is indistinguishable from -ESRCH)
144
         */
145

146
        assert(fd >= 0);
49,879✔
147

148
        r = pidfd_get_pid_ioctl(fd, ret);
49,879✔
149
        if (r != -EOPNOTSUPP)
49,879✔
150
                return r;
151

152
        return pidfd_get_pid_fdinfo(fd, ret);
15,923✔
153
}
154

155
int pidfd_verify_pid(int pidfd, pid_t pid) {
32,993✔
156
        pid_t current_pid;
32,993✔
157
        int r;
32,993✔
158

159
        assert(pidfd >= 0);
32,993✔
160
        assert(pid > 0);
32,993✔
161

162
        r = pidfd_get_pid(pidfd, &current_pid);
32,993✔
163
        if (r < 0)
32,993✔
164
                return r;
32,993✔
165

166
        return current_pid != pid ? -ESRCH : 0;
30,913✔
167
}
168

169
int pidfd_get_ppid(int fd, pid_t *ret) {
2,414✔
170
        struct pidfd_info info = { .mask = PIDFD_INFO_PID };
2,414✔
171
        int r;
2,414✔
172

173
        assert(fd >= 0);
2,414✔
174

175
        r = pidfd_get_info(fd, &info);
2,414✔
176
        if (r < 0)
2,414✔
177
                return r;
2,414✔
178

179
        assert(FLAGS_SET(info.mask, PIDFD_INFO_PID));
1,021✔
180

181
        if (info.ppid == 0) /* See comments in pid_get_ppid() */
1,021✔
182
                return -EADDRNOTAVAIL;
183

184
        if (ret)
1,021✔
185
                *ret = info.ppid;
1,021✔
186
        return 0;
187
}
188

189
int pidfd_get_uid(int fd, uid_t *ret) {
54✔
190
        struct pidfd_info info = { .mask = PIDFD_INFO_CREDS };
54✔
191
        int r;
54✔
192

193
        assert(fd >= 0);
54✔
194

195
        r = pidfd_get_info(fd, &info);
54✔
196
        if (r < 0)
54✔
197
                return r;
54✔
198

199
        assert(FLAGS_SET(info.mask, PIDFD_INFO_CREDS));
45✔
200

201
        if (ret)
45✔
202
                *ret = info.ruid;
45✔
203
        return 0;
204
}
205

UNCOV
206
int pidfd_get_cgroupid(int fd, uint64_t *ret) {
×
UNCOV
207
        struct pidfd_info info = { .mask = PIDFD_INFO_CGROUPID };
×
UNCOV
208
        int r;
×
209

210
        assert(fd >= 0);
×
211

UNCOV
212
        r = pidfd_get_info(fd, &info);
×
213
        if (r < 0)
×
UNCOV
214
                return r;
×
215

216
        assert(FLAGS_SET(info.mask, PIDFD_INFO_CGROUPID));
×
217

UNCOV
218
        if (ret)
×
219
                *ret = info.cgroupid;
×
220
        return 0;
221
}
222

223
int pidfd_get_inode_id(int fd, uint64_t *ret) {
40,028✔
224
        static bool file_handle_supported = true;
40,028✔
225
        int r;
40,028✔
226

227
        assert(fd >= 0);
40,028✔
228

229
        r = pidfd_check_pidfs(fd);
40,028✔
230
        if (r < 0)
40,028✔
231
                return r;
40,028✔
232
        if (r == 0)
40,028✔
233
                return -EOPNOTSUPP;
234

235
        if (file_handle_supported) {
40,028✔
236
                union {
37,936✔
237
                        struct file_handle file_handle;
238
                        uint8_t space[offsetof(struct file_handle, f_handle) + sizeof(uint64_t)];
239
                } fh = {
37,936✔
240
                        .file_handle.handle_bytes = sizeof(uint64_t),
241
                        .file_handle.handle_type = FILEID_KERNFS,
242
                };
243
                int mnt_id;
37,936✔
244

245
                r = RET_NERRNO(name_to_handle_at(fd, "", &fh.file_handle, &mnt_id, AT_EMPTY_PATH));
37,936✔
246
                if (r >= 0) {
3,663✔
247
                        if (ret)
34,273✔
248
                                *ret = *CAST_ALIGN_PTR(uint64_t, fh.file_handle.f_handle);
34,273✔
249
                        return 0;
34,273✔
250
                }
251
                assert(r != -EOVERFLOW);
3,663✔
252
                if (is_name_to_handle_at_fatal_error(r))
3,663✔
253
                        return r;
254

255
                file_handle_supported = false;
3,663✔
256
        }
257

258
#if SIZEOF_INO_T == 8
259
        struct stat st;
5,755✔
260
        if (fstat(fd, &st) < 0)
5,755✔
UNCOV
261
                return -errno;
×
262

263
        if (ret)
5,755✔
264
                *ret = (uint64_t) st.st_ino;
5,755✔
265
        return 0;
266

267
#elif SIZEOF_INO_T == 4
268
        /* On 32-bit systems (where sizeof(ino_t) == 4), the inode id returned by fstat() cannot be used to
269
         * reliably identify the process, nor can we communicate the origin of the id with the clients.
270
         * Hence let's just refuse to acquire pidfdid through fstat() here. All clients shall also insist on
271
         * the 64-bit id from name_to_handle_at(). */
272
        return -EOPNOTSUPP;
273
#else
274
#  error Unsupported ino_t size
275
#endif
276
}
277

278
int pidfd_get_inode_id_self_cached(uint64_t *ret) {
39,416✔
279
        static thread_local uint64_t cached = 0;
39,416✔
280
        static thread_local pid_t initialized = 0; /* < 0: cached error; == 0: invalid; > 0: valid and pid that was current */
39,416✔
281
        int r;
39,416✔
282

283
        assert(ret);
39,416✔
284

285
        if (initialized == getpid_cached()) {
39,416✔
286
                *ret = cached;
4,614✔
287
                return 0;
4,614✔
288
        }
289
        if (initialized < 0)
34,802✔
290
                return initialized;
291

292
        _cleanup_close_ int fd = pidfd_open(getpid_cached(), 0);
74,218✔
293
        if (fd < 0)
34,802✔
UNCOV
294
                return -errno;
×
295

296
        r = pidfd_get_inode_id(fd, &cached);
34,802✔
297
        if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
34,802✔
UNCOV
298
                return (initialized = -EOPNOTSUPP);
×
299
        if (r < 0)
34,802✔
300
                return r;
301

302
        *ret = cached;
34,802✔
303
        initialized = getpid_cached();
34,802✔
304
        return 0;
34,802✔
305
}
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