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

systemd / systemd / 20321298054

17 Dec 2025 11:19PM UTC coverage: 72.709% (-0.03%) from 72.736%
20321298054

push

github

YHNdnzj
core: set Result=start-limit-hit when a unit is rate limited

There is currently no way to figure out a rate limit was hit on a unit,
as the last result is stripped in order to keep reporting the first
result, which is useful in case of a watchdog failure, which is the
reason why it was changed as such.

But rate limiting is also an important information to provide to
users, so allow the Result property to reflect it when it
happens.

6 of 7 new or added lines in 7 files covered. (85.71%)

1358 existing lines in 49 files now uncovered.

309654 of 425883 relevant lines covered (72.71%)

1138050.05 hits per line

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

83.02
/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/mount.h>
8
#include <sys/personality.h>
9
#include <sys/prctl.h>
10
#include <sys/wait.h>
11
#include <syslog.h>
12
#include <threads.h>
13
#include <unistd.h>
14
#if HAVE_VALGRIND_VALGRIND_H
15
#include <valgrind/valgrind.h>
16
#endif
17

18
#include "sd-messages.h"
19

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

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

62
static int get_process_state(pid_t pid) {
12,927✔
63
        _cleanup_free_ char *line = NULL;
12,927✔
64
        const char *p;
12,927✔
65
        char state;
12,927✔
66
        int r;
12,927✔
67

68
        assert(pid >= 0);
12,927✔
69

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

74
        p = procfs_file_alloca(pid, "stat");
12,927✔
75

76
        r = read_one_line_file(p, &line);
12,927✔
77
        if (r == -ENOENT)
12,927✔
78
                return -ESRCH;
79
        if (r < 0)
10,102✔
80
                return r;
81

82
        p = strrchr(line, ')');
10,101✔
83
        if (!p)
10,101✔
84
                return -EIO;
85

86
        p++;
10,101✔
87

88
        if (sscanf(p, " %c", &state) != 1)
10,101✔
89
                return -EIO;
90

91
        return (unsigned char) state;
10,101✔
92
}
93

94
int pid_get_comm(pid_t pid, char **ret) {
42,672✔
95
        _cleanup_free_ char *escaped = NULL, *comm = NULL;
42,672✔
96
        int r;
42,672✔
97

98
        assert(pid >= 0);
42,672✔
99
        assert(ret);
42,672✔
100

101
        if (pid == 0 || pid == getpid_cached()) {
42,672✔
102
                comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */
22,202✔
103
                if (!comm)
22,202✔
104
                        return -ENOMEM;
105

106
                if (prctl(PR_GET_NAME, comm) < 0)
22,202✔
107
                        return -errno;
×
108
        } else {
109
                const char *p;
20,470✔
110

111
                p = procfs_file_alloca(pid, "comm");
20,470✔
112

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

121
        escaped = new(char, COMM_MAX_LEN);
38,331✔
122
        if (!escaped)
38,331✔
123
                return -ENOMEM;
124

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

128
        *ret = TAKE_PTR(escaped);
38,331✔
129
        return 0;
38,331✔
130
}
131

132
int pidref_get_comm(const PidRef *pid, char **ret) {
158✔
133
        _cleanup_free_ char *comm = NULL;
158✔
134
        int r;
158✔
135

136
        if (!pidref_is_set(pid))
158✔
137
                return -ESRCH;
138

139
        if (pidref_is_remote(pid))
316✔
140
                return -EREMOTE;
141

142
        r = pid_get_comm(pid->pid, &comm);
158✔
143
        if (r < 0)
158✔
144
                return r;
145

146
        r = pidref_verify(pid);
158✔
147
        if (r < 0)
158✔
148
                return r;
149

150
        if (ret)
158✔
151
                *ret = TAKE_PTR(comm);
158✔
152
        return 0;
153
}
154

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

162
        _cleanup_free_ char *t = NULL;
19,387✔
163
        const char *p;
19,387✔
164
        size_t k;
19,387✔
165
        int r;
19,387✔
166

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

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

186
        if (k == 0) {
14,963✔
187
                if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
472✔
188
                        return -ENOENT;
449✔
189

190
                /* Kernel threads have no argv[] */
191
                _cleanup_free_ char *comm = NULL;
23✔
192

193
                r = pid_get_comm(pid, &comm);
23✔
194
                if (r < 0)
23✔
195
                        return r;
196

197
                free(t);
23✔
198
                t = strjoin("[", comm, "]");
23✔
199
                if (!t)
23✔
200
                        return -ENOMEM;
201

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

208
        if (ret)
14,514✔
209
                *ret = TAKE_PTR(t);
14,514✔
210
        if (ret_size)
14,514✔
211
                *ret_size = k;
14,514✔
212

213
        return r;
214
}
215

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

221
        assert(pid >= 0);
14,720✔
222
        assert(ret);
14,720✔
223

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

238
        int full = pid_get_cmdline_nulstr(pid, max_columns, flags, &t, &k);
14,720✔
239
        if (full < 0)
14,720✔
240
                return full;
241

242
        if (flags & (PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_QUOTE_POSIX)) {
9,922✔
243
                ShellEscapeFlags shflags = SHELL_ESCAPE_EMPTY |
9,533✔
244
                        FLAGS_SET(flags, PROCESS_CMDLINE_QUOTE_POSIX) * SHELL_ESCAPE_POSIX;
9,533✔
245

246
                assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
9,533✔
247

248
                _cleanup_strv_free_ char **args = NULL;
9,533✔
249

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

256
                ans = quote_command_line(args, shflags);
9,533✔
257
                if (!ans)
9,533✔
258
                        return -ENOMEM;
259
        } else {
260
                /* Arguments are separated by NULs. Let's replace those with spaces. */
261
                for (size_t i = 0; i < k - 1; i++)
18,687✔
262
                        if (t[i] == '\0')
18,298✔
263
                                t[i] = ' ';
664✔
264

265
                delete_trailing_chars(t, WHITESPACE);
389✔
266

267
                bool eight_bit = (flags & PROCESS_CMDLINE_USE_LOCALE) && !is_locale_utf8();
389✔
268

269
                ans = escape_non_printable_full(t, max_columns,
1,167✔
270
                                                eight_bit * XESCAPE_8_BIT | !full * XESCAPE_FORCE_ELLIPSIS);
724✔
271
                if (!ans)
389✔
272
                        return -ENOMEM;
273

274
                ans = str_realloc(ans);
389✔
275
        }
276

277
        *ret = ans;
9,922✔
278
        return 0;
9,922✔
279
}
280

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

285
        if (!pidref_is_set(pid))
46✔
286
                return -ESRCH;
287

288
        if (pidref_is_remote(pid))
92✔
289
                return -EREMOTE;
290

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

295
        r = pidref_verify(pid);
46✔
296
        if (r < 0)
46✔
297
                return r;
298

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

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

310
        assert(pid >= 0);
4,667✔
311
        assert((flags & ~PROCESS_CMDLINE_COMM_FALLBACK) == 0);
4,667✔
312
        assert(ret);
4,667✔
313

314
        r = pid_get_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k);
4,667✔
315
        if (r < 0)
4,667✔
316
                return r;
317

318
        args = strv_parse_nulstr_full(t, k, /* drop_trailing_nuls= */ true);
4,592✔
319
        if (!args)
4,592✔
320
                return -ENOMEM;
321

322
        *ret = args;
4,592✔
323
        return 0;
4,592✔
324
}
325

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

330
        if (!pidref_is_set(pid))
×
331
                return -ESRCH;
332

333
        if (pidref_is_remote(pid))
×
334
                return -EREMOTE;
335

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

340
        r = pidref_verify(pid);
×
341
        if (r < 0)
×
342
                return r;
343

344
        if (ret)
×
345
                *ret = TAKE_PTR(args);
×
346

347
        return 0;
348
}
349

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

356
        assert(machine);
35✔
357
        assert(pid);
35✔
358

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

364
        if (!hostname_is_valid(machine, 0))
34✔
365
                return -EINVAL;
366

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

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

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

387
        *pid = leader;
34✔
388
        return 0;
34✔
389
}
390

