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

systemd / systemd / 21269554371

22 Jan 2026 06:13PM UTC coverage: 72.571% (-0.2%) from 72.798%
21269554371

push

github

YHNdnzj
pam_systemd: fix regression introduced in v258 by preserving the FIFO fd

Upstream commit 3180c4d introduced a version incompatibility between
pam_systemd.so v258 and logind v257. This is problematic because such version
mismatches can occur in practice: logind still cannot be restarted during a
systemd package upgrade (it's a long-standing limitation, see
https://github.com/systemd/systemd/issues/17308).

When pam_systemd requests a new session, logind v257 returns a FIFO
fd. pam_systemd.so v258 ignores this fd and closes it. logind interprets the
closure as the session leader exiting and immediately terminates the session.

This patch partially reverts commit 3180c4d and restores the handling of the
FIFO fd in pam_systemd. The change is limited to the D-Bus APIs, since the
varlink API was only introduced in logind v258.

Follow-up for 3180c4d46.

0 of 9 new or added lines in 1 file covered. (0.0%)

1194 existing lines in 35 files now uncovered.

310232 of 427490 relevant lines covered (72.57%)

1165572.69 hits per line

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

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

3
#include <linux/oom.h>
4
#include <pthread.h>
5
#include <spawn.h>
6
#include <stdio.h>
7
#include <sys/mman.h>
8
#include <sys/mount.h>
9
#include <sys/personality.h>
10
#include <sys/prctl.h>
11
#include <sys/wait.h>
12
#include <syslog.h>
13
#include <threads.h>
14
#include <unistd.h>
15
#if HAVE_VALGRIND_VALGRIND_H
16
#include <valgrind/valgrind.h>
17
#endif
18

19
#include "sd-messages.h"
20

21
#include "alloc-util.h"
22
#include "architecture.h"
23
#include "argv-util.h"
24
#include "capability-util.h"
25
#include "cgroup-util.h"
26
#include "dirent-util.h"
27
#include "dlfcn-util.h"
28
#include "env-file.h"
29
#include "errno-util.h"
30
#include "escape.h"
31
#include "fd-util.h"
32
#include "fileio.h"
33
#include "fs-util.h"
34
#include "hostname-util.h"
35
#include "io-util.h"
36
#include "iovec-util.h"
37
#include "locale-util.h"
38
#include "log.h"
39
#include "memory-util.h"
40
#include "mountpoint-util.h"
41
#include "namespace-util.h"
42
#include "nulstr-util.h"
43
#include "parse-util.h"
44
#include "path-util.h"
45
#include "pidfd-util.h"
46
#include "pidref.h"
47
#include "process-util.h"
48
#include "raw-clone.h"
49
#include "rlimit-util.h"
50
#include "signal-util.h"
51
#include "socket-util.h"
52
#include "stat-util.h"
53
#include "stdio-util.h"
54
#include "string-table.h"
55
#include "string-util.h"
56
#include "time-util.h"
57
#include "user-util.h"
58

59
/* The kernel limits userspace processes to TASK_COMM_LEN (16 bytes), but allows higher values for its own
60
 * workers, e.g. "kworker/u9:3-kcryptd/253:0". Let's pick a fixed smallish limit that will work for the kernel.
61
 */
62
#define COMM_MAX_LEN 128
63

64
static int get_process_state(pid_t pid) {
13,097✔
65
        _cleanup_free_ char *line = NULL;
13,097✔
66
        const char *p;
13,097✔
67
        char state;
13,097✔
68
        int r;
13,097✔
69

70
        assert(pid >= 0);
13,097✔
71

72
        /* Shortcut: if we are enquired about our own state, we are obviously running */
73
        if (pid == 0 || pid == getpid_cached())
13,097✔
74
                return (unsigned char) 'R';
×
75

76
        p = procfs_file_alloca(pid, "stat");
13,097✔
77

78
        r = read_one_line_file(p, &line);
13,097✔
79
        if (r == -ENOENT)
13,097✔
80
                return -ESRCH;
81
        if (r < 0)
10,231✔
82
                return r;
83

84
        p = strrchr(line, ')');
10,231✔
85
        if (!p)
10,231✔
86
                return -EIO;
87

88
        p++;
10,231✔
89

90
        if (sscanf(p, " %c", &state) != 1)
10,231✔
91
                return -EIO;
92

93
        return (unsigned char) state;
10,231✔
94
}
95

96
int pid_get_comm(pid_t pid, char **ret) {
43,191✔
97
        _cleanup_free_ char *escaped = NULL, *comm = NULL;
43,191✔
98
        int r;
43,191✔
99

100
        assert(pid >= 0);
43,191✔
101
        assert(ret);
43,191✔
102

103
        if (pid == 0 || pid == getpid_cached()) {
43,191✔
104
                comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */
22,610✔
105
                if (!comm)
22,610✔
106
                        return -ENOMEM;
107

108
                if (prctl(PR_GET_NAME, comm) < 0)
22,610✔
109
                        return -errno;
×
110
        } else {
111
                const char *p;
20,581✔
112

113
                p = procfs_file_alloca(pid, "comm");
20,581✔
114

115
                /* Note that process names of kernel threads can be much longer than TASK_COMM_LEN */
116
                r = read_one_line_file(p, &comm);
20,581✔
117
                if (r == -ENOENT)
20,581✔
118
                        return -ESRCH;
119
                if (r < 0)
16,220✔
120
                        return r;
121
        }
122

123
        escaped = new(char, COMM_MAX_LEN);
38,827✔
124
        if (!escaped)
38,827✔
125
                return -ENOMEM;
126

127
        /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */
128
        cellescape(escaped, COMM_MAX_LEN, comm);
38,827✔
129

130
        *ret = TAKE_PTR(escaped);
38,827✔
131
        return 0;
38,827✔
132
}
133

134
int pidref_get_comm(const PidRef *pid, char **ret) {
186✔
135
        _cleanup_free_ char *comm = NULL;
186✔
136
        int r;
186✔
137

138
        if (!pidref_is_set(pid))
186✔
139
                return -ESRCH;
140

141
        if (pidref_is_remote(pid))
372✔
142
                return -EREMOTE;
143

144
        r = pid_get_comm(pid->pid, &comm);
186✔
145
        if (r < 0)
186✔
146
                return r;
147

148
        r = pidref_verify(pid);
186✔
149
        if (r < 0)
186✔
150
                return r;
151

152
        if (ret)
186✔
153
                *ret = TAKE_PTR(comm);
186✔
154
        return 0;
155
}
156

157
static int pid_get_cmdline_nulstr(
19,413✔
158
                pid_t pid,
159
                size_t max_size,
160
                ProcessCmdlineFlags flags,
161
                char **ret,
162
                size_t *ret_size) {
163

164
        _cleanup_free_ char *t = NULL;
19,413✔
165
        const char *p;
19,413✔
166
        size_t k;
19,413✔
167
        int r;
19,413✔
168

169
        /* Retrieves a process' command line as a "sized nulstr", i.e. possibly without the last NUL, but
170
         * with a specified size.
171
         *
172
         * If PROCESS_CMDLINE_COMM_FALLBACK is specified in flags and the process has no command line set
173
         * (the case for kernel threads), or has a command line that resolves to the empty string, will
174
         * return the "comm" name of the process instead. This will use at most _SC_ARG_MAX bytes of input
175
         * data.
176
         *
177
         * Returns an error, 0 if output was read but is truncated, 1 otherwise.
178
         */
179

180
        p = procfs_file_alloca(pid, "cmdline");
19,629✔
181
        r = read_virtual_file(p, max_size, &t, &k); /* Let's assume that each input byte results in >= 1
19,413✔
182
                                                     * columns of output. We ignore zero-width codepoints. */
183
        if (r == -ENOENT)
19,413✔
184
                return -ESRCH;
185
        if (r < 0)
14,964✔
186
                return r;
187

188
        if (k == 0) {
14,959✔
189
                if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
492✔
190
                        return -ENOENT;
473✔
191

192
                /* Kernel threads have no argv[] */
193
                _cleanup_free_ char *comm = NULL;
19✔
194

195
                r = pid_get_comm(pid, &comm);
19✔
196
                if (r < 0)
19✔
197
                        return r;
198

199
                free(t);
19✔
200
                t = strjoin("[", comm, "]");
19✔
201
                if (!t)
19✔
202
                        return -ENOMEM;
203

204
                k = strlen(t);
19✔
205
                r = k <= max_size;
19✔
206
                if (r == 0) /* truncation */
19✔
207
                        t[max_size] = '\0';
12✔
208
        }
209

210
        if (ret)
14,486✔
211
                *ret = TAKE_PTR(t);
14,486✔
212
        if (ret_size)
14,486✔
213
                *ret_size = k;
14,486✔
214

215
        return r;
216
}
217

218
int pid_get_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
14,743✔
219
        _cleanup_free_ char *t = NULL;
14,743✔
220
        size_t k;
14,743✔
221
        char *ans;
14,743✔
222

223
        assert(pid >= 0);
14,743✔
224
        assert(ret);
14,743✔
225

226
        /* Retrieve and format a command line. See above for discussion of retrieval options.
227
         *
228
         * There are two main formatting modes:
229
         *
230
         * - when PROCESS_CMDLINE_QUOTE is specified, output is quoted in C/Python style. If no shell special
231
         *   characters are present, this output can be copy-pasted into the terminal to execute. UTF-8
232
         *   output is assumed.
233
         *
234
         * - otherwise, a compact non-roundtrippable form is returned. Non-UTF8 bytes are replaced by �. The
235
         *   returned string is of the specified console width at most, abbreviated with an ellipsis.
236
         *
237
         * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
238
         * PROCESS_CMDLINE_COMM_FALLBACK is not specified). Returns 0 and sets *line otherwise. */
239

240
        int full = pid_get_cmdline_nulstr(pid, max_columns, flags, &t, &k);
14,743✔
241
        if (full < 0)
14,743✔
242
                return full;
243

244
        if (flags & (PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_QUOTE_POSIX)) {
9,891✔
245
                ShellEscapeFlags shflags = SHELL_ESCAPE_EMPTY |
9,517✔
246
                        FLAGS_SET(flags, PROCESS_CMDLINE_QUOTE_POSIX) * SHELL_ESCAPE_POSIX;
9,517✔
247

248
                assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
9,517✔
249

250
                _cleanup_strv_free_ char **args = NULL;
9,517✔
251

252
                /* Drop trailing NULs, otherwise strv_parse_nulstr() adds additional empty strings at the end.
253
                 * See also issue #21186. */
254
                args = strv_parse_nulstr_full(t, k, /* drop_trailing_nuls= */ true);
9,517✔
255
                if (!args)
9,517✔
256
                        return -ENOMEM;
257

258
                ans = quote_command_line(args, shflags);
9,517✔
259
                if (!ans)
9,517✔
260
                        return -ENOMEM;
261
        } else {
262
                /* Arguments are separated by NULs. Let's replace those with spaces. */
263
                for (size_t i = 0; i < k - 1; i++)
17,988✔
264
                        if (t[i] == '\0')
17,614✔
265
                                t[i] = ' ';
652✔
266

267
                delete_trailing_chars(t, WHITESPACE);
374✔
268

269
                bool eight_bit = (flags & PROCESS_CMDLINE_USE_LOCALE) && !is_locale_utf8();
374✔
270

271
                ans = escape_non_printable_full(t, max_columns,
1,122✔
272
                                                eight_bit * XESCAPE_8_BIT | !full * XESCAPE_FORCE_ELLIPSIS);
694✔
273
                if (!ans)
374✔
274
                        return -ENOMEM;
275

276
                ans = str_realloc(ans);
374✔
277
        }
278

279
        *ret = ans;
9,891✔
280
        return 0;
9,891✔
281
}
282

283
int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
46✔
284
        _cleanup_free_ char *s = NULL;
46✔
285
        int r;
46✔
286

287
        if (!pidref_is_set(pid))
46✔
288
                return -ESRCH;
289

290
        if (pidref_is_remote(pid))
92✔
291
                return -EREMOTE;
292

293
        r = pid_get_cmdline(pid->pid, max_columns, flags, &s);
46✔
294
        if (r < 0)
46✔
295
                return r;
296

297
        r = pidref_verify(pid);
46✔
298
        if (r < 0)
46✔
299
                return r;
300

301
        if (ret)
46✔
302
                *ret = TAKE_PTR(s);
46✔
303
        return 0;
304
}
305

306
int pid_get_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) {
4,670✔
307
        _cleanup_free_ char *t = NULL;
4,670✔
308
        char **args;
4,670✔
309
        size_t k;
4,670✔
310
        int r;
4,670✔
311

312
        assert(pid >= 0);
4,670✔
313
        assert((flags & ~PROCESS_CMDLINE_COMM_FALLBACK) == 0);
4,670✔
314
        assert(ret);
4,670✔
315

316
        r = pid_get_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k);
4,670✔
317
        if (r < 0)
4,670✔
318
                return r;
319

320
        args = strv_parse_nulstr_full(t, k, /* drop_trailing_nuls= */ true);
4,595✔
321
        if (!args)
4,595✔
322
                return -ENOMEM;
323

324
        *ret = args;
4,595✔
325
        return 0;
4,595✔
326
}
327

328
int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char ***ret) {
×
329
        _cleanup_strv_free_ char **args = NULL;
×
330
        int r;
×
331

332
        if (!pidref_is_set(pid))
×
333
                return -ESRCH;
334

335
        if (pidref_is_remote(pid))
×
336
                return -EREMOTE;
337

338
        r = pid_get_cmdline_strv(pid->pid, flags, &args);
×
339
        if (r < 0)
×
340
                return r;
341

342
        r = pidref_verify(pid);
×
343
        if (r < 0)
×
344
                return r;
345

346
        if (ret)
×
347
                *ret = TAKE_PTR(args);
×
348

349
        return 0;
350
}
351

352
int container_get_leader(const char *machine, pid_t *pid) {
35✔
353
        _cleanup_free_ char *s = NULL, *class = NULL;
35✔
354
        const char *p;
35✔
355
        pid_t leader;
35✔
356
        int r;
35✔
357

358
        assert(machine);
35✔
359
        assert(pid);
35✔
360

361
        if (streq(machine, ".host")) {
35✔
362
                *pid = 1;
1✔
363
                return 0;
1✔
364
        }
365

366
        if (!hostname_is_valid(machine, 0))
34✔
367
                return -EINVAL;
368

369
        p = strjoina("/run/systemd/machines/", machine);
170✔
370
        r = parse_env_file(NULL, p,
34✔
371
                           "LEADER", &s,
372
                           "CLASS", &class);
373
        if (r == -ENOENT)
34✔
374
                return -EHOSTDOWN;
375
        if (r < 0)
34✔
376
                return r;
377
        if (!s)
34✔
378
                return -EIO;
379

380
        if (!streq_ptr(class, "container"))
34✔
381
                return -EIO;
382

383
        r = parse_pid(s, &leader);
34✔
384
        if (r < 0)
34✔
385
                return r;
386
        if (leader <= 1)
34✔
387
                return -EIO;
388

389
        *pid = leader;
34✔
390
        return 0;
34✔
391
}
392

393
int pid_is_kernel_thread(pid_t pid) {
3,903✔
394
        int r;
3,903✔
395

396
        if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
3,903✔
397
                return 0;
3,903✔
398
        if (!pid_is_valid(pid))
3,878✔
399
                return -EINVAL;
400

401
        const char *p = procfs_file_alloca(pid, "stat");
3,878✔
402
        _cleanup_free_ char *line = NULL;
3,878✔
403
        r = read_one_line_file(p, &line);
3,878✔
404
        if (r == -ENOENT)
3,878✔
405
                return -ESRCH;
406
        if (r < 0)
3,878✔
407
                return r;
408

409
        /* Skip past the comm field */
410
        char *q = strrchr(line, ')');
3,878✔
411
        if (!q)
3,878✔
412
                return -EINVAL;
413
        q++;
3,878✔
414

415
        /* Skip 6 fields to reach the flags field */
416
        for (size_t i = 0; i < 6; i++) {
27,146✔
417
                size_t l = strspn(q, WHITESPACE);
23,268✔
418
                if (l < 1)
23,268✔
419
                        return -EINVAL;
420
                q += l;
23,268✔
421

422
                l = strcspn(q, WHITESPACE);
23,268✔
423
                if (l < 1)
23,268✔
424
                        return -EINVAL;
425
                q += l;
23,268✔
426
        }
427

428
        /* Skip preceding whitespace */
429
        size_t l = strspn(q, WHITESPACE);
3,878✔
430
        if (l < 1)
3,878✔
431
                return -EINVAL;
432
        q += l;
3,878✔
433

434
        /* Truncate the rest */
435
        l = strcspn(q, WHITESPACE);
3,878✔
436
        if (l < 1)
3,878✔
437
                return -EINVAL;
438
        q[l] = 0;
3,878✔
439

440
        unsigned long long flags;
3,878✔
441
        r = safe_atollu(q, &flags);
3,878✔
442
        if (r < 0)
3,878✔
443
                return r;
444

445
        return !!(flags & PF_KTHREAD);
3,878✔
446
}
447

448
int pidref_is_kernel_thread(const PidRef *pid) {
1,622✔
449
        int result, r;
1,622✔
450

451
        if (!pidref_is_set(pid))
1,622✔
452
                return -ESRCH;
453

454
        if (pidref_is_remote(pid))
1,622✔
455
                return -EREMOTE;
456

457
        result = pid_is_kernel_thread(pid->pid);
1,622✔
458
        if (result < 0)
1,622✔
459
                return result;
460

461
        r = pidref_verify(pid); /* Verify that the PID wasn't reused since */
1,622✔
462
        if (r < 0)
1,622✔
463
                return r;
×
464

465
        return result;
466
}
467

468
static int get_process_link_contents(pid_t pid, const char *proc_file, char **ret) {
14,214✔
469
        const char *p;
14,214✔
470
        int r;
14,214✔
471

472
        assert(proc_file);
14,214✔
473

474
        p = procfs_file_alloca(pid, proc_file);
14,218✔
475

476
        r = readlink_malloc(p, ret);
14,214✔
477
        return (r == -ENOENT && proc_mounted() > 0) ? -ESRCH : r;
14,214✔
478
}
479

480
int get_process_exe(pid_t pid, char **ret) {
14,188✔
481
        char *d;
14,188✔
482
        int r;
14,188✔
483

484
        assert(pid >= 0);
14,188✔
485

486
        r = get_process_link_contents(pid, "exe", ret);
14,188✔
487
        if (r < 0)
14,188✔
488
                return r;
489

490
        if (ret) {
9,605✔
491
                d = endswith(*ret, " (deleted)");
9,605✔
492
                if (d)
9,605✔
493
                        *d = '\0';
×
494
        }
495

496
        return 0;
497
}
498

499
int pid_get_uid(pid_t pid, uid_t *ret) {
4,071✔
500
        int r;
4,071✔
501

502
        assert(pid >= 0);
4,071✔
503
        assert(ret);
4,071✔
504

505
        if (pid == 0 || pid == getpid_cached()) {
4,071✔
506
                *ret = getuid();
2✔
507
                return 0;
4,071✔
508
        }
509

510
        _cleanup_free_ char *v = NULL;
4,069✔
511
        r = procfs_file_get_field(pid, "status", "Uid", &v);
4,069✔
512
        if (r == -ENOENT)
4,069✔
513
                return -ESRCH;
514
        if (r < 0)
175✔
515
                return r;
516

517
        return parse_uid(v, ret);
175✔
518
}
519

520
int pidref_get_uid(const PidRef *pid, uid_t *ret) {
69✔
521
        int r;
69✔
522

523
        if (!pidref_is_set(pid))
69✔
524
                return -ESRCH;
69✔
525

526
        if (pidref_is_remote(pid))
69✔
527
                return -EREMOTE;
528

529
        if (pid->fd >= 0) {
69✔
530
                r = pidfd_get_uid(pid->fd, ret);
69✔
531
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
69✔
532
                        return r;
533
        }
534

535
        uid_t uid;
3✔
536
        r = pid_get_uid(pid->pid, &uid);
3✔
537
        if (r < 0)
3✔
538
                return r;
539

540
        r = pidref_verify(pid);
3✔
541
        if (r < 0)
3✔
542
                return r;
543

544
        if (ret)
3✔
545
                *ret = uid;
3✔
546
        return 0;
547
}
548

549
int get_process_gid(pid_t pid, gid_t *ret) {
4,068✔
550
        int r;
4,068✔
551

552
        assert(pid >= 0);
4,068✔
553
        assert(ret);
4,068✔
554

555
        if (pid == 0 || pid == getpid_cached()) {
4,068✔
556
                *ret = getgid();
1✔
557
                return 0;
4,068✔
558
        }
559

560
        _cleanup_free_ char *v = NULL;
4,067✔
561
        r = procfs_file_get_field(pid, "status", "Gid", &v);
4,067✔
562
        if (r == -ENOENT)
4,067✔
563
                return -ESRCH;
564
        if (r < 0)
172✔
565
                return r;
566

567
        return parse_gid(v, ret);
4,067✔
568
}
569

570
int get_process_cwd(pid_t pid, char **ret) {
13✔
571
        assert(pid >= 0);
13✔
572

573
        if (pid == 0 || pid == getpid_cached())
13✔
574
                return safe_getcwd(ret);
×
575

576
        return get_process_link_contents(pid, "cwd", ret);
13✔
577
}
578

579
int get_process_root(pid_t pid, char **ret) {
13✔
580
        assert(pid >= 0);
13✔
581
        return get_process_link_contents(pid, "root", ret);
13✔
582
}
583

584
#define ENVIRONMENT_BLOCK_MAX (5U*1024U*1024U)
585

586
int get_process_environ(pid_t pid, char **ret) {
15✔
587
        _cleanup_fclose_ FILE *f = NULL;
15✔
588
        _cleanup_free_ char *outcome = NULL;
15✔
589
        size_t sz = 0;
15✔
590
        const char *p;
15✔
591
        int r;
15✔
592

593
        assert(pid >= 0);
15✔
594
        assert(ret);
15✔
595

596
        p = procfs_file_alloca(pid, "environ");
15✔
597

598
        r = fopen_unlocked(p, "re", &f);
15✔
599
        if (r == -ENOENT)
15✔
600
                return -ESRCH;
601
        if (r < 0)
15✔
602
                return r;
603

604
        for (;;) {
6,608✔
605
                char c;
6,623✔
606

607
                if (sz >= ENVIRONMENT_BLOCK_MAX)
6,623✔
608
                        return -ENOBUFS;
×
609

610
                if (!GREEDY_REALLOC(outcome, sz + 5))
6,623✔
611
                        return -ENOMEM;
612

613
                r = safe_fgetc(f, &c);
6,623✔
614
                if (r < 0)
6,623✔
615
                        return r;
616
                if (r == 0)
6,623✔
617
                        break;
618

619
                if (c == '\0')
6,608✔
620
                        outcome[sz++] = '\n';
235✔
621
                else
622
                        sz += cescape_char(c, outcome + sz);
6,373✔
623
        }
624

625
        outcome[sz] = '\0';
15✔
626
        *ret = TAKE_PTR(outcome);
15✔
627

628
        return 0;
15✔
629
}
630