391
int pid_is_kernel_thread(pid_t pid) {
3,870✔
392
        _cleanup_free_ char *line = NULL;
3,870✔
393
        unsigned long long flags;
3,870✔
394
        size_t l, i;
3,870✔
395
        const char *p;
3,870✔
396
        char *q;
3,870✔
397
        int r;
3,870✔
398

399
        if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
3,870✔
400
                return 0;
25✔
401
        if (!pid_is_valid(pid))
3,845✔
402
                return -EINVAL;
403

404
        p = procfs_file_alloca(pid, "stat");
3,845✔
405
        r = read_one_line_file(p, &line);
3,845✔
406
        if (r == -ENOENT)
3,845✔
407
                return -ESRCH;
408
        if (r < 0)
3,845✔
409
                return r;
410

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

417
        /* Skip 6 fields to reach the flags field */
418
        for (i = 0; i < 6; i++) {
26,915✔
419
                l = strspn(q, WHITESPACE);
23,070✔
420
                if (l < 1)
23,070✔
421
                        return -EINVAL;
422
                q += l;
23,070✔
423

424
                l = strcspn(q, WHITESPACE);
23,070✔
425
                if (l < 1)
23,070✔
426
                        return -EINVAL;
427
                q += l;
23,070✔
428
        }
429

430
        /* Skip preceding whitespace */
431
        l = strspn(q, WHITESPACE);
3,845✔
432
        if (l < 1)
3,845✔
433
                return -EINVAL;
434
        q += l;
3,845✔
435

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

442
        r = safe_atollu(q, &flags);
3,845✔
443
        if (r < 0)
3,845✔
444
                return r;
445

446
        return !!(flags & PF_KTHREAD);
3,845✔
447
}
448

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

452
        if (!pidref_is_set(pid))
1,637✔
453
                return -ESRCH;
454

455
        if (pidref_is_remote(pid))
1,637✔
456
                return -EREMOTE;
457

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

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

466
        return result;
467
}
468

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

473
        assert(proc_file);
14,160✔
474

475
        p = procfs_file_alloca(pid, proc_file);
14,164✔
476

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

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

485
        assert(pid >= 0);
14,134✔
486

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

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

497
        return 0;
498
}
499

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

503
        assert(pid >= 0);
4,058✔
504
        assert(ret);
4,058✔
505

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

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

518
        return parse_uid(v, ret);
184✔
519
}
520

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

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

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

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

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

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

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

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

553
        assert(pid >= 0);
4,055✔
554
        assert(ret);
4,055✔
555

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

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

568
        return parse_gid(v, ret);
4,054✔
569
}
570

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

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

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

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

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

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

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

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

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

605
        for (;;) {
6,419✔
606
                char c;
6,434✔
607

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

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

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

620
                if (c == '\0')
6,419✔
621
                        outcome[sz++] = '\n';
228✔
622
                else
623
                        sz += cescape_char(c, outcome + sz);
6,191✔
624
        }
625

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

629
        return 0;
15✔
630
}
631

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

638
        assert(pid >= 0);
1,530✔
639

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

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

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

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

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

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

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

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

681
        if (ret)
1,519✔
682
                *ret = (pid_t) ppid;
1,519✔
683

684
        return 0;
685
}
686

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

690
        if (!pidref_is_set(pidref))
2,467✔
691
                return -ESRCH;
2,467✔
692

693
        if (pidref_is_remote(pidref))
2,467✔
694
                return -EREMOTE;
695

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

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

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

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

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

720
        assert(ret);
11✔
721

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

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

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

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

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

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

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

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

759
        assert(pid >= 0);
578✔
760

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

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

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

776
        unsigned long llu;
578✔
777

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

802
        if (ret)
578✔
803
                *ret = jiffies_to_usec(llu); /* CLOCK_BOOTTIME */
578✔
804

805
        return 0;
806
}
807

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

812
        if (!pidref_is_set(pid))
578✔
813
                return -ESRCH;
578✔
814

815
        if (pidref_is_remote(pid))
578✔
816
                return -EREMOTE;
817

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

822
        r = pidref_verify(pid);
578✔
823
        if (r < 0)
578✔
824
                return r;
825

826
        if (ret)
578✔
827
                *ret = t;
578✔
828

829
        return 0;
830
}
831

832
int get_process_umask(pid_t pid, mode_t *ret) {
21,998✔
833
        _cleanup_free_ char *m = NULL;
21,998✔
834
        int r;
21,998✔
835

836
        assert(pid >= 0);
21,998✔
837
        assert(ret);
21,998✔
838

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

845
        return parse_mode(m, ret);
21,998✔
846
}
847

848
int wait_for_terminate(pid_t pid, siginfo_t *ret) {
652✔
849
        return pidref_wait_for_terminate(&PIDREF_MAKE_FROM_PID(pid), ret);
652✔
850
}
851

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

869
        if (!pidref_is_set(pidref))
6,821✔
870
                return -ESRCH;
6,821✔
871
        if (pidref_is_remote(pidref))
13,642✔
872
                return -EREMOTE;
873
        if (pidref->pid == 1 || pidref_is_self(pidref))
6,821✔
874
                return -ECHILD;
×
875

876
        _cleanup_free_ char *buffer = NULL;
6,821✔
877
        if (!name) {
6,821✔
878
                r = pidref_get_comm(pidref, &buffer);
2✔
879
                if (r < 0)
2✔
880
                        log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pidref->pid);
×
881
                else
882
                        name = buffer;
2✔
883
        }
884

885
        int prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG;
6,821✔
886

887
        siginfo_t status;
6,821✔
888
        r = pidref_wait_for_terminate(pidref, &status);
6,821✔
889
        if (r < 0)
6,821✔
890
                return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name));
×
891

892
        if (status.si_code == CLD_EXITED) {
6,821✔
893
                if (status.si_status != EXIT_SUCCESS)
6,821✔
894
                        log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
64✔
895
                                 "%s failed with exit status %i.", strna(name), status.si_status);
896
                else
897
                        log_debug("%s succeeded.", name);
6,757✔
898

899
                return status.si_status;
6,821✔
900

901
        } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) {
×
902

903
                log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status));
×
904
                return -EPROTO;
×
905
        }
906

907
        log_full(prio, "%s failed due to unknown reason.", strna(name));
×
908
        return -EPROTO;
909
}
910

911
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
5,518✔
912
        return pidref_wait_for_terminate_and_check(name, &PIDREF_MAKE_FROM_PID(pid), flags);
5,518✔
913
}
914

915
/*
916
 * Return values:
917
 *
918
 * < 0 : wait_for_terminate_with_timeout() failed to get the state of the process, the process timed out, the process
919
 *       was terminated by a signal, or failed for an unknown reason.
920
 *
921
 * >=0 : The process terminated normally with no failures.
922
 *
923
 * Success is indicated by a return value of zero, a timeout is indicated by ETIMEDOUT, and all other child failure
924
 * states are indicated by error is indicated by a non-zero value.
925
 *
926
 * This call assumes SIGCHLD has been blocked already, in particular before the child to wait for has been forked off
927
 * to remain entirely race-free.
928
 */
929
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
×
930
        sigset_t mask;
×
931
        int r;
×
932
        usec_t until;
×
933

934
        assert_se(sigemptyset(&mask) == 0);
×
935
        assert_se(sigaddset(&mask, SIGCHLD) == 0);
×
936

937
        /* Drop into a sigtimewait-based timeout. Waiting for the
938
         * pid to exit. */
939
        until = usec_add(now(CLOCK_MONOTONIC), timeout);
×
940
        for (;;) {
×
941
                usec_t n;
×
942
                siginfo_t status = {};
×
943

944
                n = now(CLOCK_MONOTONIC);
×
945
                if (n >= until)
×
946
                        break;
947

948
                r = RET_NERRNO(sigtimedwait(&mask, NULL, TIMESPEC_STORE(until - n)));
×
949
                /* Assuming we woke due to the child exiting. */
950
                if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
×
951
                        if (status.si_pid == pid) {
×
952
                                /* This is the correct child. */
953
                                if (status.si_code == CLD_EXITED)
×
954
                                        return status.si_status == 0 ? 0 : -EPROTO;
×
955
                                else
956
                                        return -EPROTO;
957
                        }
958
                }
959
                /* Not the child, check for errors and proceed appropriately */
960
                if (r < 0) {
×
961
                        switch (r) {
×
962
                        case -EAGAIN:
963
                                /* Timed out, child is likely hung. */
964
                                return -ETIMEDOUT;
965
                        case -EINTR:
×
966
                                /* Received a different signal and should retry */
967
                                continue;
×
968
                        default:
×
969
                                /* Return any unexpected errors */
970
                                return r;
×
971
                        }
972
                }
973
        }
974

975
        return -EPROTO;
×
976
}
977

978
void sigkill_wait(pid_t pid) {
126✔
979
        assert(pid > 1);
126✔
980

981
        (void) kill(pid, SIGKILL);
126✔
982
        (void) wait_for_terminate(pid, NULL);
126✔
983
}
126✔
984

985
void sigkill_waitp(pid_t *pid) {
12,221✔
986
        PROTECT_ERRNO;
12,221✔
987

988
        if (!pid)
12,221✔
989
                return;
990
        if (*pid <= 1)
12,221✔
991
                return;
992

993
        sigkill_wait(*pid);
126✔
994
}
995

996
void sigterm_wait(pid_t pid) {
96✔
997
        assert(pid > 1);
96✔
998

999
        (void) kill_and_sigcont(pid, SIGTERM);
96✔
1000
        (void) wait_for_terminate(pid, NULL);
96✔
1001
}
96✔
1002