631
int pid_get_ppid(pid_t pid, pid_t *ret) {
1,529✔
632
        _cleanup_free_ char *line = NULL;
1,529✔
633
        unsigned long ppid;
1,529✔
634
        const char *p;
1,529✔
635
        int r;
1,529✔
636

637
        assert(pid >= 0);
1,529✔
638

639
        if (pid == 0)
1,529✔
640
                pid = getpid_cached();
1✔
641
        if (pid == 1) /* PID 1 has no parent, shortcut this case */
1,529✔
642
                return -EADDRNOTAVAIL;
643

644
        if (pid == getpid_cached()) {
1,525✔
645
                if (ret)
6✔
646
                        *ret = getppid();
6✔
647
                return 0;
6✔
648
        }
649

650
        p = procfs_file_alloca(pid, "stat");
1,519✔
651
        r = read_one_line_file(p, &line);
1,519✔
652
        if (r == -ENOENT)
1,519✔
653
                return -ESRCH;
654
        if (r < 0)
1,518✔
655
                return r;
656

657
        /* Let's skip the pid and comm fields. The latter is enclosed in () but does not escape any () in its
658
         * value, so let's skip over it manually */
659

660
        p = strrchr(line, ')');
1,518✔
661
        if (!p)
1,518✔
662
                return -EIO;
663
        p++;
1,518✔
664

665
        if (sscanf(p, " "
1,518✔
666
                   "%*c "  /* state */
667
                   "%lu ", /* ppid */
668
                   &ppid) != 1)
669
                return -EIO;
670

671
        /* If ppid is zero the process has no parent. Which might be the case for PID 1 (caught above)
672
         * but also for processes originating in other namespaces that are inserted into a pidns.
673
         * Return a recognizable error in this case. */
674
        if (ppid == 0)
1,518✔
675
                return -EADDRNOTAVAIL;
676

677
        if ((pid_t) ppid < 0 || (unsigned long) (pid_t) ppid != ppid)
1,518✔
678
                return -ERANGE;
679

680
        if (ret)
1,518✔
681
                *ret = (pid_t) ppid;
1,518✔
682

683
        return 0;
684
}
685

686
int pidref_get_ppid(const PidRef *pidref, pid_t *ret) {
2,588✔
687
        int r;
2,588✔
688

689
        if (!pidref_is_set(pidref))
2,588✔
690
                return -ESRCH;
2,588✔
691

692
        if (pidref_is_remote(pidref))
2,588✔
693
                return -EREMOTE;
694

695
        if (pidref->fd >= 0) {
2,588✔
696
                r = pidfd_get_ppid(pidref->fd, ret);
2,588✔
697
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
2,588✔
698
                        return r;
699
        }
700

701
        pid_t ppid;
1,523✔
702
        r = pid_get_ppid(pidref->pid, ret ? &ppid : NULL);
1,523✔
703
        if (r < 0)
1,523✔
704
                return r;
705

706
        r = pidref_verify(pidref);
1,522✔
707
        if (r < 0)
1,522✔
708
                return r;
709

710
        if (ret)
1,522✔
711
                *ret = ppid;
1,522✔
712
        return 0;
713
}
714

715
int pidref_get_ppid_as_pidref(const PidRef *pidref, PidRef *ret) {
11✔
716
        pid_t ppid;
11✔
717
        int r;
11✔
718

719
        assert(ret);
11✔
720

721
        r = pidref_get_ppid(pidref, &ppid);
11✔
722
        if (r < 0)
11✔
723
                return r;
11✔
724

725
        for (unsigned attempt = 0; attempt < 16; attempt++) {
10✔
726
                _cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
10✔
727

728
                r = pidref_set_pid(&parent, ppid);
10✔
729
                if (r < 0)
10✔
730
                        return r;
731

732
                /* If we have a pidfd of the original PID, let's verify that the process we acquired really
733
                 * is the parent still */
734
                if (pidref->fd >= 0) {
10✔
735
                        r = pidref_get_ppid(pidref, &ppid);
10✔
736
                        if (r < 0)
10✔
737
                                return r;
738

739
                        /* Did the PPID change since we queried it? if so we might have pinned the wrong
740
                         * process, if its PID got reused by now. Let's try again */
741
                        if (parent.pid != ppid)
10✔
742
                                continue;
×
743
                }
744

745
                *ret = TAKE_PIDREF(parent);
10✔
746
                return 0;
10✔
747
        }
748

749
        /* Give up after 16 tries */
750
        return -ENOTRECOVERABLE;
751
}
752

753
int pid_get_start_time(pid_t pid, usec_t *ret) {
673✔
754
        _cleanup_free_ char *line = NULL;
673✔
755
        const char *p;
673✔
756
        int r;
673✔
757

758
        assert(pid >= 0);
673✔
759

760
        p = procfs_file_alloca(pid, "stat");
673✔
761
        r = read_one_line_file(p, &line);
673✔
762
        if (r == -ENOENT)
673✔
763
                return -ESRCH;
764
        if (r < 0)
673✔
765
                return r;
766

767
        /* Let's skip the pid and comm fields. The latter is enclosed in () but does not escape any () in its
768
         * value, so let's skip over it manually */
769

770
        p = strrchr(line, ')');
673✔
771
        if (!p)
673✔
772
                return -EIO;
773
        p++;
673✔
774

775
        unsigned long llu;
673✔
776

777
        if (sscanf(p, " "
673✔
778
                   "%*c " /* state */
779
                   "%*u " /* ppid */
780
                   "%*u " /* pgrp */
781
                   "%*u " /* session */
782
                   "%*u " /* tty_nr */
783
                   "%*u " /* tpgid */
784
                   "%*u " /* flags */
785
                   "%*u " /* minflt */
786
                   "%*u " /* cminflt */
787
                   "%*u " /* majflt */
788
                   "%*u " /* cmajflt */
789
                   "%*u " /* utime */
790
                   "%*u " /* stime */
791
                   "%*u " /* cutime */
792
                   "%*u " /* cstime */
793
                   "%*i " /* priority */
794
                   "%*i " /* nice */
795
                   "%*u " /* num_threads */
796
                   "%*u " /* itrealvalue */
797
                   "%lu ", /* starttime */
798
                   &llu) != 1)
799
                return -EIO;
800

801
        if (ret)
673✔
802
                *ret = jiffies_to_usec(llu); /* CLOCK_BOOTTIME */
673✔
803

804
        return 0;
805
}
806

807
int pidref_get_start_time(const PidRef *pid, usec_t *ret) {
673✔
808
        usec_t t;
673✔
809
        int r;
673✔
810

811
        if (!pidref_is_set(pid))
673✔
812
                return -ESRCH;
673✔
813

814
        if (pidref_is_remote(pid))
673✔
815
                return -EREMOTE;
816

817
        r = pid_get_start_time(pid->pid, ret ? &t : NULL);
673✔
818
        if (r < 0)
673✔
819
                return r;
820

821
        r = pidref_verify(pid);
673✔
822
        if (r < 0)
673✔
823
                return r;
824

825
        if (ret)
673✔
826
                *ret = t;
673✔
827

828
        return 0;
829
}
830

831
int get_process_umask(pid_t pid, mode_t *ret) {
24,708✔
832
        _cleanup_free_ char *m = NULL;
24,708✔
833
        int r;
24,708✔
834

835
        assert(pid >= 0);
24,708✔
836
        assert(ret);
24,708✔
837

838
        r = procfs_file_get_field(pid, "status", "Umask", &m);
24,708✔
839
        if (r == -ENOENT)
24,708✔
840
                return -ESRCH;
841
        if (r < 0)
24,708✔
842
                return r;
843

844
        return parse_mode(m, ret);
24,708✔
845
}
846

847
/*
848
 * Return values:
849
 * < 0 : pidref_wait_for_terminate() failed to get the state of the
850
 *       process, the process was terminated by a signal, or
851
 *       failed for an unknown reason.
852
 * >=0 : The process terminated normally, and its exit code is
853
 *       returned.
854
 *
855
 * That is, success is indicated by a return value of zero, and an
856
 * error is indicated by a non-zero value.
857
 *
858
 * A warning is emitted if the process terminates abnormally,
859
 * and also if it returns non-zero unless check_exit_code is true.
860
 */
861
int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFlags flags) {
7,062✔
862
        int r;
7,062✔
863

864
        if (!pidref_is_set(pidref))
7,062✔
865
                return -ESRCH;
7,062✔
866
        if (pidref_is_remote(pidref))
14,124✔
867
                return -EREMOTE;
868
        if (pidref->pid == 1 || pidref_is_self(pidref))
7,062✔
869
                return -ECHILD;
×
870

871
        _cleanup_free_ char *buffer = NULL;
7,062✔
872
        if (!name) {
7,062✔
873
                r = pidref_get_comm(pidref, &buffer);
2✔
874
                if (r < 0)
2✔
875
                        log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pidref->pid);
×
876
                else
877
                        name = buffer;
2✔
878
        }
879

880
        int prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG;
7,062✔
881

882
        siginfo_t status;
7,062✔
883
        r = pidref_wait_for_terminate(pidref, &status);
7,062✔
884
        if (r < 0)
7,062✔
885
                return log_full_errno(prio, r, "Failed to wait for '%s': %m", strna(name));
×
886

887
        if (status.si_code == CLD_EXITED) {
7,062✔
888
                if (status.si_status != EXIT_SUCCESS)
7,062✔
889
                        log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
64✔
890
                                 "'%s' failed with exit status %i.", strna(name), status.si_status);
891
                else
892
                        log_debug("'%s' succeeded.", name);
6,998✔
893

894
                return status.si_status;
7,062✔
895

896
        } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED))
×
897
                return log_full_errno(prio, SYNTHETIC_ERRNO(EPROTO),
×
898
                                      "'%s' terminated by signal %s.", strna(name), signal_to_string(status.si_status));
899

900
        return log_full_errno(prio, SYNTHETIC_ERRNO(EPROTO),
×
901
                              "'%s' failed due to unknown reason.", strna(name));
902
}
903

904
int kill_and_sigcont(pid_t pid, int sig) {
×
905
        int r;
×
906

907
        r = RET_NERRNO(kill(pid, sig));
×
908

909
        /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't
910
         * affected by a process being suspended anyway. */
911
        if (r >= 0 && !IN_SET(sig, SIGCONT, SIGKILL))
×
912
                (void) kill(pid, SIGCONT);
×
913

914
        return r;
×
915
}
916

917
int getenv_for_pid(pid_t pid, const char *field, char **ret) {
4,846✔
918
        _cleanup_fclose_ FILE *f = NULL;
4,846✔
919
        const char *path;
4,846✔
920
        size_t sum = 0;
4,846✔
921
        int r;
4,846✔
922

923
        assert(pid >= 0);
4,846✔
924
        assert(field);
4,846✔
925
        assert(ret);
4,846✔
926

927
        if (pid == 0 || pid == getpid_cached())
4,846✔
928
                return strdup_to_full(ret, getenv(field));
14✔
929

930
        if (!pid_is_valid(pid))
4,832✔
931
                return -EINVAL;
932

933
        path = procfs_file_alloca(pid, "environ");
4,832✔
934

935
        r = fopen_unlocked(path, "re", &f);
4,832✔
936
        if (r == -ENOENT)
4,832✔
937
                return -ESRCH;
938
        if (r < 0)
4,425✔
939
                return r;
940

941
        for (;;) {
51,211✔
942
                _cleanup_free_ char *line = NULL;
24,104✔
943
                const char *match;
27,125✔
944

945
                if (sum > ENVIRONMENT_BLOCK_MAX) /* Give up searching eventually */
27,125✔
946
                        return -ENOBUFS;
947

948
                r = read_nul_string(f, LONG_LINE_MAX, &line);
27,125✔
949
                if (r < 0)
27,125✔
950
                        return r;
951
                if (r == 0)  /* EOF */
27,125✔
952
                        break;
953

954
                sum += r;
24,104✔
955

956
                match = startswith(line, field);
24,104✔
957
                if (match && *match == '=')
24,104✔
958
                        return strdup_to_full(ret, match + 1);
18✔
959
        }
960

961
        *ret = NULL;
3,021✔
962
        return 0;
3,021✔
963
}
964

965
int pidref_is_my_child(PidRef *pid) {
2,566✔
966
        int r;
2,566✔
967

968
        if (!pidref_is_set(pid))
2,566✔
969
                return -ESRCH;
2,566✔
970

971
        if (pidref_is_remote(pid))
2,566✔
972
                return -EREMOTE;
973

974
        if (pid->pid == 1 || pidref_is_self(pid))
2,566✔
975
                return false;
×
976

977
        pid_t ppid;
2,566✔
978
        r = pidref_get_ppid(pid, &ppid);
2,566✔
979
        if (r == -EADDRNOTAVAIL) /* if this process is outside of our pidns, it is definitely not our child */
2,566✔
980
                return false;
981
        if (r < 0)
2,566✔
982
                return r;
983

984
        return ppid == getpid_cached();
2,566✔
985
}
986

987
int pid_is_my_child(pid_t pid) {
×
988

989
        if (pid == 0)
×
990
                return false;
×
991

992
        return pidref_is_my_child(&PIDREF_MAKE_FROM_PID(pid));
×
993
}
994

995
int pidref_is_unwaited(PidRef *pid) {
8,860✔
996
        int r;
8,860✔
997

998
        /* Checks whether a PID is still valid at all, including a zombie */
999

1000
        if (!pidref_is_set(pid))
8,860✔
1001
                return -ESRCH;
1002

1003
        if (pidref_is_remote(pid))
8,859✔
1004
                return -EREMOTE;
1005

1006
        if (pid->pid == 1 || pidref_is_self(pid))
8,859✔
1007
                return true;
1✔
1008

1009
        r = pidref_kill(pid, 0);
8,858✔
1010
        if (r == -ESRCH)
8,858✔
1011
                return false;
1012
        if (r < 0)
2,226✔
1013
                return r;
198✔
1014

1015
        return true;
1016
}
1017

1018
int pid_is_unwaited(pid_t pid) {
8,193✔
1019

1020
        if (pid == 0)
8,193✔
1021
                return true;
8,193✔
1022

1023
        return pidref_is_unwaited(&PIDREF_MAKE_FROM_PID(pid));
8,193✔
1024
}
1025

1026
int pid_is_alive(pid_t pid) {
13,099✔
1027
        int r;
13,099✔
1028

1029
        /* Checks whether a PID is still valid and not a zombie */
1030

1031
        if (pid < 0)
13,099✔
1032
                return -ESRCH;
1033

1034
        if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
13,098✔
1035
                return true;
1036

1037
        if (pid == getpid_cached())
13,098✔
1038
                return true;
1039

1040
        r = get_process_state(pid);
13,097✔
1041
        if (r == -ESRCH)
13,097✔
1042
                return false;
1043
        if (r < 0)
10,231✔
1044
                return r;
1045

1046
        return r != 'Z';
10,231✔
1047
}
1048

1049
int pidref_is_alive(const PidRef *pidref) {
13,094✔
1050
        int r, result;
13,094✔
1051

1052
        if (!pidref_is_set(pidref))
13,094✔
1053
                return -ESRCH;
1054

1055
        if (pidref_is_remote(pidref))
13,094✔
1056
                return -EREMOTE;
1057

1058
        result = pid_is_alive(pidref->pid);
13,094✔
1059
        if (result < 0) {
13,094✔
1060
                assert(result != -ESRCH);
×
1061
                return result;
1062
        }
1063

1064
        r = pidref_verify(pidref);
13,094✔
1065
        if (r == -ESRCH)
13,094✔
1066
                return false;
1067
        if (r < 0)
10,226✔
1068
                return r;
×
1069

1070
        return result;
1071
}
1072

1073
int pidref_from_same_root_fs(PidRef *a, PidRef *b) {
20✔
1074
        _cleanup_(pidref_done) PidRef self = PIDREF_NULL;
×
1075
        int r;
20✔
1076

1077
        /* Checks if the two specified processes have the same root fs. Either can be specified as NULL in
1078
         * which case we'll check against ourselves. */
1079

1080
        if (!a || !b) {
20✔
1081
                r = pidref_set_self(&self);
×
1082
                if (r < 0)
×
1083
                        return r;
1084
                if (!a)
×
1085
                        a = &self;
×
1086
                if (!b)
×
1087
                        b = &self;
×
1088
        }
1089

1090
        if (!pidref_is_set(a) || !pidref_is_set(b))
20✔
1091
                return -ESRCH;
×
1092

1093
        /* If one of the two processes have the same root they cannot have the same root fs, but if both of
1094
         * them do we don't know */
1095
        if (pidref_is_remote(a) && pidref_is_remote(b))
20✔
1096
                return -EREMOTE;
1097
        if (pidref_is_remote(a) || pidref_is_remote(b))
60✔
1098
                return false;
1099

1100
        if (pidref_equal(a, b))
20✔
1101
                return true;
1102

1103
        const char *roota = procfs_file_alloca(a->pid, "root");
18✔
1104
        const char *rootb = procfs_file_alloca(b->pid, "root");
18✔
1105

1106
        int result = inode_same(roota, rootb, 0);
18✔
1107
        if (result == -ENOENT)
18✔
1108
                return proc_mounted() == 0 ? -ENOSYS : -ESRCH;
×
1109
        if (result < 0)
18✔
1110
                return result;
1111

1112
        r = pidref_verify(a);
18✔
1113
        if (r < 0)
18✔
1114
                return r;
1115
        r = pidref_verify(b);
18✔
1116
        if (r < 0)
18✔
1117
                return r;
×
1118

1119
        return result;
1120
}
1121

1122
bool is_main_thread(void) {
7,409,901✔
1123
        static thread_local int cached = -1;
7,409,901✔
1124

1125
        if (cached < 0)
7,409,901✔
1126
                cached = getpid_cached() == gettid();
56,118✔
1127

1128
        return cached;
7,409,901✔
1129
}
1130

1131
bool oom_score_adjust_is_valid(int oa) {
6,805✔
1132
        return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
6,805✔
1133
}
1134

1135
unsigned long personality_from_string(const char *s) {
9✔
1136
        Architecture architecture;
9✔
1137

1138
        if (!s)
9✔
1139
                return PERSONALITY_INVALID;
1140

1141
        /* Parse a personality specifier. We use our own identifiers that indicate specific ABIs, rather than just
1142
         * hints regarding the register size, since we want to keep things open for multiple locally supported ABIs for
1143
         * the same register size. */
1144

1145
        architecture = architecture_from_string(s);
8✔
1146
        if (architecture < 0)
8✔
1147
                return PERSONALITY_INVALID;
1148

1149
        if (architecture == native_architecture())
6✔
1150
                return PER_LINUX;
1151
#ifdef ARCHITECTURE_SECONDARY
1152
        if (architecture == ARCHITECTURE_SECONDARY)
3✔
1153
                return PER_LINUX32;
2✔
1154
#endif
1155

1156
        return PERSONALITY_INVALID;
1157
}
1158

1159
const char* personality_to_string(unsigned long p) {
2,954✔
1160
        Architecture architecture = _ARCHITECTURE_INVALID;
2,954✔
1161

1162
        if (p == PER_LINUX)
2,954✔
1163
                architecture = native_architecture();
1164
#ifdef ARCHITECTURE_SECONDARY
1165
        else if (p == PER_LINUX32)
2,949✔
1166
                architecture = ARCHITECTURE_SECONDARY;
1167
#endif
1168

1169
        if (architecture < 0)
1170
                return NULL;
1171

1172
        return architecture_to_string(architecture);
7✔
1173
}
1174

1175
int safe_personality(unsigned long p) {
1,486✔
1176
        int ret;
1,486✔
1177

1178
        /* So here's the deal, personality() is weirdly defined by glibc. In some cases it returns a failure via errno,
1179
         * and in others as negative return value containing an errno-like value. Let's work around this: this is a
1180
         * wrapper that uses errno if it is set, and uses the return value otherwise. And then it sets both errno and
1181
         * the return value indicating the same issue, so that we are definitely on the safe side.
1182
         *
1183
         * See https://github.com/systemd/systemd/issues/6737 */
1184

1185
        errno = 0;
1,486✔
1186
        ret = personality(p);
1,486✔
1187
        if (ret < 0) {
1,486✔
1188
                if (errno != 0)
12✔
1189
                        return -errno;
12✔
1190

1191
                errno = -ret;
×
1192
        }
1193

1194
        return ret;
1195
}
1196

1197
int opinionated_personality(unsigned long *ret) {
1,471✔
1198
        int current;
1,471✔
1199

1200
        /* Returns the current personality, or PERSONALITY_INVALID if we can't determine it. This function is a bit
1201
         * opinionated though, and ignores all the finer-grained bits and exotic personalities, only distinguishing the
1202
         * two most relevant personalities: PER_LINUX and PER_LINUX32. */
1203

1204
        current = safe_personality(PERSONALITY_INVALID);
1,471✔
1205
        if (current < 0)
1,471✔
1206
                return current;
1207

1208
        if (((unsigned long) current & OPINIONATED_PERSONALITY_MASK) == PER_LINUX32)
1,471✔
1209
                *ret = PER_LINUX32;
×
1210
        else
1211
                *ret = PER_LINUX;
1,471✔
1212

1213
        return 0;
1214
}
1215

1216
void valgrind_summary_hack(void) {
39✔
1217
#if HAVE_VALGRIND_VALGRIND_H
1218
        if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) {
1219
                pid_t pid;
1220
                pid = raw_clone(SIGCHLD);
1221
                if (pid < 0)
1222
                        log_struct_errno(
1223
                                LOG_EMERG, errno,
1224
                                LOG_MESSAGE_ID(SD_MESSAGE_VALGRIND_HELPER_FORK_STR),
1225
                                LOG_MESSAGE("Failed to fork off valgrind helper: %m"));
1226
                else if (pid == 0)
1227
                        exit(EXIT_SUCCESS);
1228
                else {
1229
                        log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
1230
                        _cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
1231
                        (void) pidref_set_pid(&pidref, pid);
1232
                        (void) pidref_wait_for_terminate(&pidref, NULL);
1233
                }
1234
        }
1235
#endif
1236
}
39✔
1237

1238
int pid_compare_func(const pid_t *a, const pid_t *b) {
1,599✔
1239
        /* Suitable for usage in qsort() */
1240
        return CMP(*a, *b);
1,599✔
1241
}
1242

1243
bool nice_is_valid(int n) {
876✔
1244
        return n >= PRIO_MIN && n < PRIO_MAX;
876✔
1245
}
1246

1247
bool sched_policy_is_valid(int policy) {
×
1248
        return IN_SET(policy, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR, SCHED_EXT);
×
1249
}
1250

1251
bool sched_policy_supported(int policy) {
4✔
1252
        return sched_get_priority_min(policy) >= 0;
4✔
1253
}
1254