1003
void sigkill_nowait(pid_t pid) {
×
1004
        assert(pid > 1);
×
1005

1006
        (void) kill(pid, SIGKILL);
×
1007
}
×
1008

1009
void sigkill_nowaitp(pid_t *pid) {
×
1010
        PROTECT_ERRNO;
×
1011

1012
        if (!pid)
×
1013
                return;
1014
        if (*pid <= 1)
×
1015
                return;
1016

1017
        sigkill_nowait(*pid);
×
1018
}
1019

1020
int kill_and_sigcont(pid_t pid, int sig) {
96✔
1021
        int r;
96✔
1022

1023
        r = RET_NERRNO(kill(pid, sig));
96✔
1024

1025
        /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't
1026
         * affected by a process being suspended anyway. */
1027
        if (r >= 0 && !IN_SET(sig, SIGCONT, SIGKILL))
96✔
1028
                (void) kill(pid, SIGCONT);
96✔
1029

1030
        return r;
96✔
1031
}
1032

1033
int getenv_for_pid(pid_t pid, const char *field, char **ret) {
4,761✔
1034
        _cleanup_fclose_ FILE *f = NULL;
4,761✔
1035
        const char *path;
4,761✔
1036
        size_t sum = 0;
4,761✔
1037
        int r;
4,761✔
1038

1039
        assert(pid >= 0);
4,761✔
1040
        assert(field);
4,761✔
1041
        assert(ret);
4,761✔
1042

1043
        if (pid == 0 || pid == getpid_cached())
4,761✔
1044
                return strdup_to_full(ret, getenv(field));
14✔
1045

1046
        if (!pid_is_valid(pid))
4,747✔
1047
                return -EINVAL;
1048

1049
        path = procfs_file_alloca(pid, "environ");
4,747✔
1050

1051
        r = fopen_unlocked(path, "re", &f);
4,747✔
1052
        if (r == -ENOENT)
4,747✔
1053
                return -ESRCH;
1054
        if (r < 0)
4,340✔
1055
                return r;
1056

1057
        for (;;) {
50,844✔
1058
                _cleanup_free_ char *line = NULL;
23,928✔
1059
                const char *match;
26,934✔
1060

1061
                if (sum > ENVIRONMENT_BLOCK_MAX) /* Give up searching eventually */
26,934✔
1062
                        return -ENOBUFS;
1063

1064
                r = read_nul_string(f, LONG_LINE_MAX, &line);
26,934✔
1065
                if (r < 0)
26,934✔
1066
                        return r;
1067
                if (r == 0)  /* EOF */
26,934✔
1068
                        break;
1069

1070
                sum += r;
23,928✔
1071

1072
                match = startswith(line, field);
23,928✔
1073
                if (match && *match == '=')
23,928✔
1074
                        return strdup_to_full(ret, match + 1);
18✔
1075
        }
1076

1077
        *ret = NULL;
3,006✔
1078
        return 0;
3,006✔
1079
}
1080

1081
int pidref_is_my_child(PidRef *pid) {
2,445✔
1082
        int r;
2,445✔
1083

1084
        if (!pidref_is_set(pid))
2,445✔
1085
                return -ESRCH;
2,445✔
1086

1087
        if (pidref_is_remote(pid))
2,445✔
1088
                return -EREMOTE;
1089

1090
        if (pid->pid == 1 || pidref_is_self(pid))
2,445✔
1091
                return false;
×
1092

1093
        pid_t ppid;
2,445✔
1094
        r = pidref_get_ppid(pid, &ppid);
2,445✔
1095
        if (r == -EADDRNOTAVAIL) /* if this process is outside of our pidns, it is definitely not our child */
2,445✔
1096
                return false;
1097
        if (r < 0)
2,445✔
1098
                return r;
1099

1100
        return ppid == getpid_cached();
2,445✔
1101
}
1102

1103
int pid_is_my_child(pid_t pid) {
×
1104

1105
        if (pid == 0)
×
1106
                return false;
×
1107

1108
        return pidref_is_my_child(&PIDREF_MAKE_FROM_PID(pid));
×
1109
}
1110

1111
int pidref_is_unwaited(PidRef *pid) {
8,614✔
1112
        int r;
8,614✔
1113

1114
        /* Checks whether a PID is still valid at all, including a zombie */
1115

1116
        if (!pidref_is_set(pid))
8,614✔
1117
                return -ESRCH;
1118

1119
        if (pidref_is_remote(pid))
8,613✔
1120
                return -EREMOTE;
1121

1122
        if (pid->pid == 1 || pidref_is_self(pid))
8,613✔
1123
                return true;
3✔
1124

1125
        r = pidref_kill(pid, 0);
8,610✔
1126
        if (r == -ESRCH)
8,610✔
1127
                return false;
1128
        if (r < 0)
2,097✔
1129
                return r;
195✔
1130

1131
        return true;
1132
}
1133

1134
int pid_is_unwaited(pid_t pid) {
8,036✔
1135

1136
        if (pid == 0)
8,036✔
1137
                return true;
8,036✔
1138

1139
        return pidref_is_unwaited(&PIDREF_MAKE_FROM_PID(pid));
8,036✔
1140
}
1141

1142
int pid_is_alive(pid_t pid) {
12,929✔
1143
        int r;
12,929✔
1144

1145
        /* Checks whether a PID is still valid and not a zombie */
1146

1147
        if (pid < 0)
12,929✔
1148
                return -ESRCH;
1149

1150
        if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
12,928✔
1151
                return true;
1152

1153
        if (pid == getpid_cached())
12,928✔
1154
                return true;
1155

1156
        r = get_process_state(pid);
12,927✔
1157
        if (r == -ESRCH)
12,927✔
1158
                return false;
1159
        if (r < 0)
10,101✔
1160
                return r;
1161

1162
        return r != 'Z';
10,101✔
1163
}
1164

1165
int pidref_is_alive(const PidRef *pidref) {
12,926✔
1166
        int r, result;
12,926✔
1167

1168
        if (!pidref_is_set(pidref))
12,926✔
1169
                return -ESRCH;
1170

1171
        if (pidref_is_remote(pidref))
12,924✔
1172
                return -EREMOTE;
1173

1174
        result = pid_is_alive(pidref->pid);
12,924✔
1175
        if (result < 0) {
12,924✔
1176
                assert(result != -ESRCH);
×
1177
                return result;
1178
        }
1179

1180
        r = pidref_verify(pidref);
12,924✔
1181
        if (r == -ESRCH)
12,924✔
1182
                return false;
1183
        if (r < 0)
10,097✔
1184
                return r;
×
1185

1186
        return result;
1187
}
1188

1189
int pidref_from_same_root_fs(PidRef *a, PidRef *b) {
20✔
1190
        _cleanup_(pidref_done) PidRef self = PIDREF_NULL;
×
1191
        int r;
20✔
1192

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

1196
        if (!a || !b) {
20✔
1197
                r = pidref_set_self(&self);
×
1198
                if (r < 0)
×
1199
                        return r;
1200
                if (!a)
×
1201
                        a = &self;
×
1202
                if (!b)
×
1203
                        b = &self;
×
1204
        }
1205

1206
        if (!pidref_is_set(a) || !pidref_is_set(b))
20✔
1207
                return -ESRCH;
×
1208

1209
        /* If one of the two processes have the same root they cannot have the same root fs, but if both of
1210
         * them do we don't know */
1211
        if (pidref_is_remote(a) && pidref_is_remote(b))
20✔
1212
                return -EREMOTE;
1213
        if (pidref_is_remote(a) || pidref_is_remote(b))
60✔
1214
                return false;
1215

1216
        if (pidref_equal(a, b))
20✔
1217
                return true;
1218

1219
        const char *roota = procfs_file_alloca(a->pid, "root");
18✔
1220
        const char *rootb = procfs_file_alloca(b->pid, "root");
18✔
1221

1222
        int result = inode_same(roota, rootb, 0);
18✔
1223
        if (result == -ENOENT)
18✔
1224
                return proc_mounted() == 0 ? -ENOSYS : -ESRCH;
×
1225
        if (result < 0)
18✔
1226
                return result;
1227

1228
        r = pidref_verify(a);
18✔
1229
        if (r < 0)
18✔
1230
                return r;
1231
        r = pidref_verify(b);
18✔
1232
        if (r < 0)
18✔
1233
                return r;
×
1234

1235
        return result;
1236
}
1237

1238
bool is_main_thread(void) {
7,236,698✔
1239
        static thread_local int cached = -1;
7,236,698✔
1240

1241
        if (cached < 0)
7,236,698✔
1242
                cached = getpid_cached() == gettid();
55,870✔
1243

1244
        return cached;
7,236,698✔
1245
}
1246

1247
bool oom_score_adjust_is_valid(int oa) {
6,743✔
1248
        return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
6,743✔
1249
}
1250