1255
/* Wrappers around sched_get_priority_{min,max}() that gracefully handles missing SCHED_EXT support in the kernel */
1256
int sched_get_priority_min_safe(int policy) {
4✔
1257
        int r;
4✔
1258

1259
        r = sched_get_priority_min(policy);
4✔
1260
        if (r >= 0)
4✔
1261
                return r;
3✔
1262

1263
        /* Fallback priority */
1264
        return 0;
1265
}
1266

1267
int sched_get_priority_max_safe(int policy) {
4✔
1268
        int r;
4✔
1269

1270
        r = sched_get_priority_max(policy);
4✔
1271
        if (r >= 0)
4✔
1272
                return r;
3✔
1273

1274
        return 0;
1275
}
1276

1277
/* The cached PID, possible values:
1278
 *
1279
 *     == UNSET [0]  → cache not initialized yet
1280
 *     == BUSY [-1]  → some thread is initializing it at the moment
1281
 *     any other     → the cached PID
1282
 */
1283

1284
#define CACHED_PID_UNSET ((pid_t) 0)
1285
#define CACHED_PID_BUSY ((pid_t) -1)
1286

1287
static pid_t cached_pid = CACHED_PID_UNSET;
1288

1289
void reset_cached_pid(void) {
1,609✔
1290
        /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
1291
        cached_pid = CACHED_PID_UNSET;
1,609✔
1292
}
1,609✔
1293

1294
pid_t getpid_cached(void) {
151,157,738✔
1295
        static bool installed = false;
151,157,738✔
1296
        pid_t current_value = CACHED_PID_UNSET;
151,157,738✔
1297

1298
        /* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
1299
         * system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
1300
         * cached. Starting with 2.24 getpid() started to become prohibitively expensive when used for detecting when
1301
         * objects were used across fork()s. With this caching the old behaviour is somewhat restored.
1302
         *
1303
         * https://bugzilla.redhat.com/show_bug.cgi?id=1443976
1304
         * https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
1305
         */
1306

1307
        (void) __atomic_compare_exchange_n(
151,157,738✔
1308
                        &cached_pid,
1309
                        &current_value,
1310
                        CACHED_PID_BUSY,
1311
                        false,
1312
                        __ATOMIC_SEQ_CST,
1313
                        __ATOMIC_SEQ_CST);
1314

1315
        switch (current_value) {
151,157,738✔
1316

1317
        case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */
103,275✔
1318
                pid_t new_pid;
103,275✔
1319

1320
                new_pid = getpid();
103,275✔
1321

1322
                if (!installed) {
103,275✔
1323
                        /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's
1324
                         * only half-documented (glibc doesn't document it but LSB does — though only superficially)
1325
                         * we'll check for errors only in the most generic fashion possible. */
1326

1327
                        if (pthread_atfork(NULL, NULL, reset_cached_pid) != 0) {
72,021✔
1328
                                /* OOM? Let's try again later */
1329
                                cached_pid = CACHED_PID_UNSET;
×
1330
                                return new_pid;
×
1331
                        }
1332

1333
                        installed = true;
72,021✔
1334
                }
1335

1336
                cached_pid = new_pid;
103,275✔
1337
                return new_pid;
103,275✔
1338
        }
1339

1340
        case CACHED_PID_BUSY: /* Somebody else is currently initializing */
×
1341
                return getpid();
×
1342

1343
        default: /* Properly initialized */
1344
                return current_value;
1345
        }
1346
}
1347

1348
int must_be_root(void) {
56✔
1349

1350
        if (geteuid() == 0)
56✔
1351
                return 0;
1352

1353
        return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root.");
×
1354
}
1355

1356
pid_t clone_with_nested_stack(int (*fn)(void *), int flags, void *userdata) {
3,525✔
1357
        size_t ps;
3,525✔
1358
        pid_t pid;
3,525✔
1359
        void *mystack;
3,525✔
1360

1361
        /* A wrapper around glibc's clone() call that automatically sets up a "nested" stack. Only supports
1362
         * invocations without CLONE_VM, so that we can continue to use the parent's stack mapping.
1363
         *
1364
         * Note: glibc's clone() wrapper does not synchronize malloc() locks. This means that if the parent
1365
         * is threaded these locks will be in an undefined state in the child, and hence memory allocations
1366
         * are likely going to run into deadlocks. Hence: if you use this function make sure your parent is
1367
         * strictly single-threaded or your child never calls malloc(). */
1368

1369
        assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
3,525✔
1370
                         CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
1371

1372
        /* We allocate some space on the stack to use as the stack for the child (hence "nested"). Note that
1373
         * the net effect is that the child will have the start of its stack inside the stack of the parent,
1374
         * but since they are a CoW copy of each other that's fine. We allocate one page-aligned page. But
1375
         * since we don't want to deal with differences between systems where the stack grows backwards or
1376
         * forwards we'll allocate one more and place the stack address in the middle. Except that we also
1377
         * want it page aligned, hence we'll allocate one page more. Makes 3. */
1378

1379
        ps = page_size();
3,525✔
1380
        mystack = alloca(ps*3);
3,525✔
1381
        mystack = (uint8_t*) mystack + ps; /* move pointer one page ahead since stacks usually grow backwards */
3,525✔
1382
        mystack = (void*) ALIGN_TO((uintptr_t) mystack, ps); /* align to page size (moving things further ahead) */
3,525✔
1383

1384
#if HAVE_CLONE
1385
        pid = clone(fn, mystack, flags, userdata);
3,525✔
1386
#else
1387
        pid = __clone2(fn, mystack, ps, flags, userdata);
1388
#endif
1389
        if (pid < 0)
3,525✔
1390
                return -errno;
×
1391

1392
        return pid;
1393
}
1394

1395
static int fork_flags_to_signal(ForkFlags flags) {
29,429✔
1396
        return (flags & FORK_DEATHSIG_SIGTERM) ? SIGTERM :
29,429✔
1397
                (flags & FORK_DEATHSIG_SIGINT) ? SIGINT :
841✔
1398
                                                 SIGKILL;
1399
}
1400

1401
int pidref_safe_fork_full(
28,102✔
1402
                const char *name,
1403
                const int stdio_fds[3],
1404
                int except_fds[],
1405
                size_t n_except_fds,
1406
                ForkFlags flags,
1407
                PidRef *ret) {
1408

1409
        pid_t original_pid, pid;
28,102✔
1410
        sigset_t saved_ss, ss;
28,102✔
1411
        _unused_ _cleanup_(block_signals_reset) sigset_t *saved_ssp = NULL;
×
1412
        bool block_signals = false, block_all = false, intermediary = false;
28,102✔
1413
        _cleanup_close_pair_ int pidref_transport_fds[2] = EBADF_PAIR;
58,641✔
1414
        int prio, r;
28,102✔
1415

1416
        assert(!FLAGS_SET(flags, FORK_WAIT|FORK_FREEZE));
28,102✔
1417
        assert(!FLAGS_SET(flags, FORK_DETACH) ||
28,102✔
1418
               (flags & (FORK_WAIT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL)) == 0);
1419

1420
        /* A wrapper around fork(), that does a couple of important initializations in addition to mere
1421
         * forking. If provided, ret is initialized in both the parent and the child process, both times
1422
         * referencing the child process. Returns == 0 in the child and > 0 in the parent. */
1423

1424
        prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG;
28,102✔
1425

1426
        original_pid = getpid_cached();
28,102✔
1427

1428
        if (flags & FORK_FLUSH_STDIO) {
28,102✔
1429
                fflush(stdout);
5✔
1430
                fflush(stderr); /* This one shouldn't be necessary, stderr should be unbuffered anyway, but let's better be safe than sorry */
5✔
1431
        }
1432

1433
        if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT)) {
28,102✔
1434
                /* We temporarily block all signals, so that the new child has them blocked initially. This
1435
                 * way, we can be sure that SIGTERMs are not lost we might send to the child. (Note that for
1436
                 * FORK_DEATHSIG_SIGKILL we don't bother, since it cannot be blocked anyway.) */
1437

1438
                assert_se(sigfillset(&ss) >= 0);
23,809✔
1439
                block_signals = block_all = true;
1440

1441
        } else if (flags & FORK_WAIT) {
4,293✔
1442
                /* Let's block SIGCHLD at least, so that we can safely watch for the child process */
1443

1444
                assert_se(sigemptyset(&ss) >= 0);
157✔
1445
                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
157✔
1446
                block_signals = true;
1447
        }
1448

1449
        if (block_signals) {
1450
                if (sigprocmask(SIG_BLOCK, &ss, &saved_ss) < 0)
23,966✔
1451
                        return log_full_errno(prio, errno, "Failed to block signal mask: %m");
×
1452
                saved_ssp = &saved_ss;
23,966✔
1453
        }
1454

1455
        if (FLAGS_SET(flags, FORK_DETACH)) {
28,102✔
1456
                /* Fork off intermediary child if needed */
1457

1458
                r = is_reaper_process();
105✔
1459
                if (r < 0)
105✔
1460
                        return log_full_errno(prio, r, "Failed to determine if we are a reaper process: %m");
×
1461

1462
                if (!r) {
105✔
1463
                        /* Not a reaper process, hence do a double fork() so we are reparented to one */
1464

1465
                        if (ret && socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pidref_transport_fds) < 0)
11✔
1466
                                return log_full_errno(prio, errno, "Failed to allocate pidref socket: %m");
×
1467

1468
                        pid = fork();
11✔
1469
                        if (pid < 0)
28✔
1470
                                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
×
1471
                        if (pid > 0) {
28✔
1472
                                log_debug("Successfully forked off intermediary '%s' as PID " PID_FMT ".", strna(name), pid);
11✔
1473

1474
                                pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
11✔
1475

1476
                                if (pidref_transport_fds[0] >= 0) {
11✔
1477
                                        /* Wait for the intermediary child to exit so the caller can be
1478
                                         * certain the actual child process has been reparented by the time
1479
                                         * this function returns. */
1480
                                        r = pidref_wait_for_terminate_and_check(
10✔
1481
                                                        name,
1482
                                                        &PIDREF_MAKE_FROM_PID(pid),
10✔
1483
                                                        FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
1484
                                        if (r < 0)
10✔
1485
                                                return log_full_errno(prio, r, "Failed to wait for intermediary process: %m");
×
1486
                                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
10✔
1487
                                                return -EPROTO;
1488

1489
                                        int pidfd;
10✔
1490
                                        ssize_t n = receive_one_fd_iov(
20✔
1491
                                                        pidref_transport_fds[0],
1492
                                                        &IOVEC_MAKE(&pid, sizeof(pid)),
10✔
1493
                                                        /* iovlen= */ 1,
1494
                                                        /* flags= */ 0,
1495
                                                        &pidfd);
1496
                                        if (n < 0)
10✔
1497
                                                return log_full_errno(prio, n, "Failed to receive child pidref: %m");
×
1498

1499
                                        *ret = (PidRef) { .pid = pid, .fd = pidfd };
10✔
1500
                                }
1501

1502
                                return 1; /* return in the parent */
11✔
1503
                        }
1504

1505
                        pidref_transport_fds[0] = safe_close(pidref_transport_fds[0]);
17✔
1506
                        intermediary = true;
17✔
1507
                }
1508
        }
1509

1510
        if ((flags & (FORK_NEW_MOUNTNS|FORK_NEW_USERNS|FORK_NEW_NETNS|FORK_NEW_PIDNS)) != 0)
28,108✔
1511
                pid = raw_clone(SIGCHLD|
5,665✔
1512
                                (FLAGS_SET(flags, FORK_NEW_MOUNTNS) ? CLONE_NEWNS : 0) |
5,665✔
1513
                                (FLAGS_SET(flags, FORK_NEW_USERNS) ? CLONE_NEWUSER : 0) |
5,665✔
1514
                                (FLAGS_SET(flags, FORK_NEW_NETNS) ? CLONE_NEWNET : 0) |
5,665✔
1515
                                (FLAGS_SET(flags, FORK_NEW_PIDNS) ? CLONE_NEWPID : 0));
5,665✔
1516
        else
1517
                pid = fork();
22,443✔
1518
        if (pid < 0)
58,641✔
1519
                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
2✔
1520
        if (pid > 0) {
58,640✔
1521

1522
                /* If we are in the intermediary process, exit now */
1523
                if (intermediary) {
27,764✔
1524
                        if (pidref_transport_fds[1] >= 0) {
11✔
1525
                                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
10✔
1526

1527
                                r = pidref_set_pid(&pidref, pid);
10✔
1528
                                if (r < 0) {
10✔
1529
                                        log_full_errno(prio, r, "Failed to open reference to PID "PID_FMT": %m", pid);
×
1530
                                        _exit(EXIT_FAILURE);
×
1531
                                }
1532

1533
                                r = send_one_fd_iov(
10✔
1534
                                                pidref_transport_fds[1],
1535
                                                pidref.fd,
1536
                                                &IOVEC_MAKE(&pidref.pid, sizeof(pidref.pid)),
1537
                                                /* iovlen= */ 1,
1538
                                                /* flags= */ 0);
1539
                                if (r < 0) {
10✔
1540
                                        log_full_errno(prio, r, "Failed to send child pidref: %m");
×
1541
                                        _exit(EXIT_FAILURE);
×
1542
                                }
1543
                        }
1544

1545
                        _exit(EXIT_SUCCESS);
11✔
1546
                }
1547

1548
                /* We are in the parent process */
1549
                log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
27,753✔
1550

1551
                if (flags & FORK_WAIT) {
27,753✔
1552
                        if (block_all) {
845✔
1553
                                /* undo everything except SIGCHLD */
1554
                                ss = saved_ss;
688✔
1555
                                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
688✔
1556
                                (void) sigprocmask(SIG_SETMASK, &ss, NULL);
688✔
1557
                        }
1558

1559
                        r = pidref_wait_for_terminate_and_check(
845✔
1560
                                        name,
1561
                                        &PIDREF_MAKE_FROM_PID(pid),
845✔
1562
                                        FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
1563
                        if (r < 0)
845✔
1564
                                return r;
845✔
1565
                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
845✔
1566
                                return -EPROTO;
1567

1568
                        /* If we are in the parent and successfully waited, then the process doesn't exist anymore. */
1569
                        if (ret)
845✔
1570
                                *ret = PIDREF_NULL;
2✔
1571

1572
                        return 1;
845✔
1573
                }
1574

1575
                if (ret) {
26,908✔
1576
                        r = pidref_set_pid(ret, pid);
25,659✔
1577
                        if (r < 0) /* Let's not fail for this, no matter what, the process exists after all, and that's key */
25,659✔
1578
                                *ret = PIDREF_MAKE_FROM_PID(pid);
×
1579
                }
1580

1581
                return 1;
26,908✔
1582
        }
1583

1584
        /* We are in the child process */
1585

1586
        pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
30,876✔
1587

1588
        /* Restore signal mask manually */
1589
        saved_ssp = NULL;
30,876✔
1590

1591
        if (flags & FORK_REOPEN_LOG) {
30,876✔
1592
                /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
1593
                log_close();
7,423✔
1594
                log_set_open_when_needed(true);
7,423✔
1595
                log_settle_target();
7,423✔
1596
        }
1597

1598
        if (name) {
30,876✔
1599
                r = rename_process(name);
30,876✔
1600
                if (r < 0)
30,876✔
1601
                        log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG,
×
1602
                                       r, "Failed to rename process, ignoring: %m");
1603
        }
1604

1605
        /* let's disable dlopen() in the child, as a paranoia safety precaution: children should not live for
1606
         * long and only do minimal work before exiting or exec()ing. Doing dlopen() is not either. If people
1607
         * want dlopen() they should do it before forking. This is a safety precaution in particular for
1608
         * cases where the child does namespace shenanigans: we should never end up loading a module from a
1609
         * foreign environment. Note that this has no effect on NSS! (i.e. it only has effect on uses of our
1610
         * dlopen_safe(), which we use comprehensively in our codebase, but glibc NSS doesn't bother, of
1611
         * course.) */
1612
        if (!FLAGS_SET(flags, FORK_ALLOW_DLOPEN))
30,876✔
1613
                block_dlopen();
30,842✔
1614

1615
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL))
30,876✔
1616
                if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) {
29,429✔
1617
                        log_full_errno(prio, errno, "Failed to set death signal: %m");
×
1618
                        _exit(EXIT_FAILURE);
×
1619
                }
1620

1621
        if (flags & FORK_RESET_SIGNALS) {
30,876✔
1622
                r = reset_all_signal_handlers();
25,768✔
1623
                if (r < 0) {
25,768✔
1624
                        log_full_errno(prio, r, "Failed to reset signal handlers: %m");
×
1625
                        _exit(EXIT_FAILURE);
×
1626
                }
1627

1628
                /* This implicitly undoes the signal mask stuff we did before the fork()ing above */
1629
                r = reset_signal_mask();
25,768✔
1630
                if (r < 0) {
25,768✔
1631
                        log_full_errno(prio, r, "Failed to reset signal mask: %m");
×
1632
                        _exit(EXIT_FAILURE);
×
1633
                }
1634
        } else if (block_signals) { /* undo what we did above */
5,108✔
1635
                if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
4,664✔
1636
                        log_full_errno(prio, errno, "Failed to restore signal mask: %m");
×
1637
                        _exit(EXIT_FAILURE);
×
1638
                }
1639
        }
1640

1641
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL|FORK_DEATHSIG_SIGINT)) {
30,876✔
1642
                pid_t ppid;
29,429✔
1643
                /* Let's see if the parent PID is still the one we started from? If not, then the parent
1644
                 * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
1645

1646
                ppid = getppid();
29,429✔
1647
                if (ppid == 0)
29,429✔
1648
                        /* Parent is in a different PID namespace. */;
1649
                else if (ppid != original_pid) {
29,390✔
1650
                        int sig = fork_flags_to_signal(flags);
×
1651
                        log_debug("Parent died early, raising %s.", signal_to_string(sig));
×
1652
                        (void) raise(sig);
×
1653
                        _exit(EXIT_FAILURE);
×
1654
                }
1655
        }
1656

1657
        if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) {
30,876✔
1658
                /* Optionally, make sure we never propagate mounts to the host. */
1659
                if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
153✔
1660
                        log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
×
1661
                        _exit(EXIT_FAILURE);
×
1662
                }
1663
        }
1664

1665
        if (FLAGS_SET(flags, FORK_PRIVATE_TMP)) {
30,876✔
1666
                assert(FLAGS_SET(flags, FORK_NEW_MOUNTNS));
×
1667

1668
                /* Optionally, overmount new tmpfs instance on /tmp/. */
1669
                r = mount_nofollow("tmpfs", "/tmp", "tmpfs",
×
1670
                                   MS_NOSUID|MS_NODEV,
1671
                                   "mode=01777" TMPFS_LIMITS_RUN);
1672
                if (r < 0) {
×
1673
                        log_full_errno(prio, r, "Failed to overmount /tmp/: %m");
×
1674
                        _exit(EXIT_FAILURE);
×
1675
                }
1676
        }
1677

1678
        if (flags & FORK_REARRANGE_STDIO) {
30,876✔
1679
                if (stdio_fds) {
15,844✔
1680
                        r = rearrange_stdio(stdio_fds[0], stdio_fds[1], stdio_fds[2]);
15,828✔
1681
                        if (r < 0) {
15,828✔
1682
                                log_full_errno(prio, r, "Failed to rearrange stdio fds: %m");
×
1683
                                _exit(EXIT_FAILURE);
×
1684
                        }
1685

1686
                        /* Turn off O_NONBLOCK on the fdio fds, in case it was left on */
1687
                        stdio_disable_nonblock();
15,828✔
1688
                } else {
1689
                        r = make_null_stdio();
16✔
1690
                        if (r < 0) {
16✔
1691
                                log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
×
1692
                                _exit(EXIT_FAILURE);
×
1693
                        }
1694
                }
1695
        } else if (flags & FORK_STDOUT_TO_STDERR) {
15,032✔
1696
                if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
2✔
1697
                        log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
×
1698
                        _exit(EXIT_FAILURE);
×
1699
                }
1700
        }
1701

1702
        if (flags & FORK_CLOSE_ALL_FDS) {
30,876✔
1703
                /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
1704
                log_close();
24,827✔
1705

1706
                r = close_all_fds(except_fds, n_except_fds);
24,827✔
1707
                if (r < 0) {
24,827✔
1708
                        log_full_errno(prio, r, "Failed to close all file descriptors: %m");
×
1709
                        _exit(EXIT_FAILURE);
×
1710
                }
1711
        }
1712

1713
        if (flags & FORK_PACK_FDS) {
30,876✔
1714
                /* FORK_CLOSE_ALL_FDS ensures that except_fds are the only FDs >= 3 that are
1715
                 * open, this is including the log. This is required by pack_fds, which will
1716
                 * get stuck in an infinite loop of any FDs other than except_fds are open. */
1717
                assert(FLAGS_SET(flags, FORK_CLOSE_ALL_FDS));
92✔
1718

1719
                r = pack_fds(except_fds, n_except_fds);
92✔
1720
                if (r < 0) {
92✔
1721
                        log_full_errno(prio, r, "Failed to pack file descriptors: %m");
×
1722
                        _exit(EXIT_FAILURE);
×
1723
                }
1724
        }
1725

1726
        if (flags & FORK_CLOEXEC_OFF) {
30,876✔
1727
                r = fd_cloexec_many(except_fds, n_except_fds, false);
107✔
1728
                if (r < 0) {
107✔
1729
                        log_full_errno(prio, r, "Failed to turn off O_CLOEXEC on file descriptors: %m");
×
1730
                        _exit(EXIT_FAILURE);
×
1731
                }
1732
        }
1733

1734
        /* When we were asked to reopen the logs, do so again now */
1735
        if (flags & FORK_REOPEN_LOG) {
30,876✔
1736
                log_open();
7,423✔
1737
                log_set_open_when_needed(false);
7,423✔
1738
        }
1739

1740
        if (flags & FORK_RLIMIT_NOFILE_SAFE) {
30,876✔
1741
                r = rlimit_nofile_safe();
16,960✔
1742
                if (r < 0) {
16,960✔
1743
                        log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
×
1744
                        _exit(EXIT_FAILURE);
×
1745
                }
1746
        }
1747

1748
        if (!FLAGS_SET(flags, FORK_KEEP_NOTIFY_SOCKET)) {
30,876✔
1749
                r = RET_NERRNO(unsetenv("NOTIFY_SOCKET"));
30,876✔
1750
                if (r < 0) {
×
1751
                        log_full_errno(prio, r, "Failed to unset $NOTIFY_SOCKET: %m");
×
1752
                        _exit(EXIT_FAILURE);
×
1753
                }
1754
        }
1755

1756
        if (FLAGS_SET(flags, FORK_FREEZE))
30,876✔
1757
                freeze();
×
1758