1251
unsigned long personality_from_string(const char *p) {
9✔
1252
        Architecture architecture;
9✔
1253

1254
        if (!p)
9✔
1255
                return PERSONALITY_INVALID;
1256

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

1261
        architecture = architecture_from_string(p);
8✔
1262
        if (architecture < 0)
8✔
1263
                return PERSONALITY_INVALID;
1264

1265
        if (architecture == native_architecture())
6✔
1266
                return PER_LINUX;
1267
#ifdef ARCHITECTURE_SECONDARY
1268
        if (architecture == ARCHITECTURE_SECONDARY)
3✔
1269
                return PER_LINUX32;
2✔
1270
#endif
1271

1272
        return PERSONALITY_INVALID;
1273
}
1274

1275
const char* personality_to_string(unsigned long p) {
2,805✔
1276
        Architecture architecture = _ARCHITECTURE_INVALID;
2,805✔
1277

1278
        if (p == PER_LINUX)
2,805✔
1279
                architecture = native_architecture();
1280
#ifdef ARCHITECTURE_SECONDARY
1281
        else if (p == PER_LINUX32)
2,800✔
1282
                architecture = ARCHITECTURE_SECONDARY;
1283
#endif
1284

1285
        if (architecture < 0)
1286
                return NULL;
1287

1288
        return architecture_to_string(architecture);
7✔
1289
}
1290

1291
int safe_personality(unsigned long p) {
1,481✔
1292
        int ret;
1,481✔
1293

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

1301
        errno = 0;
1,481✔
1302
        ret = personality(p);
1,481✔
1303
        if (ret < 0) {
1,481✔
1304
                if (errno != 0)
12✔
1305
                        return -errno;
12✔
1306

1307
                errno = -ret;
×
1308
        }
1309

1310
        return ret;
1311
}
1312

1313
int opinionated_personality(unsigned long *ret) {
1,466✔
1314
        int current;
1,466✔
1315

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

1320
        current = safe_personality(PERSONALITY_INVALID);
1,466✔
1321
        if (current < 0)
1,466✔
1322
                return current;
1323

1324
        if (((unsigned long) current & OPINIONATED_PERSONALITY_MASK) == PER_LINUX32)
1,466✔
1325
                *ret = PER_LINUX32;
×
1326
        else
1327
                *ret = PER_LINUX;
1,466✔
1328

1329
        return 0;
1330
}
1331

1332
void valgrind_summary_hack(void) {
39✔
1333
#if HAVE_VALGRIND_VALGRIND_H
1334
        if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) {
1335
                pid_t pid;
1336
                pid = raw_clone(SIGCHLD);
1337
                if (pid < 0)
1338
                        log_struct_errno(
1339
                                LOG_EMERG, errno,
1340
                                LOG_MESSAGE_ID(SD_MESSAGE_VALGRIND_HELPER_FORK_STR),
1341
                                LOG_MESSAGE("Failed to fork off valgrind helper: %m"));
1342
                else if (pid == 0)
1343
                        exit(EXIT_SUCCESS);
1344
                else {
1345
                        log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
1346
                        (void) wait_for_terminate(pid, NULL);
1347
                }
1348
        }
1349
#endif
1350
}
39✔
1351

1352
int pid_compare_func(const pid_t *a, const pid_t *b) {
859✔
1353
        /* Suitable for usage in qsort() */
1354
        return CMP(*a, *b);
859✔
1355
}
1356

1357
bool nice_is_valid(int n) {
882✔
1358
        return n >= PRIO_MIN && n < PRIO_MAX;
882✔
1359
}
1360

1361
bool sched_policy_is_valid(int i) {
×
1362
        return IN_SET(i, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR);
×
1363
}
1364

1365
bool sched_priority_is_valid(int i) {
×
1366
        return i >= 0 && i <= sched_get_priority_max(SCHED_RR);
×
1367
}
1368

1369
/* The cached PID, possible values:
1370
 *
1371
 *     == UNSET [0]  → cache not initialized yet
1372
 *     == BUSY [-1]  → some thread is initializing it at the moment
1373
 *     any other     → the cached PID
1374
 */
1375

1376
#define CACHED_PID_UNSET ((pid_t) 0)
1377
#define CACHED_PID_BUSY ((pid_t) -1)
1378

1379
static pid_t cached_pid = CACHED_PID_UNSET;
1380

1381
void reset_cached_pid(void) {
1,574✔
1382
        /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
1383
        cached_pid = CACHED_PID_UNSET;
1,574✔
1384
}
1,574✔
1385

1386
pid_t getpid_cached(void) {
151,152,845✔
1387
        static bool installed = false;
151,152,845✔
1388
        pid_t current_value = CACHED_PID_UNSET;
151,152,845✔
1389

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

1399
        (void) __atomic_compare_exchange_n(
151,152,845✔
1400
                        &cached_pid,
1401
                        &current_value,
1402
                        CACHED_PID_BUSY,
1403
                        false,
1404
                        __ATOMIC_SEQ_CST,
1405
                        __ATOMIC_SEQ_CST);
1406

1407
        switch (current_value) {
151,152,845✔
1408

1409
        case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */
102,466✔
1410
                pid_t new_pid;
102,466✔
1411

1412
                new_pid = getpid();
102,466✔
1413

1414
                if (!installed) {
102,466✔
1415
                        /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's
1416
                         * only half-documented (glibc doesn't document it but LSB does — though only superficially)
1417
                         * we'll check for errors only in the most generic fashion possible. */
1418

1419
                        if (pthread_atfork(NULL, NULL, reset_cached_pid) != 0) {
71,923✔
1420
                                /* OOM? Let's try again later */
1421
                                cached_pid = CACHED_PID_UNSET;
×
1422
                                return new_pid;
×
1423
                        }
1424

1425
                        installed = true;
71,923✔
1426
                }
1427

1428
                cached_pid = new_pid;
102,466✔
1429
                return new_pid;
102,466✔
1430
        }
1431

1432
        case CACHED_PID_BUSY: /* Somebody else is currently initializing */
×
1433
                return getpid();
×
1434

1435
        default: /* Properly initialized */
1436
                return current_value;
1437
        }
1438
}
1439

1440
int must_be_root(void) {
56✔
1441

1442
        if (geteuid() == 0)
56✔
1443
                return 0;
1444

1445
        return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root.");
×
1446
}
1447

1448
pid_t clone_with_nested_stack(int (*fn)(void *), int flags, void *userdata) {
3,516✔
1449
        size_t ps;
3,516✔
1450
        pid_t pid;
3,516✔
1451
        void *mystack;
3,516✔
1452

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

1461
        assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
3,516✔
1462
                         CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
1463

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

1471
        ps = page_size();
3,516✔
1472
        mystack = alloca(ps*3);
3,516✔
1473
        mystack = (uint8_t*) mystack + ps; /* move pointer one page ahead since stacks usually grow backwards */
3,516✔
1474
        mystack = (void*) ALIGN_TO((uintptr_t) mystack, ps); /* align to page size (moving things further ahead) */
3,516✔
1475

1476
#if HAVE_CLONE
1477
        pid = clone(fn, mystack, flags, userdata);
3,516✔
1478
#else
1479
        pid = __clone2(fn, mystack, ps, flags, userdata);
1480
#endif
1481
        if (pid < 0)
3,516✔
1482
                return -errno;
×
1483

1484
        return pid;
1485
}
1486

1487
static void restore_sigsetp(sigset_t **ssp) {
58,149✔
1488
        if (*ssp)
58,149✔
1489
                (void) sigprocmask(SIG_SETMASK, *ssp, NULL);
24,113✔
1490
}
58,149✔
1491

1492
static int fork_flags_to_signal(ForkFlags flags) {
28,730✔
1493
        return (flags & FORK_DEATHSIG_SIGTERM) ? SIGTERM :
28,730✔
1494
                (flags & FORK_DEATHSIG_SIGINT) ? SIGINT :
552✔
1495
                                                 SIGKILL;
1496
}
1497

1498
int pidref_safe_fork_full(
28,311✔
1499
                const char *name,
1500
                const int stdio_fds[3],
1501
                int except_fds[],
1502
                size_t n_except_fds,
1503
                ForkFlags flags,
1504
                PidRef *ret_pid) {
1505

1506
        pid_t original_pid, pid;
28,311✔
1507
        sigset_t saved_ss, ss;
28,311✔
1508
        _unused_ _cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
×
1509
        bool block_signals = false, block_all = false, intermediary = false;
28,311✔
1510
        _cleanup_close_pair_ int pidref_transport_fds[2] = EBADF_PAIR;
58,149✔
1511
        int prio, r;
28,311✔
1512

1513
        assert(!FLAGS_SET(flags, FORK_WAIT|FORK_FREEZE));
28,311✔
1514
        assert(!FLAGS_SET(flags, FORK_DETACH) ||
28,311✔
1515
               (flags & (FORK_WAIT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL)) == 0);
1516

1517
        /* A wrapper around fork(), that does a couple of important initializations in addition to mere
1518
         * forking. If provided, ret_pid is initialized in both the parent and the child process, both times
1519
         * referencing the child process. Returns == 0 in the child and > 0 in the parent. */
1520

1521
        prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG;
28,311✔
1522

1523
        original_pid = getpid_cached();
28,311✔
1524

1525
        if (flags & FORK_FLUSH_STDIO) {
28,311✔
1526
                fflush(stdout);
5✔
1527
                fflush(stderr); /* This one shouldn't be necessary, stderr should be unbuffered anyway, but let's better be safe than sorry */
5✔
1528
        }
1529

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

1535
                assert_se(sigfillset(&ss) >= 0);
24,286✔
1536
                block_signals = block_all = true;
1537

1538
        } else if (flags & FORK_WAIT) {
4,025✔
1539
                /* Let's block SIGCHLD at least, so that we can safely watch for the child process */
1540

1541
                assert_se(sigemptyset(&ss) >= 0);
148✔
1542
                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
148✔
1543
                block_signals = true;
1544
        }
1545

1546
        if (block_signals) {
1547
                if (sigprocmask(SIG_BLOCK, &ss, &saved_ss) < 0)
24,434✔
1548
                        return log_full_errno(prio, errno, "Failed to block signal mask: %m");
×
1549
                saved_ssp = &saved_ss;
24,434✔
1550
        }
1551

1552
        if (FLAGS_SET(flags, FORK_DETACH)) {
28,311✔
1553
                /* Fork off intermediary child if needed */
1554

1555
                r = is_reaper_process();
105✔
1556
                if (r < 0)
105✔
1557
                        return log_full_errno(prio, r, "Failed to determine if we are a reaper process: %m");
×
1558

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

1562
                        if (ret_pid && socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pidref_transport_fds) < 0)
11✔
1563
                                return log_full_errno(prio, errno, "Failed to allocate pidref socket: %m");
×
1564

1565
                        pid = fork();
11✔
1566
                        if (pid < 0)
28✔
1567
                                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
×
1568
                        if (pid > 0) {
28✔
1569
                                log_debug("Successfully forked off intermediary '%s' as PID " PID_FMT ".", strna(name), pid);
11✔
1570

1571
                                pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
11✔
1572

1573
                                if (pidref_transport_fds[0] >= 0) {
11✔
1574
                                        /* Wait for the intermediary child to exit so the caller can be certain the actual child
1575
                                         * process has been reparented by the time this function returns. */
1576
                                        r = wait_for_terminate_and_check(name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
20✔
1577
                                        if (r < 0)
10✔
1578
                                                return log_full_errno(prio, r, "Failed to wait for intermediary process: %m");
×
1579
                                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
10✔
1580
                                                return -EPROTO;
1581

1582
                                        int pidfd;
10✔
1583
                                        ssize_t n = receive_one_fd_iov(
20✔
1584
                                                        pidref_transport_fds[0],
1585
                                                        &IOVEC_MAKE(&pid, sizeof(pid)),
10✔
1586
                                                        /* iovlen= */ 1,
1587
                                                        /* flags= */ 0,
1588
                                                        &pidfd);
1589
                                        if (n < 0)
10✔
1590
                                                return log_full_errno(prio, n, "Failed to receive child pidref: %m");
×
1591

1592
                                        *ret_pid = (PidRef) { .pid = pid, .fd = pidfd };
10✔
1593
                                }
1594

1595
                                return 1; /* return in the parent */
11✔
1596
                        }
1597

1598
                        pidref_transport_fds[0] = safe_close(pidref_transport_fds[0]);
17✔
1599
                        intermediary = true;
17✔
1600
                }
1601
        }
1602

1603
        if ((flags & (FORK_NEW_MOUNTNS|FORK_NEW_USERNS|FORK_NEW_NETNS|FORK_NEW_PIDNS)) != 0)
28,317✔
1604
                pid = raw_clone(SIGCHLD|
5,561✔
1605
                                (FLAGS_SET(flags, FORK_NEW_MOUNTNS) ? CLONE_NEWNS : 0) |
5,561✔
1606
                                (FLAGS_SET(flags, FORK_NEW_USERNS) ? CLONE_NEWUSER : 0) |
5,561✔
1607
                                (FLAGS_SET(flags, FORK_NEW_NETNS) ? CLONE_NEWNET : 0) |
5,561✔
1608
                                (FLAGS_SET(flags, FORK_NEW_PIDNS) ? CLONE_NEWPID : 0));
5,561✔
1609
        else
1610
                pid = fork();
22,756✔
1611
        if (pid < 0)
58,149✔
1612
                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
×
1613
        if (pid > 0) {
58,149✔
1614

1615
                /* If we are in the intermediary process, exit now */
1616
                if (intermediary) {
27,990✔
1617
                        if (pidref_transport_fds[1] >= 0) {
11✔
1618
                                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
10✔
1619

1620
                                r = pidref_set_pid(&pidref, pid);
10✔
1621
                                if (r < 0) {
10✔
1622
                                        log_full_errno(prio, r, "Failed to open reference to PID "PID_FMT": %m", pid);
×
1623
                                        _exit(EXIT_FAILURE);
×
1624
                                }
1625

1626
                                r = send_one_fd_iov(
10✔
1627
                                                pidref_transport_fds[1],
1628
                                                pidref.fd,
1629
                                                &IOVEC_MAKE(&pidref.pid, sizeof(pidref.pid)),
1630
                                                /* iovlen= */ 1,
1631
                                                /* flags= */ 0);
1632
                                if (r < 0) {
10✔
1633
                                        log_full_errno(prio, r, "Failed to send child pidref: %m");
×
1634
                                        _exit(EXIT_FAILURE);
×
1635
                                }
1636
                        }
1637

1638
                        _exit(EXIT_SUCCESS);
11✔
1639
                }
1640

1641
                /* We are in the parent process */
1642
                log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
27,979✔
1643

1644
                if (flags & FORK_WAIT) {
27,979✔
1645
                        if (block_all) {
806✔
1646
                                /* undo everything except SIGCHLD */
1647
                                ss = saved_ss;
658✔
1648
                                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
658✔
1649
                                (void) sigprocmask(SIG_SETMASK, &ss, NULL);
658✔
1650
                        }
1651

1652
                        r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
967✔
1653
                        if (r < 0)
806✔
1654
                                return r;
1655
                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
806✔
1656
                                return -EPROTO;
1657

1658
                        /* If we are in the parent and successfully waited, then the process doesn't exist anymore. */
1659
                        if (ret_pid)
806✔
1660
                                *ret_pid = PIDREF_NULL;
14✔
1661

1662
                        return 1;
806✔
1663
                }
1664

1665
                if (ret_pid) {
27,173✔
1666
                        if (FLAGS_SET(flags, _FORK_PID_ONLY))
26,573✔
1667
                                *ret_pid = PIDREF_MAKE_FROM_PID(pid);
7,339✔
1668
                        else {
1669
                                r = pidref_set_pid(ret_pid, pid);
19,234✔
1670
                                if (r < 0) /* Let's not fail for this, no matter what, the process exists after all, and that's key */
19,234✔
1671
                                        *ret_pid = PIDREF_MAKE_FROM_PID(pid);
×
1672
                        }
1673
                }
1674

1675
                return 1;
27,173✔
1676
        }
1677

1678
        /* We are in the child process */
1679

1680
        pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
30,159✔
1681

1682
        /* Restore signal mask manually */
1683
        saved_ssp = NULL;
30,159✔
1684

1685
        if (flags & FORK_REOPEN_LOG) {
30,159✔
1686
                /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
1687
                log_close();
6,777✔
1688
                log_set_open_when_needed(true);
6,777✔
1689
                log_settle_target();
6,777✔
1690
        }
1691

1692
        if (name) {
30,159✔
1693
                r = rename_process(name);
30,159✔
1694
                if (r < 0)
30,159✔
1695
                        log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG,
×
1696
                                       r, "Failed to rename process, ignoring: %m");
1697
        }
1698

1699
        /* let's disable dlopen() in the child, as a paranoia safety precaution: children should not live for
1700
         * long and only do minimal work before exiting or exec()ing. Doing dlopen() is not either. If people
1701
         * want dlopen() they should do it before forking. This is a safety precaution in particular for
1702
         * cases where the child does namespace shenanigans: we should never end up loading a module from a
1703
         * foreign environment. Note that this has no effect on NSS! (i.e. it only has effect on uses of our
1704
         * dlopen_safe(), which we use comprehensively in our codebase, but glibc NSS doesn't bother, of
1705
         * course.) */
1706
        if (!FLAGS_SET(flags, FORK_ALLOW_DLOPEN))
30,159✔
1707
                block_dlopen();
30,125✔
1708

1709
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL))
30,159✔
1710
                if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) {
28,730✔
1711
                        log_full_errno(prio, errno, "Failed to set death signal: %m");
×
UNCOV
1712
                        _exit(EXIT_FAILURE);
×
1713
                }
1714