1759
        if (ret) {
30,876✔
1760
                r = pidref_set_self(ret);
28,652✔
1761
                if (r < 0) {
28,652✔
1762
                        log_full_errno(prio, r, "Failed to acquire PID reference on ourselves: %m");
×
1763
                        _exit(EXIT_FAILURE);
×
1764
                }
1765
        }
1766

1767
        return 0;
1768
}
1769

1770
int namespace_fork_full(
131✔
1771
                const char *outer_name,
1772
                const char *inner_name,
1773
                int except_fds[],
1774
                size_t n_except_fds,
1775
                ForkFlags flags,
1776
                int pidns_fd,
1777
                int mntns_fd,
1778
                int netns_fd,
1779
                int userns_fd,
1780
                int root_fd,
1781
                PidRef *ret) {
1782

1783
        _cleanup_(pidref_done_sigkill_wait) PidRef pidref_outer = PIDREF_NULL;
×
1784
        _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
220✔
1785
        int r, prio = FLAGS_SET(flags, FORK_LOG) ? LOG_ERR : LOG_DEBUG;
131✔
1786

1787
        /* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle
1788
         * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
1789
         * /proc/self/fd works correctly.
1790
         *
1791
         * TODO: once we can rely on PIDFD_INFO_EXIT, do not keep the middle process around and instead
1792
         * return the pidfd of the inner process for direct tracking. */
1793

1794
        /* Insist on PDEATHSIG being enabled, as the pid returned is the one of the middle man, and otherwise
1795
         * killing of it won't be propagated to the inner child. */
1796
        assert((flags & (FORK_DEATHSIG_SIGKILL|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT)) != 0);
131✔
1797
        assert((flags & (FORK_DETACH|FORK_FREEZE)) == 0);
131✔
1798
        assert(!FLAGS_SET(flags, FORK_ALLOW_DLOPEN)); /* never allow loading shared library from another ns */
131✔
1799

1800
        /* We want read() to block as a synchronization point */
1801
        assert_cc(sizeof(int) <= PIPE_BUF);
131✔
1802
        if (pipe2(errno_pipe_fd, O_CLOEXEC) < 0)
131✔
1803
                return log_full_errno(prio, errno, "Failed to create pipe: %m");
×
1804

1805
        r = pidref_safe_fork_full(
350✔
1806
                        outer_name,
1807
                        /* stdio_fds= */ NULL, /* except_fds= */ NULL, /* n_except_fds= */ 0,
1808
                        (flags|FORK_DEATHSIG_SIGKILL) & ~(FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_NEW_NETNS|FORK_NEW_PIDNS|FORK_CLOSE_ALL_FDS|FORK_PACK_FDS|FORK_CLOEXEC_OFF|FORK_RLIMIT_NOFILE_SAFE),
131✔
1809
                        &pidref_outer);
1810
        if (r == -EPROTO && FLAGS_SET(flags, FORK_WAIT)) {
219✔
1811
                errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
×
1812

1813
                int k = read_errno(errno_pipe_fd[0]);
×
1814
                if (k < 0 && k != -EIO)
×
1815
                        return k;
1816
        }
1817
        if (r < 0)
219✔
1818
                return r;
1819
        if (r == 0) {
219✔
1820
                _cleanup_(pidref_done) PidRef pidref_inner = PIDREF_NULL;
×
1821

1822
                /* Child */
1823

1824
                errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
88✔
1825

1826
                r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
88✔
1827
                if (r < 0) {
88✔
1828
                        log_full_errno(prio, r, "Failed to join namespace: %m");
×
1829
                        report_errno_and_exit(errno_pipe_fd[1], r);
×
1830
                }
1831

1832
                /* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */
1833
                r = pidref_safe_fork_full(
265✔
1834
                                inner_name,
1835
                                NULL,
1836
                                except_fds, n_except_fds,
1837
                                flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_REARRANGE_STDIO|FORK_FLUSH_STDIO|FORK_STDOUT_TO_STDERR),
88✔
1838
                                &pidref_inner);
1839
                if (r < 0)
177✔
1840
                        report_errno_and_exit(errno_pipe_fd[1], r);
×
1841
                if (r == 0) {
177✔
1842
                        /* Child */
1843

1844
                        if (!FLAGS_SET(flags, FORK_CLOSE_ALL_FDS)) {
89✔
1845
                                errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
89✔
1846
                                pidref_done(&pidref_outer);
89✔
1847
                        } else {
1848
                                errno_pipe_fd[1] = -EBADF;
×
1849
                                pidref_outer = PIDREF_NULL;
×
1850
                        }
1851

1852
                        if (ret)
89✔
1853
                                *ret = TAKE_PIDREF(pidref_inner);
89✔
1854
                        return 0;
89✔
1855
                }
1856

1857
                log_close();
88✔
1858
                log_set_open_when_needed(true);
88✔
1859

1860
                (void) close_all_fds(&pidref_inner.fd, 1);
88✔
1861

1862
                r = pidref_wait_for_terminate_and_check(
176✔
1863
                                inner_name,
1864
                                &pidref_inner,
1865
                                FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
1866
                if (r < 0)
88✔
1867
                        _exit(EXIT_FAILURE);
×
1868

1869
                _exit(r);
88✔
1870
        }
1871

1872
        errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
131✔
1873

1874
        r = read_errno(errno_pipe_fd[0]);
131✔
1875
        if (r < 0)
131✔
1876
                return r; /* the child logs about failures on its own, no need to duplicate here */
1877

1878
        if (ret)
131✔
1879
                *ret = TAKE_PIDREF(pidref_outer);
131✔
1880
        else
1881
                pidref_done(&pidref_outer); /* disarm sigkill_wait */
×
1882

1883
        return 1;
1884
}
1885

1886
int set_oom_score_adjust(int value) {
3,646✔
1887
        char t[DECIMAL_STR_MAX(int)];
3,646✔
1888

1889
        if (!oom_score_adjust_is_valid(value))
3,646✔
1890
                return -EINVAL;
3,646✔
1891

1892
        xsprintf(t, "%i", value);
3,646✔
1893

1894
        return write_string_file("/proc/self/oom_score_adj", t,
3,646✔
1895
                                 WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
1896
}
1897

1898
int get_oom_score_adjust(int *ret) {
2,469✔
1899
        _cleanup_free_ char *t = NULL;
2,469✔
1900
        int r, a;
2,469✔
1901

1902
        r = read_virtual_file("/proc/self/oom_score_adj", SIZE_MAX, &t, NULL);
2,469✔
1903
        if (r < 0)
2,469✔
1904
                return r;
1905

1906
        delete_trailing_chars(t, WHITESPACE);
2,469✔
1907

1908
        r = safe_atoi(t, &a);
2,469✔
1909
        if (r < 0)
2,469✔
1910
                return r;
1911

1912
        if (!oom_score_adjust_is_valid(a))
2,469✔
1913
                return -ENODATA;
1914

1915
        if (ret)
2,469✔
1916
                *ret = a;
2,469✔
1917

1918
        return 0;
1919
}
1920

1921
static int rlimit_to_nice(rlim_t limit) {
2✔
1922
        if (limit <= 1)
2✔
1923
                return PRIO_MAX-1; /* i.e. 19 */
1924

1925
        if (limit >= -PRIO_MIN + PRIO_MAX)
2✔
1926
                return PRIO_MIN; /* i.e. -20 */
1927

1928
        return PRIO_MAX - (int) limit;
2✔
1929
}
1930

1931
int setpriority_closest(int priority) {
27✔
1932
        struct rlimit highest;
27✔
1933
        int r, current, limit;
27✔
1934

1935
        /* Try to set requested nice level */
1936
        r = RET_NERRNO(setpriority(PRIO_PROCESS, 0, priority));
27✔
1937
        if (r >= 0)
2✔
1938
                return 1;
25✔
1939
        if (!ERRNO_IS_NEG_PRIVILEGE(r))
2✔
1940
                return r;
1941

1942
        errno = 0;
2✔
1943
        current = getpriority(PRIO_PROCESS, 0);
2✔
1944
        if (errno != 0)
2✔
1945
                return -errno;
×
1946

1947
        if (priority == current)
2✔
1948
                return 1;
1949

1950
       /* Hmm, we'd expect that raising the nice level from our status quo would always work. If it doesn't,
1951
        * then the whole setpriority() system call is blocked to us, hence let's propagate the error
1952
        * right-away */
1953
        if (priority > current)
2✔
1954
                return r;
1955

1956
        if (getrlimit(RLIMIT_NICE, &highest) < 0)
2✔
1957
                return -errno;
×
1958

1959
        limit = rlimit_to_nice(highest.rlim_cur);
2✔
1960

1961
        /* Push to the allowed limit if we're higher than that. Note that we could also be less nice than
1962
         * limit allows us, but still higher than what's requested. In that case our current value is
1963
         * the best choice. */
1964
        if (current > limit)
2✔
1965
                if (setpriority(PRIO_PROCESS, 0, limit) < 0)
2✔
1966
                        return -errno;
×
1967

1968
        log_debug("Cannot set requested nice level (%i), using next best (%i).", priority, MIN(current, limit));
2✔
1969
        return 0;
1970
}
1971

1972
_noreturn_ void freeze(void) {
×
1973
        log_close();
×
1974

1975
        /* Make sure nobody waits for us (i.e. on one of our sockets) anymore. Note that we use
1976
         * close_all_fds_without_malloc() instead of plain close_all_fds() here, since we want this function
1977
         * to be compatible with being called from signal handlers. */
1978
        (void) close_all_fds_without_malloc(NULL, 0);
×
1979

1980
        /* Let's not freeze right away, but keep reaping zombies. */
1981
        for (;;) {
×
1982
                siginfo_t si = {};
×
1983

1984
                if (waitid(P_ALL, 0, &si, WEXITED) < 0 && errno != EINTR)
×
1985
                        break;
1986
        }
1987

1988
        /* waitid() failed with an ECHLD error (because there are no left-over child processes) or any other
1989
         * (unexpected) error. Freeze for good now! */
1990
        for (;;)
×
1991
                pause();
×
1992
}
1993

1994
int get_process_threads(pid_t pid) {
7✔
1995
        _cleanup_free_ char *t = NULL;
7✔
1996
        int n, r;
7✔
1997

1998
        if (pid < 0)
7✔
1999
                return -EINVAL;
2000

2001
        r = procfs_file_get_field(pid, "status", "Threads", &t);
7✔
2002
        if (r == -ENOENT)
7✔
2003
                return -ESRCH;
2004
        if (r < 0)
7✔
2005
                return r;
2006

2007
        r = safe_atoi(t, &n);
7✔
2008
        if (r < 0)
7✔
2009
                return r;
2010
        if (n < 0)
7✔
2011
                return -EINVAL;
×
2012

2013
        return n;
2014
}
2015

2016
int is_reaper_process(void) {
3,634✔
2017
        int b = 0;
3,634✔
2018

2019
        /* Checks if we are running in a reaper process, i.e. if we are expected to deal with processes
2020
         * reparented to us. This simply checks if we are PID 1 or if PR_SET_CHILD_SUBREAPER was called. */
2021

2022
        if (getpid_cached() == 1)
3,634✔
2023
                return true;
3,634✔
2024

2025
        if (prctl(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0UL, 0UL, 0UL) < 0)
363✔
2026
                return -errno;
×
2027

2028
        return b != 0;
363✔
2029
}
2030

2031
int make_reaper_process(bool b) {
666✔
2032

2033
        if (getpid_cached() == 1) {
666✔
2034

2035
                if (!b)
52✔
2036
                        return -EINVAL;
2037

2038
                return 0;
52✔
2039
        }
2040

2041
        /* Some prctl()s insist that all 5 arguments are specified, others do not. Let's always specify all,
2042
         * to avoid any ambiguities */
2043
        if (prctl(PR_SET_CHILD_SUBREAPER, (unsigned long) b, 0UL, 0UL, 0UL) < 0)
614✔
2044
                return -errno;
×
2045

2046
        return 0;
2047
}
2048

2049
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(posix_spawnattr_t*, posix_spawnattr_destroy, NULL);
×
2050

2051
int posix_spawn_wrapper(
2,465✔
2052
                const char *path,
2053
                char * const *argv,
2054
                char * const *envp,
2055
                const char *cgroup,
2056
                PidRef *ret_pidref) {
2057

2058
        short flags = POSIX_SPAWN_SETSIGMASK;
2,465✔
2059
        posix_spawnattr_t attr;
2,465✔
2060
        sigset_t mask;
2,465✔
2061
        int r;
2,465✔
2062

2063
        /* Forks and invokes 'path' with 'argv' and 'envp' using CLONE_VM and CLONE_VFORK, which means the
2064
         * caller will be blocked until the child either exits or exec's. The memory of the child will be
2065
         * fully shared with the memory of the parent, so that there are no copy-on-write or memory.max
2066
         * issues.
2067
         *
2068
         * Also, move the newly-created process into 'cgroup' through POSIX_SPAWN_SETCGROUP (clone3())
2069
         * if available.
2070
         * returns 1: We're already in the right cgroup
2071
         *         0: 'cgroup' not specified or POSIX_SPAWN_SETCGROUP is not supported. The caller
2072
         *            needs to call 'cg_attach' on their own */
2073

2074
        assert(path);
2,465✔
2075
        assert(argv);
2,465✔
2076
        assert(ret_pidref);
2,465✔
2077

2078
        assert_se(sigfillset(&mask) >= 0);
2,465✔
2079

2080
        r = posix_spawnattr_init(&attr);
2,465✔
2081
        if (r != 0)
2,465✔
2082
                return -r; /* These functions return a positive errno on failure */
2,465✔
2083

2084
        /* Initialization needs to succeed before we can set up a destructor. */
2085
        _unused_ _cleanup_(posix_spawnattr_destroyp) posix_spawnattr_t *attr_destructor = &attr;
4,930✔
2086

2087
#if HAVE_PIDFD_SPAWN
2088
        static bool have_clone_into_cgroup = true; /* kernel 5.7+ */
2,465✔
2089
        _cleanup_close_ int cgroup_fd = -EBADF;
2,465✔
2090

2091
        if (cgroup && have_clone_into_cgroup) {
2,465✔
2092
                _cleanup_free_ char *resolved_cgroup = NULL;
2,465✔
2093

2094
                r = cg_get_path(cgroup, /* suffix= */ NULL, &resolved_cgroup);
2,465✔
2095
                if (r < 0)
2,465✔
2096
                        return r;
2097

2098
                cgroup_fd = open(resolved_cgroup, O_PATH|O_DIRECTORY|O_CLOEXEC);
2,465✔
2099
                if (cgroup_fd < 0)
2,465✔
2100
                        return -errno;
×
2101

2102
                r = posix_spawnattr_setcgroup_np(&attr, cgroup_fd);
2,465✔
2103
                if (r != 0)
2,465✔
2104
                        return -r;
×
2105

2106
                flags |= POSIX_SPAWN_SETCGROUP;
2,465✔
2107
        }
2108
#endif
2109

2110
        r = posix_spawnattr_setflags(&attr, flags);
2,465✔
2111
        if (r != 0)
2,465✔
2112
                return -r;
×
2113
        r = posix_spawnattr_setsigmask(&attr, &mask);
2,465✔
2114
        if (r != 0)
2,465✔
2115
                return -r;
×
2116

2117
#if HAVE_PIDFD_SPAWN
2118
        _cleanup_close_ int pidfd = -EBADF;
2,465✔
2119

2120
        r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
2,465✔
2121
        if (ERRNO_IS_NOT_SUPPORTED(r) && FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP) && cg_is_threaded(cgroup) > 0)
2,465✔
2122
                return -EUCLEAN; /* clone3() could also return EOPNOTSUPP if the target cgroup is in threaded mode,
2123
                                    turn that into something recognizable */
2124
        if ((ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r)) &&
2,465✔
2125
            FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP)) {
2126
                /* Compiled on a newer host, or seccomp&friends blocking clone3()? Fallback, but
2127
                 * need to disable POSIX_SPAWN_SETCGROUP, which is what redirects to clone3().
2128
                 * CLONE_INTO_CGROUP definitely won't work, hence remember the fact so that we don't
2129
                 * retry every time.
2130
                 * Note, CLONE_INTO_CGROUP is supported since kernel v5.7, but some architectures still
2131
                 * do not support clone3(). Hence, we need to keep the fallback logic for a while. */
2132
                have_clone_into_cgroup = false;
×
2133

2134
                flags &= ~POSIX_SPAWN_SETCGROUP;
×
2135
                r = posix_spawnattr_setflags(&attr, flags);
×
2136
                if (r != 0)
×
2137
                        return -r;
×
2138

2139
                r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
×
2140
        }