1715
        if (flags & FORK_RESET_SIGNALS) {
30,159✔
1716
                r = reset_all_signal_handlers();
25,138✔
1717
                if (r < 0) {
25,138✔
1718
                        log_full_errno(prio, r, "Failed to reset signal handlers: %m");
×
UNCOV
1719
                        _exit(EXIT_FAILURE);
×
1720
                }
1721

1722
                /* This implicitly undoes the signal mask stuff we did before the fork()ing above */
1723
                r = reset_signal_mask();
25,138✔
1724
                if (r < 0) {
25,138✔
1725
                        log_full_errno(prio, r, "Failed to reset signal mask: %m");
×
UNCOV
1726
                        _exit(EXIT_FAILURE);
×
1727
                }
1728
        } else if (block_signals) { /* undo what we did above */
5,021✔
1729
                if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
4,594✔
1730
                        log_full_errno(prio, errno, "Failed to restore signal mask: %m");
×
UNCOV
1731
                        _exit(EXIT_FAILURE);
×
1732
                }
1733
        }
1734

1735
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL|FORK_DEATHSIG_SIGINT)) {
30,159✔
1736
                pid_t ppid;
28,730✔
1737
                /* Let's see if the parent PID is still the one we started from? If not, then the parent
1738
                 * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
1739

1740
                ppid = getppid();
28,730✔
1741
                if (ppid == 0)
28,730✔
1742
                        /* Parent is in a different PID namespace. */;
1743
                else if (ppid != original_pid) {
28,692✔
1744
                        int sig = fork_flags_to_signal(flags);
×
1745
                        log_debug("Parent died early, raising %s.", signal_to_string(sig));
×
1746
                        (void) raise(sig);
×
UNCOV
1747
                        _exit(EXIT_FAILURE);
×
1748
                }
1749
        }
1750

1751
        if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) {
30,159✔
1752
                /* Optionally, make sure we never propagate mounts to the host. */
1753
                if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
144✔
1754
                        log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
×
UNCOV
1755
                        _exit(EXIT_FAILURE);
×
1756
                }
1757
        }
1758

1759
        if (FLAGS_SET(flags, FORK_PRIVATE_TMP)) {
30,159✔
UNCOV
1760
                assert(FLAGS_SET(flags, FORK_NEW_MOUNTNS));
×
1761

1762
                /* Optionally, overmount new tmpfs instance on /tmp/. */
UNCOV
1763
                r = mount_nofollow("tmpfs", "/tmp", "tmpfs",
×
1764
                                   MS_NOSUID|MS_NODEV,
1765
                                   "mode=01777" TMPFS_LIMITS_RUN);
1766
                if (r < 0) {
×
1767
                        log_full_errno(prio, r, "Failed to overmount /tmp/: %m");
×
UNCOV
1768
                        _exit(EXIT_FAILURE);
×
1769
                }
1770
        }
1771

1772
        if (flags & FORK_REARRANGE_STDIO) {
30,159✔
1773
                if (stdio_fds) {
15,984✔
1774
                        r = rearrange_stdio(stdio_fds[0], stdio_fds[1], stdio_fds[2]);
15,968✔
1775
                        if (r < 0) {
15,968✔
1776
                                log_full_errno(prio, r, "Failed to rearrange stdio fds: %m");
×
UNCOV
1777
                                _exit(EXIT_FAILURE);
×
1778
                        }
1779

1780
                        /* Turn off O_NONBLOCK on the fdio fds, in case it was left on */
1781
                        stdio_disable_nonblock();
15,968✔
1782
                } else {
1783
                        r = make_null_stdio();
16✔
1784
                        if (r < 0) {
16✔
1785
                                log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
×
UNCOV
1786
                                _exit(EXIT_FAILURE);
×
1787
                        }
1788
                }
1789
        } else if (flags & FORK_STDOUT_TO_STDERR) {
14,175✔
1790
                if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
2✔
1791
                        log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
×
UNCOV
1792
                        _exit(EXIT_FAILURE);
×
1793
                }
1794
        }
1795

1796
        if (flags & FORK_CLOSE_ALL_FDS) {
30,159✔
1797
                /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
1798
                log_close();
24,332✔
1799

1800
                r = close_all_fds(except_fds, n_except_fds);
24,332✔
1801
                if (r < 0) {
24,332✔
1802
                        log_full_errno(prio, r, "Failed to close all file descriptors: %m");
×
UNCOV
1803
                        _exit(EXIT_FAILURE);
×
1804
                }
1805
        }
1806

1807
        if (flags & FORK_PACK_FDS) {
30,159✔
1808
                /* FORK_CLOSE_ALL_FDS ensures that except_fds are the only FDs >= 3 that are
1809
                 * open, this is including the log. This is required by pack_fds, which will
1810
                 * get stuck in an infinite loop of any FDs other than except_fds are open. */
1811
                assert(FLAGS_SET(flags, FORK_CLOSE_ALL_FDS));
92✔
1812

1813
                r = pack_fds(except_fds, n_except_fds);
92✔
1814
                if (r < 0) {
92✔
1815
                        log_full_errno(prio, r, "Failed to pack file descriptors: %m");
×
UNCOV
1816
                        _exit(EXIT_FAILURE);
×
1817
                }
1818
        }
1819

1820
        if (flags & FORK_CLOEXEC_OFF) {
30,159✔
1821
                r = fd_cloexec_many(except_fds, n_except_fds, false);
107✔
1822
                if (r < 0) {
107✔
1823
                        log_full_errno(prio, r, "Failed to turn off O_CLOEXEC on file descriptors: %m");
×
UNCOV
1824
                        _exit(EXIT_FAILURE);
×
1825
                }
1826
        }
1827

1828
        /* When we were asked to reopen the logs, do so again now */
1829
        if (flags & FORK_REOPEN_LOG) {
30,159✔
1830
                log_open();
6,777✔
1831
                log_set_open_when_needed(false);
6,777✔
1832
        }
1833

1834
        if (flags & FORK_RLIMIT_NOFILE_SAFE) {
30,159✔
1835
                r = rlimit_nofile_safe();
17,108✔
1836
                if (r < 0) {
17,108✔
1837
                        log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
×
UNCOV
1838
                        _exit(EXIT_FAILURE);
×
1839
                }
1840
        }
1841

1842
        if (!FLAGS_SET(flags, FORK_KEEP_NOTIFY_SOCKET)) {
30,159✔
1843
                r = RET_NERRNO(unsetenv("NOTIFY_SOCKET"));
30,159✔
1844
                if (r < 0) {
×
1845
                        log_full_errno(prio, r, "Failed to unset $NOTIFY_SOCKET: %m");
×
UNCOV
1846
                        _exit(EXIT_FAILURE);
×
1847
                }
1848
        }
1849

1850
        if (FLAGS_SET(flags, FORK_FREEZE))
30,159✔
UNCOV
1851
                freeze();
×
1852

1853
        if (ret_pid) {
30,159✔
1854
                if (FLAGS_SET(flags, _FORK_PID_ONLY))
28,633✔
1855
                        *ret_pid = PIDREF_MAKE_FROM_PID(getpid_cached());
7,283✔
1856
                else {
1857
                        r = pidref_set_self(ret_pid);
21,350✔
1858
                        if (r < 0) {
21,350✔
1859
                                log_full_errno(prio, r, "Failed to acquire PID reference on ourselves: %m");
×
UNCOV
1860
                                _exit(EXIT_FAILURE);
×
1861
                        }
1862
                }
1863
        }
1864

1865
        return 0;
1866
}
1867

1868
int safe_fork_full(
9,060✔
1869
                const char *name,
1870
                const int stdio_fds[3],
1871
                int except_fds[],
1872
                size_t n_except_fds,
1873
                ForkFlags flags,
1874
                pid_t *ret_pid) {
1875

1876
        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
17,485✔
1877
        int r;
9,060✔
1878

1879
        /* Getting the detached child process pid without pidfd is racy, so don't allow it if not returning
1880
         * a pidref to the caller. */
1881
        assert(!FLAGS_SET(flags, FORK_DETACH) || !ret_pid);
9,060✔
1882

1883
        r = pidref_safe_fork_full(name, stdio_fds, except_fds, n_except_fds, flags|_FORK_PID_ONLY, ret_pid ? &pidref : NULL);
10,514✔
1884
        if (r < 0 || !ret_pid)
17,485✔
1885
                return r;
1886

1887
        *ret_pid = pidref.pid;
14,634✔
1888

1889
        return r;
14,634✔
1890
}
1891