2141
        if (r != 0)
2,465✔
2142
                return -r;
×
2143

2144
        r = pidref_set_pidfd_consume(ret_pidref, TAKE_FD(pidfd));
2,465✔
2145
        if (r < 0)
2,465✔
2146
                return r;
2147

2148
        return FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP);
2,465✔
2149
#else
2150
        pid_t pid;
2151

2152
        r = posix_spawn(&pid, path, NULL, &attr, argv, envp);
2153
        if (r != 0)
2154
                return -r;
2155

2156
        r = pidref_set_pid(ret_pidref, pid);
2157
        if (r < 0)
2158
                return r;
2159

2160
        return 0; /* We did not use CLONE_INTO_CGROUP so return 0, the caller will have to move the child */
2161
#endif
2162
}
2163

2164
int proc_dir_open(DIR **ret) {
13✔
2165
        DIR *d;
13✔
2166

2167
        assert(ret);
13✔
2168

2169
        d = opendir("/proc");
13✔
2170
        if (!d)
13✔
2171
                return -errno;
×
2172

2173
        *ret = d;
13✔
2174
        return 0;
13✔
2175
}
2176

2177
int proc_dir_read(DIR *d, pid_t *ret) {
1,167✔
2178
        assert(d);
1,167✔
2179

2180
        for (;;) {
1,951✔
2181
                struct dirent *de;
1,951✔
2182

2183
                errno = 0;
1,951✔
2184
                de = readdir_no_dot(d);
1,951✔
2185
                if (!de) {
1,951✔
2186
                        if (errno != 0)
13✔
2187
                                return -errno;
×
2188

2189
                        break;
13✔
2190
                }
2191

2192
                if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
1,938✔
2193
                        continue;
641✔
2194

2195
                if (parse_pid(de->d_name, ret) >= 0)
1,297✔
2196
                        return 1;
2197
        }
2198

2199
        if (ret)
13✔
2200
                *ret = 0;
13✔
2201
        return 0;
2202
}
2203

2204
int proc_dir_read_pidref(DIR *d, PidRef *ret) {
1,128✔
2205
        int r;
1,128✔
2206

2207
        assert(d);
1,128✔
2208

2209
        for (;;) {
1,128✔
2210
                pid_t pid;
1,128✔
2211

2212
                r = proc_dir_read(d, &pid);
1,128✔
2213
                if (r < 0)
1,128✔
2214
                        return r;
1,116✔
2215
                if (r == 0)
1,128✔
2216
                        break;
2217

2218
                r = pidref_set_pid(ret, pid);
1,116✔
2219
                if (r == -ESRCH) /* gone by now? skip it */
1,116✔
UNCOV
2220
                        continue;
×
2221
                if (r < 0)
1,116✔
2222
                        return r;
×
2223

2224
                return 1;
2225
        }
2226

2227
        if (ret)
12✔
2228
                *ret = PIDREF_NULL;
12✔
2229
        return 0;
2230
}
2231

2232
int safe_mlockall(int flags) {
160✔
2233
        int r;
160✔
2234

2235
        /* When dealing with sensitive data, let's lock ourselves into memory. We do this only when
2236
         * privileged however, as otherwise the amount of lockable memory that RLIMIT_MEMLOCK grants us is
2237
         * frequently too low to make this work. The resource limit has no effect on CAP_IPC_LOCK processes,
2238
         * hence that's the capability we check for. */
2239
        r = have_effective_cap(CAP_IPC_LOCK);
160✔
2240
        if (r < 0)
160✔
2241
                return log_debug_errno(r, "Failed to determine if we have CAP_IPC_LOCK: %m");
×
2242
        if (r == 0)
160✔
2243
                return log_debug_errno(SYNTHETIC_ERRNO(EPERM), "Lacking CAP_IPC_LOCK, skipping mlockall().");
×
2244

2245
        if (mlockall(flags) < 0)
160✔
2246
                return log_debug_errno(errno, "Failed to call mlockall(): %m");
×
2247

2248
        log_debug("Successfully called mlockall().");
160✔
2249
        return 0;
2250
}
2251

2252
static const char *const sigchld_code_table[] = {
2253
        [CLD_EXITED] = "exited",
2254
        [CLD_KILLED] = "killed",
2255
        [CLD_DUMPED] = "dumped",
2256
        [CLD_TRAPPED] = "trapped",
2257
        [CLD_STOPPED] = "stopped",
2258
        [CLD_CONTINUED] = "continued",
2259
};
2260

2261
DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
8,918✔
2262

2263
static const char* const sched_policy_table[] = {
2264
        [SCHED_OTHER] = "other",
2265
        [SCHED_BATCH] = "batch",
2266
        [SCHED_IDLE]  = "idle",
2267
        [SCHED_FIFO]  = "fifo",
2268
        [SCHED_EXT]   = "ext",
2269
        [SCHED_RR]    = "rr",
2270
};
2271

2272
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
53✔
2273

2274
_noreturn_ void report_errno_and_exit(int errno_fd, int error) {
176✔
2275
        int r;
176✔
2276

2277
        if (error >= 0)
176✔
2278
                _exit(EXIT_SUCCESS);
175✔
2279

2280
        assert(errno_fd >= 0);
1✔
2281

2282
        r = loop_write(errno_fd, &error, sizeof(error));
1✔
2283
        if (r < 0)
1✔
2284
                log_debug_errno(r, "Failed to write errno to errno_fd=%d: %m", errno_fd);
×
2285

2286
        _exit(EXIT_FAILURE);
1✔
2287
}
2288

2289
int read_errno(int errno_fd) {
134✔
2290
        int r;
134✔
2291

2292
        assert(errno_fd >= 0);
134✔
2293

2294
        /* The issue here is that it's impossible to distinguish between an error code returned by child and
2295
         * IO error arose when reading it. So, the function logs errors and return EIO for the later case. */
2296

2297
        ssize_t n = loop_read(errno_fd, &r, sizeof(r), /* do_poll= */ false);
134✔
2298
        if (n < 0) {
134✔
2299
                log_debug_errno(n, "Failed to read errno: %m");
×
2300
                return -EIO;
×
2301
        }
2302
        if (n == 0) /* the process exited without reporting an error, assuming success */
134✔
2303
                return 0;
2304
        if (n != sizeof(r))
×
2305
                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received unexpected amount of bytes (%zi) while reading errno.", n);
×
2306

2307
        if (r == 0)
×
2308
                return 0;
2309
        if (r < 0) /* child process reported an error, return it */
×
2310
                return log_debug_errno(r, "Child process failed with errno: %m");
×
2311

2312
        return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received positive errno from child, refusing: %d", r);
×
2313
}
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