1892
int namespace_fork(
129✔
1893
                const char *outer_name,
1894
                const char *inner_name,
1895
                int except_fds[],
1896
                size_t n_except_fds,
1897
                ForkFlags flags,
1898
                int pidns_fd,
1899
                int mntns_fd,
1900
                int netns_fd,
1901
                int userns_fd,
1902
                int root_fd,
1903
                pid_t *ret_pid) {
1904

1905
        int r;
129✔
1906

1907
        /* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle
1908
         * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
1909
         * /proc/self/fd works correctly. */
1910
        assert(!FLAGS_SET(flags, FORK_ALLOW_DLOPEN)); /* never allow loading shared library from another ns */
129✔
1911

1912
        r = safe_fork_full(outer_name,
344✔
1913
                           NULL,
1914
                           except_fds, n_except_fds,
1915
                           (flags|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
129✔
1916
        if (r < 0)
215✔
1917
                return r;
1918
        if (r == 0) {
215✔
1919
                pid_t pid;
86✔
1920

1921
                /* Child */
1922

1923
                r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
86✔
1924
                if (r < 0) {
86✔
UNCOV
1925
                        log_full_errno(FLAGS_SET(flags, FORK_LOG) ? LOG_ERR : LOG_DEBUG, r, "Failed to join namespace: %m");
×
UNCOV
1926
                        _exit(EXIT_FAILURE);
×
1927
                }
1928

1929
                /* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */
1930
                r = safe_fork_full(inner_name,
259✔
1931
                                   NULL,
1932
                                   except_fds, n_except_fds,
1933
                                   flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO), &pid);
86✔
1934
                if (r < 0)
173✔
UNCOV
1935
                        _exit(EXIT_FAILURE);
×
1936
                if (r == 0) {
173✔
1937
                        /* Child */
1938
                        if (ret_pid)
87✔
1939
                                *ret_pid = pid;
87✔
1940
                        return 0;
87✔
1941
                }
1942

1943
                r = wait_for_terminate_and_check(inner_name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
172✔
1944
                if (r < 0)
86✔
UNCOV
1945
                        _exit(EXIT_FAILURE);
×
1946

1947
                _exit(r);
86✔
1948
        }
1949

1950
        return 1;
1951
}
1952

1953
int set_oom_score_adjust(int value) {
3,654✔
1954
        char t[DECIMAL_STR_MAX(int)];
3,654✔
1955

1956
        if (!oom_score_adjust_is_valid(value))
3,654✔
1957
                return -EINVAL;
3,654✔
1958

1959
        xsprintf(t, "%i", value);
3,654✔
1960

1961
        return write_string_file("/proc/self/oom_score_adj", t,
3,654✔
1962
                                 WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
1963
}
1964

1965
int get_oom_score_adjust(int *ret) {
2,384✔
1966
        _cleanup_free_ char *t = NULL;
2,384✔
1967
        int r, a;
2,384✔
1968

1969
        r = read_virtual_file("/proc/self/oom_score_adj", SIZE_MAX, &t, NULL);
2,384✔
1970
        if (r < 0)
2,384✔
1971
                return r;
1972

1973
        delete_trailing_chars(t, WHITESPACE);
2,384✔
1974

1975
        r = safe_atoi(t, &a);
2,384✔
1976
        if (r < 0)
2,384✔
1977
                return r;
1978

1979
        if (!oom_score_adjust_is_valid(a))
2,384✔
1980
                return -ENODATA;
1981

1982
        if (ret)
2,384✔
1983
                *ret = a;
2,384✔
1984

1985
        return 0;
1986
}
1987

1988
static int rlimit_to_nice(rlim_t limit) {
2✔
1989
        if (limit <= 1)
2✔
1990
                return PRIO_MAX-1; /* i.e. 19 */
1991

1992
        if (limit >= -PRIO_MIN + PRIO_MAX)
2✔
1993
                return PRIO_MIN; /* i.e. -20 */
1994

1995
        return PRIO_MAX - (int) limit;
2✔
1996
}
1997

1998
int setpriority_closest(int priority) {
25✔
1999
        struct rlimit highest;
25✔
2000
        int r, current, limit;
25✔
2001

2002
        /* Try to set requested nice level */
2003
        r = RET_NERRNO(setpriority(PRIO_PROCESS, 0, priority));
25✔
2004
        if (r >= 0)
2✔
2005
                return 1;
23✔
2006
        if (!ERRNO_IS_NEG_PRIVILEGE(r))
2✔
2007
                return r;
2008

2009
        errno = 0;
2✔
2010
        current = getpriority(PRIO_PROCESS, 0);
2✔
2011
        if (errno != 0)
2✔
UNCOV
2012
                return -errno;
×
2013

2014
        if (priority == current)
2✔
2015
                return 1;
2016

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

2023
        if (getrlimit(RLIMIT_NICE, &highest) < 0)
2✔
UNCOV
2024
                return -errno;
×
2025

2026
        limit = rlimit_to_nice(highest.rlim_cur);
2✔
2027

2028
        /* Push to the allowed limit if we're higher than that. Note that we could also be less nice than
2029
         * limit allows us, but still higher than what's requested. In that case our current value is
2030
         * the best choice. */
2031
        if (current > limit)
2✔
2032
                if (setpriority(PRIO_PROCESS, 0, limit) < 0)
2✔
UNCOV
2033
                        return -errno;
×
2034

2035
        log_debug("Cannot set requested nice level (%i), using next best (%i).", priority, MIN(current, limit));
2✔
2036
        return 0;
2037
}
2038

UNCOV
2039
_noreturn_ void freeze(void) {
×
UNCOV
2040
        log_close();
×
2041

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

2047
        /* Let's not freeze right away, but keep reaping zombies. */
UNCOV
2048
        for (;;) {
×
2049
                siginfo_t si = {};
×
2050

UNCOV
2051
                if (waitid(P_ALL, 0, &si, WEXITED) < 0 && errno != EINTR)
×
2052
                        break;
2053
        }
2054

2055
        /* waitid() failed with an ECHLD error (because there are no left-over child processes) or any other
2056
         * (unexpected) error. Freeze for good now! */
UNCOV
2057
        for (;;)
×
UNCOV
2058
                pause();
×
2059
}
2060

2061
int get_process_threads(pid_t pid) {
7✔
2062
        _cleanup_free_ char *t = NULL;
7✔
2063
        int n, r;
7✔
2064

2065
        if (pid < 0)
7✔
2066
                return -EINVAL;
2067

2068
        r = procfs_file_get_field(pid, "status", "Threads", &t);
7✔
2069
        if (r == -ENOENT)
7✔
2070
                return -ESRCH;
2071
        if (r < 0)
7✔
2072
                return r;
2073

2074
        r = safe_atoi(t, &n);
7✔
2075
        if (r < 0)
7✔
2076
                return r;
2077
        if (n < 0)
7✔
UNCOV
2078
                return -EINVAL;
×
2079

2080
        return n;
2081
}
2082

2083
int is_reaper_process(void) {
3,625✔
2084
        int b = 0;
3,625✔
2085

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

2089
        if (getpid_cached() == 1)
3,625✔
2090
                return true;
3,625✔
2091

2092
        if (prctl(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0UL, 0UL, 0UL) < 0)
351✔
UNCOV
2093
                return -errno;
×
2094

2095
        return b != 0;
351✔
2096
}
2097

2098
int make_reaper_process(bool b) {
666✔
2099

2100
        if (getpid_cached() == 1) {
666✔
2101

2102
                if (!b)
52✔
2103
                        return -EINVAL;
2104

2105
                return 0;
52✔
2106
        }
2107

2108
        /* Some prctl()s insist that all 5 arguments are specified, others do not. Let's always specify all,
2109
         * to avoid any ambiguities */
2110
        if (prctl(PR_SET_CHILD_SUBREAPER, (unsigned long) b, 0UL, 0UL, 0UL) < 0)
614✔
UNCOV
2111
                return -errno;
×
2112

2113
        return 0;
2114
}
2115

UNCOV
2116
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(posix_spawnattr_t*, posix_spawnattr_destroy, NULL);
×
2117

2118
int posix_spawn_wrapper(
2,429✔
2119
                const char *path,
2120
                char * const *argv,
2121
                char * const *envp,
2122
                const char *cgroup,
2123
                PidRef *ret_pidref) {
2124

2125
        short flags = POSIX_SPAWN_SETSIGMASK;
2,429✔
2126
        posix_spawnattr_t attr;
2,429✔
2127
        sigset_t mask;
2,429✔
2128
        int r;
2,429✔
2129

2130
        /* Forks and invokes 'path' with 'argv' and 'envp' using CLONE_VM and CLONE_VFORK, which means the
2131
         * caller will be blocked until the child either exits or exec's. The memory of the child will be
2132
         * fully shared with the memory of the parent, so that there are no copy-on-write or memory.max
2133
         * issues.
2134
         *
2135
         * Also, move the newly-created process into 'cgroup' through POSIX_SPAWN_SETCGROUP (clone3())
2136
         * if available.
2137
         * returns 1: We're already in the right cgroup
2138
         *         0: 'cgroup' not specified or POSIX_SPAWN_SETCGROUP is not supported. The caller
2139
         *            needs to call 'cg_attach' on their own */
2140

2141
        assert(path);
2,429✔
2142
        assert(argv);
2,429✔
2143
        assert(ret_pidref);
2,429✔
2144

2145
        assert_se(sigfillset(&mask) >= 0);
2,429✔
2146

2147
        r = posix_spawnattr_init(&attr);
2,429✔
2148
        if (r != 0)
2,429✔
2149
                return -r; /* These functions return a positive errno on failure */
2,429✔
2150

2151
        /* Initialization needs to succeed before we can set up a destructor. */
2152
        _unused_ _cleanup_(posix_spawnattr_destroyp) posix_spawnattr_t *attr_destructor = &attr;
4,858✔
2153

2154
#if HAVE_PIDFD_SPAWN
2155
        static bool have_clone_into_cgroup = true; /* kernel 5.7+ */
2,429✔
2156
        _cleanup_close_ int cgroup_fd = -EBADF;
2,429✔
2157

2158
        if (cgroup && have_clone_into_cgroup) {
2,429✔
2159
                _cleanup_free_ char *resolved_cgroup = NULL;
2,429✔
2160

2161
                r = cg_get_path(cgroup, /* suffix= */ NULL, &resolved_cgroup);
2,429✔
2162
                if (r < 0)
2,429✔
2163
                        return r;
2164

2165
                cgroup_fd = open(resolved_cgroup, O_PATH|O_DIRECTORY|O_CLOEXEC);
2,429✔
2166
                if (cgroup_fd < 0)
2,429✔
UNCOV
2167
                        return -errno;
×
2168

2169
                r = posix_spawnattr_setcgroup_np(&attr, cgroup_fd);
2,429✔
2170
                if (r != 0)
2,429✔
UNCOV
2171
                        return -r;
×
2172

2173
                flags |= POSIX_SPAWN_SETCGROUP;
2,429✔
2174
        }
2175
#endif
2176

2177
        r = posix_spawnattr_setflags(&attr, flags);
2,429✔
2178
        if (r != 0)
2,429✔
UNCOV
2179
                return -r;
×
2180
        r = posix_spawnattr_setsigmask(&attr, &mask);
2,429✔
2181
        if (r != 0)
2,429✔
UNCOV
2182
                return -r;
×
2183

2184
#if HAVE_PIDFD_SPAWN
2185
        _cleanup_close_ int pidfd = -EBADF;
2,429✔
2186

2187
        r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
2,429✔
2188
        if (ERRNO_IS_NOT_SUPPORTED(r) && FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP) && cg_is_threaded(cgroup) > 0)
2,429✔
2189
                return -EUCLEAN; /* clone3() could also return EOPNOTSUPP if the target cgroup is in threaded mode,
2190
                                    turn that into something recognizable */
2191
        if ((ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || r == E2BIG) &&
2,429✔
2192
            FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP)) {
2193
                /* Compiled on a newer host, or seccomp&friends blocking clone3()? Fallback, but
2194
                 * need to disable POSIX_SPAWN_SETCGROUP, which is what redirects to clone3().
2195
                 * Note that we might get E2BIG here since some kernels (e.g. 5.4) support clone3()
2196
                 * but not CLONE_INTO_CGROUP. */
2197

2198
                /* CLONE_INTO_CGROUP definitely won't work, hence remember the fact so that we don't
2199
                 * retry every time. */
2200
                have_clone_into_cgroup = false;
×
2201

2202
                flags &= ~POSIX_SPAWN_SETCGROUP;
×
2203
                r = posix_spawnattr_setflags(&attr, flags);
×
UNCOV
2204
                if (r != 0)
×
2205
                        return -r;
×
2206

UNCOV
2207
                r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
×
2208
        }
2209
        if (r != 0)
2,429✔
UNCOV
2210
                return -r;
×
2211

2212
        r = pidref_set_pidfd_consume(ret_pidref, TAKE_FD(pidfd));
2,429✔
2213
        if (r < 0)
2,429✔
2214
                return r;
2215

2216
        return FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP);
2,429✔
2217
#else
2218
        pid_t pid;
2219

2220
        r = posix_spawn(&pid, path, NULL, &attr, argv, envp);
2221
        if (r != 0)
2222
                return -r;
2223

2224
        r = pidref_set_pid(ret_pidref, pid);
2225
        if (r < 0)
2226
                return r;
2227

2228
        return 0; /* We did not use CLONE_INTO_CGROUP so return 0, the caller will have to move the child */
2229
#endif
2230
}
2231

2232
int proc_dir_open(DIR **ret) {
13✔
2233
        DIR *d;
13✔
2234

2235
        assert(ret);
13✔
2236

2237
        d = opendir("/proc");
13✔
2238
        if (!d)
13✔
UNCOV
2239
                return -errno;
×
2240

2241
        *ret = d;
13✔
2242
        return 0;
13✔
2243
}
2244

2245
int proc_dir_read(DIR *d, pid_t *ret) {
1,167✔
2246
        assert(d);
1,167✔
2247

2248
        for (;;) {
1,951✔
2249
                struct dirent *de;
1,951✔
2250

2251
                errno = 0;
1,951✔
2252
                de = readdir_no_dot(d);
1,951✔
2253
                if (!de) {
1,951✔
2254
                        if (errno != 0)
13✔
UNCOV
2255
                                return -errno;
×
2256

2257
                        break;
13✔
2258
                }
2259

2260
                if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
1,938✔
2261
                        continue;
641✔
2262

2263
                if (parse_pid(de->d_name, ret) >= 0)
1,297✔
2264
                        return 1;
2265
        }
2266

2267
        if (ret)
13✔
2268
                *ret = 0;
13✔
2269
        return 0;
2270
}
2271

2272
int proc_dir_read_pidref(DIR *d, PidRef *ret) {
1,124✔
2273
        int r;
1,124✔
2274

2275
        assert(d);
1,124✔
2276

2277
        for (;;) {
1,124✔
2278
                pid_t pid;
1,124✔
2279

2280
                r = proc_dir_read(d, &pid);
1,124✔
2281
                if (r < 0)
1,124✔
2282
                        return r;
1,112✔
2283
                if (r == 0)
1,124✔
2284
                        break;
2285

2286
                r = pidref_set_pid(ret, pid);
1,112✔
2287
                if (r == -ESRCH) /* gone by now? skip it */
1,112✔
2288
                        continue;
×
2289
                if (r < 0)
1,112✔
UNCOV
2290
                        return r;
×
2291

2292
                return 1;
2293
        }
2294

2295
        if (ret)
12✔
2296
                *ret = PIDREF_NULL;
12✔
2297
        return 0;
2298
}
2299

2300
static const char *const sigchld_code_table[] = {
2301
        [CLD_EXITED] = "exited",
2302
        [CLD_KILLED] = "killed",
2303
        [CLD_DUMPED] = "dumped",
2304
        [CLD_TRAPPED] = "trapped",
2305
        [CLD_STOPPED] = "stopped",
2306
        [CLD_CONTINUED] = "continued",
2307
};
2308

2309
DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
8,839✔
2310

2311
static const char* const sched_policy_table[] = {
2312
        [SCHED_OTHER] = "other",
2313
        [SCHED_BATCH] = "batch",
2314
        [SCHED_IDLE] = "idle",
2315
        [SCHED_FIFO] = "fifo",
2316
        [SCHED_RR] = "rr",
2317
};
2318

2319
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
52✔
2320

2321
_noreturn_ void report_errno_and_exit(int errno_fd, int error) {
64✔
2322
        int r;
64✔
2323

2324
        if (error >= 0)
64✔
2325
                _exit(EXIT_SUCCESS);
63✔
2326

2327
        assert(errno_fd >= 0);
1✔
2328

2329
        r = loop_write(errno_fd, &error, sizeof(error));
1✔
2330
        if (r < 0)
1✔
UNCOV
2331
                log_debug_errno(r, "Failed to write errno to errno_fd=%d: %m", errno_fd);
×
2332

2333
        _exit(EXIT_FAILURE);
1✔
2334
}
2335

2336
int read_errno(int errno_fd) {
3✔
2337
        int r;
3✔
2338

2339
        assert(errno_fd >= 0);
3✔
2340

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

2344
        ssize_t n = loop_read(errno_fd, &r, sizeof(r), /* do_poll= */ false);
3✔
2345
        if (n < 0) {
3✔
UNCOV
2346
                log_debug_errno(n, "Failed to read errno: %m");
×
UNCOV
2347
                return -EIO;
×
2348
        }
2349
        if (n == sizeof(r)) {
3✔
2350
                if (r == 0)
×
2351
                        return 0;
2352
                if (r < 0) /* child process reported an error, return it */
×
UNCOV
2353
                        return log_debug_errno(r, "Child process failed with errno: %m");
×
UNCOV
2354
                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received an errno, but it's a positive value.");
×
2355
        }
2356
        if (n != 0)
3✔
UNCOV
2357
                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received unexpected amount of bytes while reading errno.");
×
2358

2359
        /* the process exited without reporting an error, assuming success */
2360
        return 0;
2361
}
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