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

systemd / systemd / 26856653518

02 Jun 2026 04:05PM UTC coverage: 72.884% (-0.1%) from 72.979%
26856653518

push

github

web-flow
Add DLOPEN macros that stamp the caller's ELF and use it to ensure executables list their dlopen dependencies (#42398)

Currently almost all the dlopens happen in libbasic or libshared code,
so the ELF dlopen notes all end up in libsystemd-shared. Many
distributions split this library and various binaries in separate
packages, and the library ends up with soft-dependencies, even though
many binaries are either completely useless or do not work at all with
the dlopen dependency. This also makes it impossible to know which
executable uses which dlopen dependency without inspecting the source
code.

If someone only wants to add the soft dependencies from libshared they
can just avoid parsing the executable binaries. By design the code in
libbasic/libshared still does the stamping too, at lower priorities, so
that libsystemd-shared will always list all the optional dependencies,
and if one wants to build a minimal system by default, they can just
parse libsystemd-shared dlopen notes, and ignore the individual
executables. But for many distribution the current setup is insufficient
and requires adding a ton of manual library dependencies, as many
executables become effectively broken or useless without the dlopen
dependencies installed (eg: resolved fails to start without libssl,
repart can do basically nothing without blkid, etc).

Add a new set of DLOPEN_<LIB> macros that wrap the dlopen_lib and also
pull in the ELF note voodoo, so that the callers get their ELF binaries
stamped too. Convert a bunch of callers to use the macro, and use
`required` dependencies for the callers that do not work without the
dlopen library being available.

The one caveat is that, in order to avoid duplicating the exact same
note in a binary due to multiple call sites, some `asm` voodoo is done
instead of the previous bare-C section-creating macro. The drawback of
this approach is that if `--gc-sections` is used to link the binary (as
we do), then binutils >= 2.36 is required... (continued)

112 of 145 new or added lines in 78 files covered. (77.24%)

1126 existing lines in 53 files now uncovered.

336961 of 462328 relevant lines covered (72.88%)

1288046.12 hits per line

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

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

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

19
#include "sd-messages.h"
20

21
#include "alloc-util.h"
22
#include "architecture.h"
23
#include "argv-util.h"
24
#include "capability-util.h"
25
#include "cgroup-util.h"
26
#include "dirent-util.h"
27
#include "dlfcn-util.h"
28
#include "errno-util.h"
29
#include "escape.h"
30
#include "fd-util.h"
31
#include "fileio.h"
32
#include "fs-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 "strv.h"
55
#include "time-util.h"
56
#include "user-util.h"
57

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

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

69
        assert(pid >= 0);
15,027✔
70

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

75
        p = procfs_file_alloca(pid, "stat");
15,027✔
76

77
        r = read_one_line_file(p, &line);
15,027✔
78
        if (r == -ENOENT)
15,027✔
79
                return -ESRCH;
80
        if (r < 0)
11,720✔
81
                return r;
82

83
        p = strrchr(line, ')');
11,718✔
84
        if (!p)
11,718✔
85
                return -EIO;
86

87
        p++;
11,718✔
88

89
        if (sscanf(p, " %c", &state) != 1)
11,718✔
90
                return -EIO;
91

92
        return (unsigned char) state;
11,718✔
93
}
94

95
int pid_get_comm(pid_t pid, char **ret) {
57,352✔
96
        _cleanup_free_ char *escaped = NULL, *comm = NULL;
57,352✔
97
        int r;
57,352✔
98

99
        assert(pid >= 0);
57,352✔
100
        assert(ret);
57,352✔
101

102
        if (pid == 0 || pid == getpid_cached()) {
57,352✔
103
                comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */
27,476✔
104
                if (!comm)
27,476✔
105
                        return -ENOMEM;
106

107
                if (prctl(PR_GET_NAME, comm) < 0)
27,476✔
108
                        return -errno;
×
109
        } else {
110
                const char *p;
29,876✔
111

112
                p = procfs_file_alloca(pid, "comm");
29,876✔
113

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

122
        escaped = new(char, COMM_MAX_LEN);
53,783✔
123
        if (!escaped)
53,783✔
124
                return -ENOMEM;
125

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

129
        *ret = TAKE_PTR(escaped);
53,783✔
130
        return 0;
53,783✔
131
}
132

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

137
        if (!pidref_is_set(pid))
328✔
138
                return -ESRCH;
139

140
        if (pidref_is_remote(pid))
656✔
141
                return -EREMOTE;
142

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

147
        r = pidref_verify(pid);
328✔
148
        if (r < 0)
328✔
149
                return r;
150

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

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

163
        _cleanup_free_ char *t = NULL;
21,664✔
164
        const char *p;
21,664✔
165
        size_t k;
21,664✔
166
        int r;
21,664✔
167

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

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

187
        if (k == 0) {
18,009✔
188
                if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
507✔
189
                        return -ENOENT;
488✔
190

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

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

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

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

209
        if (ret)
17,521✔
210
                *ret = TAKE_PTR(t);
17,521✔
211
        if (ret_size)
17,521✔
212
                *ret_size = k;
17,521✔
213

214
        return r;
215
}
216

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

222
        assert(pid >= 0);
16,400✔
223
        assert(ret);
16,400✔
224

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

239
        int full = pid_get_cmdline_nulstr(pid, max_columns, flags, &t, &k);
16,400✔
240
        if (full < 0)
16,400✔
241
                return full;
242

243
        if (flags & (PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_QUOTE_POSIX)) {
12,332✔
244
                ShellEscapeFlags shflags = SHELL_ESCAPE_EMPTY |
11,990✔
245
                        FLAGS_SET(flags, PROCESS_CMDLINE_QUOTE_POSIX) * SHELL_ESCAPE_POSIX;
11,990✔
246

247
                assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
11,990✔
248

249
                _cleanup_strv_free_ char **args = NULL;
11,990✔
250

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

257
                ans = quote_command_line(args, shflags);
11,990✔
258
                if (!ans)
11,990✔
259
                        return -ENOMEM;
260
        } else {
261
                /* Arguments are separated by NULs. Let's replace those with spaces. */
262
                for (size_t i = 0; i < k - 1; i++)
15,896✔
263
                        if (t[i] == '\0')
15,554✔
264
                                t[i] = ' ';
532✔
265

266
                delete_trailing_chars(t, WHITESPACE);
342✔
267

268
                bool eight_bit = (flags & PROCESS_CMDLINE_USE_LOCALE) && !is_locale_utf8();
342✔
269

270
                ans = escape_non_printable_full(t, max_columns,
1,026✔
271
                                                eight_bit * XESCAPE_8_BIT | !full * XESCAPE_FORCE_ELLIPSIS);
636✔
272
                if (!ans)
342✔
273
                        return -ENOMEM;
274

275
                ans = str_realloc(ans);
342✔
276
        }
277

278
        *ret = ans;
12,332✔
279
        return 0;
12,332✔
280
}
281

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

286
        if (!pidref_is_set(pid))
43✔
287
                return -ESRCH;
288

289
        if (pidref_is_remote(pid))
86✔
290
                return -EREMOTE;
291

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

296
        r = pidref_verify(pid);
43✔
297
        if (r < 0)
43✔
298
                return r;
299

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

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

311
        assert(pid >= 0);
5,264✔
312
        assert((flags & ~PROCESS_CMDLINE_COMM_FALLBACK) == 0);
5,264✔
313
        assert(ret);
5,264✔
314

315
        r = pid_get_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k);
5,264✔
316
        if (r < 0)
5,264✔
317
                return r;
318

319
        args = strv_parse_nulstr_full(t, k, /* drop_trailing_nuls= */ true);
5,189✔
320
        if (!args)
5,189✔
321
                return -ENOMEM;
322

323
        *ret = args;
5,189✔
324
        return 0;
5,189✔
325
}
326

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

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

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

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

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

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

348
        return 0;
349
}
350

351
int pid_is_kernel_thread(pid_t pid) {
4,544✔
352
        int r;
4,544✔
353

354
        if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
4,544✔
355
                return 0;
4,544✔
356
        if (!pid_is_valid(pid))
4,519✔
357
                return -EINVAL;
358

359
        const char *p = procfs_file_alloca(pid, "stat");
4,519✔
360
        _cleanup_free_ char *line = NULL;
4,519✔
361
        r = read_one_line_file(p, &line);
4,519✔
362
        if (r == -ENOENT)
4,519✔
363
                return -ESRCH;
364
        if (r < 0)
4,519✔
365
                return r;
366

367
        /* Skip past the comm field */
368
        char *q = strrchr(line, ')');
4,519✔
369
        if (!q)
4,519✔
370
                return -EINVAL;
371
        q++;
4,519✔
372

373
        /* Skip 6 fields to reach the flags field */
374
        for (size_t i = 0; i < 6; i++) {
31,633✔
375
                size_t l = strspn(q, WHITESPACE);
27,114✔
376
                if (l < 1)
27,114✔
377
                        return -EINVAL;
378
                q += l;
27,114✔
379

380
                l = strcspn(q, WHITESPACE);
27,114✔
381
                if (l < 1)
27,114✔
382
                        return -EINVAL;
383
                q += l;
27,114✔
384
        }
385

386
        /* Skip preceding whitespace */
387
        size_t l = strspn(q, WHITESPACE);
4,519✔
388
        if (l < 1)
4,519✔
389
                return -EINVAL;
390
        q += l;
4,519✔
391

392
        /* Truncate the rest */
393
        l = strcspn(q, WHITESPACE);
4,519✔
394
        if (l < 1)
4,519✔
395
                return -EINVAL;
396
        q[l] = 0;
4,519✔
397

398
        unsigned long long flags;
4,519✔
399
        r = safe_atollu(q, &flags);
4,519✔
400
        if (r < 0)
4,519✔
401
                return r;
402

403
        return !!(flags & PF_KTHREAD);
4,519✔
404
}
405

406
int pidref_is_kernel_thread(const PidRef *pid) {
1,922✔
407
        int result, r;
1,922✔
408

409
        if (!pidref_is_set(pid))
1,922✔
410
                return -ESRCH;
411

412
        if (pidref_is_remote(pid))
1,922✔
413
                return -EREMOTE;
414

415
        result = pid_is_kernel_thread(pid->pid);
1,922✔
416
        if (result < 0)
1,922✔
417
                return result;
418

419
        r = pidref_verify(pid); /* Verify that the PID wasn't reused since */
1,922✔
420
        if (r < 0)
1,922✔
UNCOV
421
                return r;
×
422

423
        return result;
424
}
425

426
static int get_process_link_contents(pid_t pid, const char *proc_file, char **ret) {
15,886✔
427
        const char *p;
15,886✔
428
        int r;
15,886✔
429

430
        assert(proc_file);
15,886✔
431

432
        p = procfs_file_alloca(pid, proc_file);
15,890✔
433

434
        r = readlink_malloc(p, ret);
15,886✔
435
        return (r == -ENOENT && proc_mounted() > 0) ? -ESRCH : r;
15,886✔
436
}
437

438
int get_process_exe(pid_t pid, char **ret) {
15,860✔
439
        char *d;
15,860✔
440
        int r;
15,860✔
441

442
        assert(pid >= 0);
15,860✔
443

444
        r = get_process_link_contents(pid, "exe", ret);
15,860✔
445
        if (r < 0)
15,860✔
446
                return r;
447

448
        if (ret) {
12,015✔
449
                d = endswith(*ret, " (deleted)");
12,015✔
450
                if (d)
12,015✔
451
                        *d = '\0';
×
452
        }
453

454
        return 0;
455
}
456

457
int pid_get_uid(pid_t pid, uid_t *ret) {
3,184✔
458
        int r;
3,184✔
459

460
        assert(pid >= 0);
3,184✔
461
        assert(ret);
3,184✔
462

463
        if (pid == 0 || pid == getpid_cached()) {
3,184✔
464
                *ret = getuid();
1✔
465
                return 0;
3,184✔
466
        }
467

468
        _cleanup_free_ char *v = NULL;
3,183✔
469
        r = procfs_file_get_field(pid, "status", "Uid", &v);
3,183✔
470
        if (r == -ENOENT)
3,183✔
471
                return -ESRCH;
472
        if (r < 0)
183✔
473
                return r;
474

475
        return parse_uid(v, ret);
183✔
476
}
477

478
int pidref_get_uid(const PidRef *pid, uid_t *ret) {
117✔
479
        int r;
117✔
480

481
        if (!pidref_is_set(pid))
117✔
482
                return -ESRCH;
117✔
483

484
        if (pidref_is_remote(pid))
117✔
485
                return -EREMOTE;
486

487
        if (pid->fd >= 0) {
117✔
488
                r = pidfd_get_uid(pid->fd, ret);
117✔
489
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
117✔
490
                        return r;
491
        }
492

493
        uid_t uid;
×
494
        r = pid_get_uid(pid->pid, &uid);
×
495
        if (r < 0)
×
496
                return r;
497

498
        r = pidref_verify(pid);
×
499
        if (r < 0)
×
500
                return r;
501

502
        if (ret)
×
503
                *ret = uid;
×
504
        return 0;
505
}
506

507
int get_process_gid(pid_t pid, gid_t *ret) {
3,184✔
508
        int r;
3,184✔
509

510
        assert(pid >= 0);
3,184✔
511
        assert(ret);
3,184✔
512

513
        if (pid == 0 || pid == getpid_cached()) {
3,184✔
514
                *ret = getgid();
1✔
515
                return 0;
3,184✔
516
        }
517

518
        _cleanup_free_ char *v = NULL;
3,183✔
519
        r = procfs_file_get_field(pid, "status", "Gid", &v);
3,183✔
520
        if (r == -ENOENT)
3,183✔
521
                return -ESRCH;
522
        if (r < 0)
183✔
523
                return r;
524

525
        return parse_gid(v, ret);
3,183✔
526
}
527

528
int get_process_cwd(pid_t pid, char **ret) {
13✔
529
        assert(pid >= 0);
13✔
530

531
        if (pid == 0 || pid == getpid_cached())
13✔
532
                return safe_getcwd(ret);
×
533

534
        return get_process_link_contents(pid, "cwd", ret);
13✔
535
}
536

537
int get_process_root(pid_t pid, char **ret) {
13✔
538
        assert(pid >= 0);
13✔
539
        return get_process_link_contents(pid, "root", ret);
13✔
540
}
541

542
#define ENVIRONMENT_BLOCK_MAX (5U*1024U*1024U)
543

544
int get_process_environ(pid_t pid, char **ret) {
15✔
545
        _cleanup_fclose_ FILE *f = NULL;
15✔
546
        _cleanup_free_ char *outcome = NULL;
15✔
547
        size_t sz = 0;
15✔
548
        const char *p;
15✔
549
        int r;
15✔
550

551
        assert(pid >= 0);
15✔
552
        assert(ret);
15✔
553

554
        p = procfs_file_alloca(pid, "environ");
15✔
555

556
        r = fopen_unlocked(p, "re", &f);
15✔
557
        if (r == -ENOENT)
15✔
558
                return -ESRCH;
559
        if (r < 0)
15✔
560
                return r;
561

562
        for (;;) {
6,606✔
563
                char c;
6,621✔
564

565
                if (sz >= ENVIRONMENT_BLOCK_MAX)
6,621✔
566
                        return -ENOBUFS;
×
567

568
                if (!GREEDY_REALLOC(outcome, sz + 5))
6,621✔
569
                        return -ENOMEM;
570

571
                r = safe_fgetc(f, &c);
6,621✔
572
                if (r < 0)
6,621✔
573
                        return r;
574
                if (r == 0)
6,621✔
575
                        break;
576

577
                if (c == '\0')
6,606✔
578
                        outcome[sz++] = '\n';
236✔
579
                else
580
                        sz += cescape_char(c, outcome + sz);
6,370✔
581
        }
582

583
        outcome[sz] = '\0';
15✔
584
        *ret = TAKE_PTR(outcome);
15✔
585

586
        return 0;
15✔
587
}
588

589
int pid_get_ppid(pid_t pid, pid_t *ret) {
6✔
590
        _cleanup_free_ char *line = NULL;
6✔
591
        unsigned long ppid;
6✔
592
        const char *p;
6✔
593
        int r;
6✔
594

595
        assert(pid >= 0);
6✔
596

597
        if (pid == 0)
6✔
598
                pid = getpid_cached();
1✔
599
        if (pid == 1) /* PID 1 has no parent, shortcut this case */
6✔
600
                return -EADDRNOTAVAIL;
601

602
        if (pid == getpid_cached()) {
3✔
603
                if (ret)
2✔
604
                        *ret = getppid();
2✔
605
                return 0;
606
        }
607

608
        p = procfs_file_alloca(pid, "stat");
1✔
609
        r = read_one_line_file(p, &line);
1✔
610
        if (r == -ENOENT)
1✔
611
                return -ESRCH;
612
        if (r < 0)
×
613
                return r;
614

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

618
        p = strrchr(line, ')');
×
619
        if (!p)
×
620
                return -EIO;
621
        p++;
×
622

623
        if (sscanf(p, " "
×
624
                   "%*c "  /* state */
625
                   "%lu ", /* ppid */
626
                   &ppid) != 1)
627
                return -EIO;
628

629
        /* If ppid is zero the process has no parent. Which might be the case for PID 1 (caught above)
630
         * but also for processes originating in other namespaces that are inserted into a pidns.
631
         * Return a recognizable error in this case. */
632
        if (ppid == 0)
×
633
                return -EADDRNOTAVAIL;
634

635
        if ((pid_t) ppid < 0 || (unsigned long) (pid_t) ppid != ppid)
×
636
                return -ERANGE;
637

638
        if (ret)
×
639
                *ret = (pid_t) ppid;
×
640

641
        return 0;
642
}
643

644
int pidref_get_ppid(const PidRef *pidref, pid_t *ret) {
5,985✔
645
        int r;
5,985✔
646

647
        if (!pidref_is_set(pidref))
5,985✔
648
                return -ESRCH;
5,985✔
649

650
        if (pidref_is_remote(pidref))
5,985✔
651
                return -EREMOTE;
652

653
        if (pidref->fd >= 0) {
5,985✔
654
                r = pidfd_get_ppid(pidref->fd, ret);
5,985✔
655
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
5,985✔
656
                        return r;
657
        }
658

659
        pid_t ppid;
×
660
        r = pid_get_ppid(pidref->pid, ret ? &ppid : NULL);
×
661
        if (r < 0)
×
662
                return r;
663

664
        r = pidref_verify(pidref);
×
665
        if (r < 0)
×
666
                return r;
667

668
        if (ret)
×
669
                *ret = ppid;
×
670
        return 0;
671
}
672

673
int pidref_get_ppid_as_pidref(const PidRef *pidref, PidRef *ret) {
11✔
674
        pid_t ppid;
11✔
675
        int r;
11✔
676

677
        assert(ret);
11✔
678

679
        r = pidref_get_ppid(pidref, &ppid);
11✔
680
        if (r < 0)
11✔
681
                return r;
11✔
682

683
        for (unsigned attempt = 0; attempt < 16; attempt++) {
10✔
684
                _cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
10✔
685

686
                r = pidref_set_pid(&parent, ppid);
10✔
687
                if (r < 0)
10✔
688
                        return r;
689

690
                /* If we have a pidfd of the original PID, let's verify that the process we acquired really
691
                 * is the parent still */
692
                if (pidref->fd >= 0) {
10✔
693
                        r = pidref_get_ppid(pidref, &ppid);
10✔
694
                        if (r < 0)
10✔
695
                                return r;
696

697
                        /* Did the PPID change since we queried it? if so we might have pinned the wrong
698
                         * process, if its PID got reused by now. Let's try again */
699
                        if (parent.pid != ppid)
10✔
700
                                continue;
×
701
                }
702

703
                *ret = TAKE_PIDREF(parent);
10✔
704
                return 0;
10✔
705
        }
706

707
        /* Give up after 16 tries */
708
        return -ENOTRECOVERABLE;
709
}
710

711
int pid_get_start_time(pid_t pid, usec_t *ret) {
2,820✔
712
        _cleanup_free_ char *line = NULL;
2,820✔
713
        const char *p;
2,820✔
714
        int r;
2,820✔
715

716
        assert(pid >= 0);
2,820✔
717

718
        p = procfs_file_alloca(pid, "stat");
2,820✔
719
        r = read_one_line_file(p, &line);
2,820✔
720
        if (r == -ENOENT)
2,820✔
721
                return -ESRCH;
722
        if (r < 0)
2,820✔
723
                return r;
724

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

728
        p = strrchr(line, ')');
2,820✔
729
        if (!p)
2,820✔
730
                return -EIO;
731
        p++;
2,820✔
732

733
        unsigned long llu;
2,820✔
734

735
        if (sscanf(p, " "
2,820✔
736
                   "%*c " /* state */
737
                   "%*u " /* ppid */
738
                   "%*u " /* pgrp */
739
                   "%*u " /* session */
740
                   "%*u " /* tty_nr */
741
                   "%*u " /* tpgid */
742
                   "%*u " /* flags */
743
                   "%*u " /* minflt */
744
                   "%*u " /* cminflt */
745
                   "%*u " /* majflt */
746
                   "%*u " /* cmajflt */
747
                   "%*u " /* utime */
748
                   "%*u " /* stime */
749
                   "%*u " /* cutime */
750
                   "%*u " /* cstime */
751
                   "%*i " /* priority */
752
                   "%*i " /* nice */
753
                   "%*u " /* num_threads */
754
                   "%*u " /* itrealvalue */
755
                   "%lu ", /* starttime */
756
                   &llu) != 1)
757
                return -EIO;
758

759
        if (ret)
2,820✔
760
                *ret = jiffies_to_usec(llu); /* CLOCK_BOOTTIME */
2,820✔
761

762
        return 0;
763
}
764

765
int pidref_get_start_time(const PidRef *pid, usec_t *ret) {
2,820✔
766
        usec_t t;
2,820✔
767
        int r;
2,820✔
768

769
        if (!pidref_is_set(pid))
2,820✔
770
                return -ESRCH;
2,820✔
771

772
        if (pidref_is_remote(pid))
2,820✔
773
                return -EREMOTE;
774

775
        r = pid_get_start_time(pid->pid, ret ? &t : NULL);
2,820✔
776
        if (r < 0)
2,820✔
777
                return r;
778

779
        r = pidref_verify(pid);
2,820✔
780
        if (r < 0)
2,820✔
781
                return r;
782

783
        if (ret)
2,820✔
784
                *ret = t;
2,820✔
785

786
        return 0;
787
}
788

789
int get_process_umask(pid_t pid, mode_t *ret) {
28,789✔
790
        _cleanup_free_ char *m = NULL;
28,789✔
791
        int r;
28,789✔
792

793
        assert(pid >= 0);
28,789✔
794
        assert(ret);
28,789✔
795

796
        r = procfs_file_get_field(pid, "status", "Umask", &m);
28,789✔
797
        if (r == -ENOENT)
28,789✔
798
                return -ESRCH;
799
        if (r < 0)
28,789✔
800
                return r;
801

802
        return parse_mode(m, ret);
28,789✔
803
}
804

805
/*
806
 * Return values:
807
 * < 0 : pidref_wait_for_terminate() failed to get the state of the
808
 *       process, the process was terminated by a signal, or
809
 *       failed for an unknown reason.
810
 * >=0 : The process terminated normally, and its exit code is
811
 *       returned.
812
 *
813
 * That is, success is indicated by a return value of zero, and an
814
 * error is indicated by a non-zero value.
815
 *
816
 * A warning is emitted if the process terminates abnormally,
817
 * and also if it returns non-zero unless check_exit_code is true.
818
 */
819
int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFlags flags) {
8,400✔
820
        int r;
8,400✔
821

822
        if (!pidref_is_set(pidref))
8,400✔
823
                return -ESRCH;
8,400✔
824
        if (pidref_is_remote(pidref))
16,800✔
825
                return -EREMOTE;
826
        if (pidref->pid == 1 || pidref_is_self(pidref))
8,400✔
827
                return -ECHILD;
828

829
        _cleanup_free_ char *buffer = NULL;
8,400✔
830
        if (!name) {
8,400✔
831
                r = pidref_get_comm(pidref, &buffer);
2✔
832
                if (r < 0)
2✔
833
                        log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pidref->pid);
×
834
                else
835
                        name = buffer;
2✔
836
        }
837

838
        int prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG;
8,400✔
839

840
        siginfo_t status;
8,400✔
841
        r = pidref_wait_for_terminate(pidref, &status);
8,400✔
842
        if (r < 0)
8,400✔
843
                return log_full_errno(prio, r, "Failed to wait for '%s': %m", strna(name));
×
844

845
        if (status.si_code == CLD_EXITED) {
8,400✔
846
                if (status.si_status != EXIT_SUCCESS)
8,400✔
847
                        log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
78✔
848
                                 "'%s' failed with exit status %i.", strna(name), status.si_status);
849
                else
850
                        log_debug("'%s' succeeded.", name);
8,322✔
851

852
                return status.si_status;
8,400✔
853

854
        } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED))
×
855
                return log_full_errno(prio, SYNTHETIC_ERRNO(EPROTO),
×
856
                                      "'%s' terminated by signal %s.", strna(name), signal_to_string(status.si_status));
857

858
        return log_full_errno(prio, SYNTHETIC_ERRNO(EPROTO),
×
859
                              "'%s' failed due to unknown reason.", strna(name));
860
}
861

862
int kill_and_sigcont(pid_t pid, int sig) {
×
863
        int r;
×
864

865
        r = RET_NERRNO(kill(pid, sig));
×
866

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

872
        return r;
×
873
}
874

875
int getenv_for_pid(pid_t pid, const char *field, char **ret) {
6,581✔
876
        _cleanup_fclose_ FILE *f = NULL;
6,581✔
877
        const char *path;
6,581✔
878
        size_t sum = 0;
6,581✔
879
        int r;
6,581✔
880

881
        assert(pid >= 0);
6,581✔
882
        assert(field);
6,581✔
883
        assert(ret);
6,581✔
884

885
        if (pid == 0 || pid == getpid_cached())
6,581✔
886
                return strdup_to_full(ret, getenv(field));
14✔
887

888
        if (!pid_is_valid(pid))
6,567✔
889
                return -EINVAL;
890

891
        path = procfs_file_alloca(pid, "environ");
6,567✔
892

893
        r = fopen_unlocked(path, "re", &f);
6,567✔
894
        if (r == -ENOENT)
6,567✔
895
                return -ESRCH;
896
        if (r < 0)
6,148✔
897
                return r;
898

899
        for (;;) {
80,553✔
900
                _cleanup_free_ char *line = NULL;
37,981✔
901
                const char *match;
42,590✔
902

903
                if (sum > ENVIRONMENT_BLOCK_MAX) /* Give up searching eventually */
42,590✔
904
                        return -ENOBUFS;
905

906
                r = read_nul_string(f, LONG_LINE_MAX, &line);
42,590✔
907
                if (r < 0)
42,590✔
908
                        return r;
909
                if (r == 0)  /* EOF */
42,590✔
910
                        break;
911

912
                sum += r;
37,981✔
913

914
                match = startswith(line, field);
37,981✔
915
                if (match && *match == '=')
37,981✔
916
                        return strdup_to_full(ret, match + 1);
18✔
917
        }
918

919
        *ret = NULL;
4,609✔
920
        return 0;
4,609✔
921
}
922

923
int pidref_is_my_child(PidRef *pid) {
5,963✔
924
        int r;
5,963✔
925

926
        if (!pidref_is_set(pid))
5,963✔
927
                return -ESRCH;
5,963✔
928

929
        if (pidref_is_remote(pid))
5,963✔
930
                return -EREMOTE;
931

932
        if (pid->pid == 1 || pidref_is_self(pid))
5,963✔
933
                return false;
934

935
        pid_t ppid;
5,963✔
936
        r = pidref_get_ppid(pid, &ppid);
5,963✔
937
        if (r == -EADDRNOTAVAIL) /* if this process is outside of our pidns, it is definitely not our child */
5,963✔
938
                return false;
939
        if (r < 0)
5,963✔
940
                return r;
941

942
        return ppid == getpid_cached();
5,963✔
943
}
944

945
int pid_is_my_child(pid_t pid) {
×
946

947
        if (pid == 0)
×
948
                return false;
×
949

950
        return pidref_is_my_child(&PIDREF_MAKE_FROM_PID(pid));
×
951
}
952

953
int pidref_is_unwaited(PidRef *pid) {
13,023✔
954
        int r;
13,023✔
955

956
        /* Checks whether a PID is still valid at all, including a zombie */
957

958
        if (!pidref_is_set(pid))
13,023✔
959
                return -ESRCH;
960

961
        if (pidref_is_remote(pid))
13,022✔
962
                return -EREMOTE;
963

964
        if (pid->pid == 1 || pidref_is_self(pid))
13,022✔
965
                return true;
966

967
        r = pidref_kill(pid, 0);
13,019✔
968
        if (r == -ESRCH)
13,019✔
969
                return false;
970
        if (r < 0)
5,307✔
971
                return r;
222✔
972

973
        return true;
974
}
975

976
int pid_is_unwaited(pid_t pid) {
9,612✔
977

978
        if (pid == 0)
9,612✔
979
                return true;
9,612✔
980

981
        return pidref_is_unwaited(&PIDREF_MAKE_FROM_PID(pid));
9,612✔
982
}
983

984
int pid_is_alive(pid_t pid) {
15,029✔
985
        int r;
15,029✔
986

987
        /* Checks whether a PID is still valid and not a zombie */
988

989
        if (pid < 0)
15,029✔
990
                return -ESRCH;
991

992
        if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
15,028✔
993
                return true;
994

995
        if (pid == getpid_cached())
15,028✔
996
                return true;
997

998
        r = get_process_state(pid);
15,027✔
999
        if (r == -ESRCH)
15,027✔
1000
                return false;
1001
        if (r < 0)
11,718✔
1002
                return r;
1003

1004
        return r != 'Z';
11,718✔
1005
}
1006

1007
int pidref_is_alive(const PidRef *pidref) {
15,026✔
1008
        int r, result;
15,026✔
1009

1010
        if (!pidref_is_set(pidref))
15,026✔
1011
                return -ESRCH;
1012

1013
        if (pidref_is_remote(pidref))
15,024✔
1014
                return -EREMOTE;
1015

1016
        result = pid_is_alive(pidref->pid);
15,024✔
1017
        if (result < 0) {
15,024✔
1018
                assert(result != -ESRCH);
×
1019
                return result;
1020
        }
1021

1022
        r = pidref_verify(pidref);
15,024✔
1023
        if (r == -ESRCH)
15,024✔
1024
                return false;
1025
        if (r < 0)
11,715✔
1026
                return r;
×
1027

1028
        return result;
1029
}
1030

1031
int pidref_from_same_root_fs(PidRef *a, PidRef *b) {
20✔
1032
        _cleanup_(pidref_done) PidRef self = PIDREF_NULL;
×
1033
        int r;
20✔
1034

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

1038
        if (!a || !b) {
20✔
1039
                r = pidref_set_self(&self);
×
1040
                if (r < 0)
×
1041
                        return r;
1042
                if (!a)
×
1043
                        a = &self;
×
1044
                if (!b)
×
1045
                        b = &self;
×
1046
        }
1047

1048
        if (!pidref_is_set(a) || !pidref_is_set(b))
20✔
1049
                return -ESRCH;
1050

1051
        /* If one of the two processes have the same root they cannot have the same root fs, but if both of
1052
         * them do we don't know */
1053
        if (pidref_is_remote(a) && pidref_is_remote(b))
20✔
1054
                return -EREMOTE;
1055
        if (pidref_is_remote(a) || pidref_is_remote(b))
60✔
1056
                return false;
1057

1058
        if (pidref_equal(a, b))
20✔
1059
                return true;
1060

1061
        const char *roota = procfs_file_alloca(a->pid, "root");
18✔
1062
        const char *rootb = procfs_file_alloca(b->pid, "root");
18✔
1063

1064
        int result = inode_same(roota, rootb, 0);
18✔
1065
        if (result == -ENOENT)
18✔
1066
                return proc_mounted() == 0 ? -ENOSYS : -ESRCH;
×
1067
        if (result < 0)
18✔
1068
                return result;
1069

1070
        r = pidref_verify(a);
18✔
1071
        if (r < 0)
18✔
1072
                return r;
1073
        r = pidref_verify(b);
18✔
1074
        if (r < 0)
18✔
1075
                return r;
×
1076

1077
        return result;
1078
}
1079

1080
bool is_main_thread(void) {
8,324,970✔
1081
        static thread_local int cached = -1;
8,324,970✔
1082

1083
        if (cached < 0)
8,324,970✔
1084
                cached = getpid_cached() == gettid();
65,914✔
1085

1086
        return cached;
8,324,970✔
1087
}
1088

1089
unsigned long personality_from_string(const char *s) {
9✔
1090
        Architecture architecture;
9✔
1091

1092
        if (!s)
9✔
1093
                return PERSONALITY_INVALID;
1094

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

1099
        architecture = architecture_from_string(s);
8✔
1100
        if (architecture < 0)
8✔
1101
                return PERSONALITY_INVALID;
1102

1103
        if (architecture == native_architecture())
6✔
1104
                return PER_LINUX;
1105
#ifdef ARCHITECTURE_SECONDARY
1106
        if (architecture == ARCHITECTURE_SECONDARY)
3✔
1107
                return PER_LINUX32;
2✔
1108
#endif
1109

1110
        return PERSONALITY_INVALID;
1111
}
1112

1113
const char* personality_to_string(unsigned long p) {
7,841✔
1114
        Architecture architecture = _ARCHITECTURE_INVALID;
7,841✔
1115

1116
        if (p == PER_LINUX)
7,841✔
1117
                architecture = native_architecture();
1118
#ifdef ARCHITECTURE_SECONDARY
1119
        else if (p == PER_LINUX32)
7,836✔
1120
                architecture = ARCHITECTURE_SECONDARY;
1121
#endif
1122

1123
        if (architecture < 0)
1124
                return NULL;
1125

1126
        return architecture_to_string(architecture);
7✔
1127
}
1128

1129
int safe_personality(unsigned long p) {
1,559✔
1130
        int ret;
1,559✔
1131

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

1139
        errno = 0;
1,559✔
1140
        ret = personality(p);
1,559✔
1141
        if (ret < 0) {
1,559✔
1142
                if (errno != 0)
12✔
1143
                        return -errno;
12✔
1144

1145
                errno = -ret;
×
1146
        }
1147

1148
        return ret;
1149
}
1150

1151
int opinionated_personality(unsigned long *ret) {
1,544✔
1152
        int current;
1,544✔
1153

1154
        assert(ret);
1,544✔
1155

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

1160
        current = safe_personality(PERSONALITY_INVALID);
1,544✔
1161
        if (current < 0)
1,544✔
1162
                return current;
1163

1164
        if (((unsigned long) current & OPINIONATED_PERSONALITY_MASK) == PER_LINUX32)
1,544✔
1165
                *ret = PER_LINUX32;
×
1166
        else
1167
                *ret = PER_LINUX;
1,544✔
1168

1169
        return 0;
1170
}
1171

1172
void valgrind_summary_hack(void) {
59✔
1173
#if HAVE_VALGRIND_VALGRIND_H
1174
        if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) {
1175
                pid_t pid;
1176
                pid = raw_clone(SIGCHLD);
1177
                if (pid < 0)
1178
                        log_struct_errno(
1179
                                LOG_EMERG, errno,
1180
                                LOG_MESSAGE_ID(SD_MESSAGE_VALGRIND_HELPER_FORK_STR),
1181
                                LOG_MESSAGE("Failed to fork off valgrind helper: %m"));
1182
                else if (pid == 0)
1183
                        exit(EXIT_SUCCESS);
1184
                else {
1185
                        log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
1186
                        _cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
1187
                        (void) pidref_set_pid(&pidref, pid);
1188
                        (void) pidref_wait_for_terminate(&pidref, NULL);
1189
                }
1190
        }
1191
#endif
1192
}
59✔
1193

1194
int pid_compare_func(const pid_t *a, const pid_t *b) {
864✔
1195
        /* Suitable for usage in qsort() */
1196
        assert(a);
864✔
1197
        assert(b);
864✔
1198

1199
        return CMP(*a, *b);
864✔
1200
}
1201

1202
bool nice_is_valid(int n) {
1,177✔
1203
        return n >= PRIO_MIN && n < PRIO_MAX;
1,177✔
1204
}
1205

1206
bool sched_policy_is_valid(int policy) {
×
1207
        return IN_SET(policy, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR, SCHED_EXT);
×
1208
}
1209

1210
bool sched_policy_supported(int policy) {
4✔
1211
        return sched_get_priority_min(policy) >= 0;
4✔
1212
}
1213

1214
/* Wrappers around sched_get_priority_{min,max}() that gracefully handles missing SCHED_EXT support in the kernel */
1215
int sched_get_priority_min_safe(int policy) {
4✔
1216
        int r;
4✔
1217

1218
        r = sched_get_priority_min(policy);
4✔
1219
        if (r >= 0)
4✔
1220
                return r;
4✔
1221

1222
        /* Fallback priority */
1223
        return 0;
1224
}
1225

1226
int sched_get_priority_max_safe(int policy) {
4✔
1227
        int r;
4✔
1228

1229
        r = sched_get_priority_max(policy);
4✔
1230
        if (r >= 0)
4✔
1231
                return r;
4✔
1232

1233
        return 0;
1234
}
1235

1236
/* The cached PID, possible values:
1237
 *
1238
 *     == UNSET [0]  → cache not initialized yet
1239
 *     == BUSY [-1]  → some thread is initializing it at the moment
1240
 *     any other     → the cached PID
1241
 */
1242

1243
#define CACHED_PID_UNSET ((pid_t) 0)
1244
#define CACHED_PID_BUSY ((pid_t) -1)
1245

1246
static pid_t cached_pid = CACHED_PID_UNSET;
1247

1248
void reset_cached_pid(void) {
1,884✔
1249
        /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
1250
        cached_pid = CACHED_PID_UNSET;
1,884✔
1251
}
1,884✔
1252

1253
pid_t getpid_cached(void) {
172,323,309✔
1254
        static bool installed = false;
172,323,309✔
1255
        pid_t current_value = CACHED_PID_UNSET;
172,323,309✔
1256

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

1266
        (void) __atomic_compare_exchange_n(
172,323,309✔
1267
                        &cached_pid,
1268
                        &current_value,
1269
                        CACHED_PID_BUSY,
1270
                        false,
1271
                        __ATOMIC_SEQ_CST,
1272
                        __ATOMIC_SEQ_CST);
1273

1274
        switch (current_value) {
172,323,309✔
1275

1276
        case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */
116,036✔
1277
                pid_t new_pid;
116,036✔
1278

1279
                new_pid = getpid();
116,036✔
1280

1281
                if (!installed) {
116,036✔
1282
                        /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's
1283
                         * only half-documented (glibc doesn't document it but LSB does — though only superficially)
1284
                         * we'll check for errors only in the most generic fashion possible. */
1285

1286
                        if (pthread_atfork(NULL, NULL, reset_cached_pid) != 0) {
83,400✔
1287
                                /* OOM? Let's try again later */
1288
                                cached_pid = CACHED_PID_UNSET;
×
1289
                                return new_pid;
×
1290
                        }
1291

1292
                        installed = true;
83,400✔
1293
                }
1294

1295
                cached_pid = new_pid;
116,036✔
1296
                return new_pid;
116,036✔
1297
        }
1298

1299
        case CACHED_PID_BUSY: /* Somebody else is currently initializing */
×
1300
                return getpid();
×
1301

1302
        default: /* Properly initialized */
1303
                return current_value;
1304
        }
1305
}
1306

1307
int must_be_root(void) {
73✔
1308

1309
        if (geteuid() == 0)
73✔
1310
                return 0;
1311

1312
        return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root.");
×
1313
}
1314

1315
pid_t clone_with_nested_stack(int (*fn)(void *), int flags, void *userdata) {
9,027✔
1316
        size_t ps;
9,027✔
1317
        pid_t pid;
9,027✔
1318
        void *mystack;
9,027✔
1319

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

1328
        assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
9,027✔
1329
                         CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
1330

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

1338
        ps = page_size();
9,027✔
1339
        mystack = alloca(ps*3);
9,027✔
1340
        mystack = (uint8_t*) mystack + ps; /* move pointer one page ahead since stacks usually grow backwards */
9,027✔
1341
        mystack = (void*) ALIGN_TO((uintptr_t) mystack, ps); /* align to page size (moving things further ahead) */
9,027✔
1342

1343
#if HAVE_CLONE
1344
        pid = clone(fn, mystack, flags, userdata);
9,027✔
1345
#else
1346
        pid = __clone2(fn, mystack, ps, flags, userdata);
1347
#endif
1348
        if (pid < 0)
9,027✔
1349
                return -errno;
×
1350

1351
        return pid;
1352
}
1353

1354
static int fork_flags_to_signal(ForkFlags flags) {
30,827✔
1355
        return (flags & FORK_DEATHSIG_SIGTERM) ? SIGTERM :
30,827✔
1356
                (flags & FORK_DEATHSIG_SIGINT) ? SIGINT :
1,022✔
1357
                                                 SIGKILL;
1358
}
1359

1360
int pidref_safe_fork_full(
29,001✔
1361
                const char *name,
1362
                const int stdio_fds[3],
1363
                int except_fds[],
1364
                size_t n_except_fds,
1365
                ForkFlags flags,
1366
                PidRef *ret) {
1367

1368
        pid_t original_pid, pid;
29,001✔
1369
        sigset_t saved_ss, ss;
29,001✔
1370
        _unused_ _cleanup_(block_signals_reset) sigset_t *saved_ssp = NULL;
×
1371
        bool block_signals = false, block_all = false, intermediary = false;
29,001✔
1372
        _cleanup_close_pair_ int pidref_transport_fds[2] = EBADF_PAIR;
60,782✔
1373
        int prio, r;
29,001✔
1374

1375
        assert(!FLAGS_SET(flags, FORK_WAIT|FORK_FREEZE));
29,001✔
1376
        assert(!FLAGS_SET(flags, FORK_DETACH) ||
29,001✔
1377
               (flags & (FORK_WAIT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL)) == 0);
1378

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

1383
        prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG;
29,001✔
1384

1385
        original_pid = getpid_cached();
29,001✔
1386

1387
        if (flags & FORK_FLUSH_STDIO) {
29,001✔
1388
                fflush(stdout);
5✔
1389
                fflush(stderr); /* This one shouldn't be necessary, stderr should be unbuffered anyway, but let's better be safe than sorry */
5✔
1390
        }
1391

1392
        if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT)) {
29,001✔
1393
                /* We temporarily block all signals, so that the new child has them blocked initially. This
1394
                 * way, we can be sure that SIGTERMs are not lost we might send to the child. (Note that for
1395
                 * FORK_DEATHSIG_SIGKILL we don't bother, since it cannot be blocked anyway.) */
1396

1397
                assert_se(sigfillset(&ss) >= 0);
24,339✔
1398
                block_signals = block_all = true;
1399

1400
        } else if (flags & FORK_WAIT) {
4,662✔
1401
                /* Let's block SIGCHLD at least, so that we can safely watch for the child process */
1402

1403
                assert_se(sigemptyset(&ss) >= 0);
164✔
1404
                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
164✔
1405
                block_signals = true;
1406
        }
1407

1408
        if (block_signals) {
1409
                if (sigprocmask(SIG_BLOCK, &ss, &saved_ss) < 0)
24,503✔
1410
                        return log_full_errno(prio, errno, "Failed to block signal mask: %m");
×
1411
                saved_ssp = &saved_ss;
24,503✔
1412
        }
1413

1414
        if (FLAGS_SET(flags, FORK_DETACH)) {
29,001✔
1415
                /* Fork off intermediary child if needed */
1416

1417
                r = is_reaper_process();
92✔
1418
                if (r < 0)
92✔
1419
                        return log_full_errno(prio, r, "Failed to determine if we are a reaper process: %m");
×
1420

1421
                if (!r) {
92✔
1422
                        /* Not a reaper process, hence do a double fork() so we are reparented to one */
1423

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

1427
                        pid = fork();
11✔
1428
                        if (pid < 0)
30✔
1429
                                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
×
1430
                        if (pid > 0) {
30✔
1431
                                log_debug("Successfully forked off intermediary '%s' as PID " PID_FMT ".", strna(name), pid);
11✔
1432

1433
                                pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
11✔
1434

1435
                                if (pidref_transport_fds[0] >= 0) {
11✔
1436
                                        /* Wait for the intermediary child to exit so the caller can be
1437
                                         * certain the actual child process has been reparented by the time
1438
                                         * this function returns. */
1439
                                        r = pidref_wait_for_terminate_and_check(
10✔
1440
                                                        name,
1441
                                                        &PIDREF_MAKE_FROM_PID(pid),
10✔
1442
                                                        FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
1443
                                        if (r < 0)
10✔
1444
                                                return log_full_errno(prio, r, "Failed to wait for intermediary process: %m");
×
1445
                                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
10✔
1446
                                                return -EPROTO;
1447

1448
                                        int pidfd;
10✔
1449
                                        ssize_t n = receive_one_fd_iov(
20✔
1450
                                                        pidref_transport_fds[0],
1451
                                                        &IOVEC_MAKE(&pid, sizeof(pid)),
10✔
1452
                                                        /* iovlen= */ 1,
1453
                                                        /* flags= */ 0,
1454
                                                        &pidfd);
1455
                                        if (n < 0)
10✔
1456
                                                return log_full_errno(prio, n, "Failed to receive child pidref: %m");
×
1457

1458
                                        *ret = (PidRef) { .pid = pid, .fd = pidfd };
10✔
1459
                                }
1460

1461
                                return 1; /* return in the parent */
1462
                        }
1463

1464
                        pidref_transport_fds[0] = safe_close(pidref_transport_fds[0]);
19✔
1465
                        intermediary = true;
19✔
1466
                }
1467
        }
1468

1469
        if ((flags & (FORK_NEW_MOUNTNS|FORK_NEW_USERNS|FORK_NEW_NETNS|FORK_NEW_PIDNS)) != 0)
29,009✔
1470
                pid = raw_clone(SIGCHLD|
6,612✔
1471
                                (FLAGS_SET(flags, FORK_NEW_MOUNTNS) ? CLONE_NEWNS : 0) |
6,612✔
1472
                                (FLAGS_SET(flags, FORK_NEW_USERNS) ? CLONE_NEWUSER : 0) |
6,612✔
1473
                                (FLAGS_SET(flags, FORK_NEW_NETNS) ? CLONE_NEWNET : 0) |
6,612✔
1474
                                (FLAGS_SET(flags, FORK_NEW_PIDNS) ? CLONE_NEWPID : 0));
6,612✔
1475
        else
1476
                pid = fork();
22,397✔
1477
        if (pid < 0)
60,784✔
1478
                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
×
1479
        if (pid > 0) {
60,784✔
1480

1481
                /* If we are in the intermediary process, exit now */
1482
                if (intermediary) {
28,550✔
1483
                        if (pidref_transport_fds[1] >= 0) {
13✔
1484
                                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
10✔
1485

1486
                                r = pidref_set_pid(&pidref, pid);
10✔
1487
                                if (r < 0) {
10✔
1488
                                        log_full_errno(prio, r, "Failed to open reference to PID "PID_FMT": %m", pid);
×
1489
                                        _exit(EXIT_FAILURE);
×
1490
                                }
1491

1492
                                r = send_one_fd_iov(
10✔
1493
                                                pidref_transport_fds[1],
1494
                                                pidref.fd,
1495
                                                &IOVEC_MAKE(&pidref.pid, sizeof(pidref.pid)),
1496
                                                /* iovlen= */ 1,
1497
                                                /* flags= */ 0);
1498
                                if (r < 0) {
10✔
1499
                                        log_full_errno(prio, r, "Failed to send child pidref: %m");
×
1500
                                        _exit(EXIT_FAILURE);
×
1501
                                }
1502
                        }
1503

1504
                        _exit(EXIT_SUCCESS);
13✔
1505
                }
1506

1507
                /* We are in the parent process */
1508
                log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
28,537✔
1509

1510
                if (flags & FORK_WAIT) {
28,537✔
1511
                        if (block_all) {
1,094✔
1512
                                /* undo everything except SIGCHLD */
1513
                                ss = saved_ss;
930✔
1514
                                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
930✔
1515
                                (void) sigprocmask(SIG_SETMASK, &ss, NULL);
930✔
1516
                        }
1517

1518
                        r = pidref_wait_for_terminate_and_check(
1,094✔
1519
                                        name,
1520
                                        &PIDREF_MAKE_FROM_PID(pid),
1,094✔
1521
                                        FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
1522
                        if (r < 0)
1,094✔
1523
                                return r;
1,094✔
1524
                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
1,094✔
1525
                                return -EPROTO;
1526

1527
                        /* If we are in the parent and successfully waited, then the process doesn't exist anymore. */
1528
                        if (ret)
1,086✔
1529
                                *ret = PIDREF_NULL;
28✔
1530

1531
                        return 1;
1532
                }
1533

1534
                if (ret) {
27,443✔
1535
                        r = pidref_set_pid(ret, pid);
26,139✔
1536
                        if (r < 0) /* Let's not fail for this, no matter what, the process exists after all, and that's key */
26,139✔
1537
                                *ret = PIDREF_MAKE_FROM_PID(pid);
×
1538
                }
1539

1540
                return 1;
1541
        }
1542

1543
        /* We are in the child process */
1544

1545
        pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
32,234✔
1546

1547
        /* Restore signal mask manually */
1548
        saved_ssp = NULL;
32,234✔
1549

1550
        if (flags & FORK_REOPEN_LOG) {
32,234✔
1551
                /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
1552
                log_close();
8,524✔
1553
                log_set_open_when_needed(true);
8,524✔
1554
                log_settle_target();
8,524✔
1555
        }
1556

1557
        if (name) {
32,234✔
1558
                r = rename_process(name);
32,234✔
1559
                if (r < 0)
32,234✔
1560
                        log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG,
×
1561
                                       r, "Failed to rename process, ignoring: %m");
1562
        }
1563

1564
        /* let's disable dlopen() in the child, as a paranoia safety precaution: children should not live for
1565
         * long and only do minimal work before exiting or exec()ing. Doing dlopen() is not either. If people
1566
         * want dlopen() they should do it before forking. This is a safety precaution in particular for
1567
         * cases where the child does namespace shenanigans: we should never end up loading a module from a
1568
         * foreign environment. Note that this has no effect on NSS! (i.e. it only has effect on uses of our
1569
         * dlopen_safe(), which we use comprehensively in our codebase, but glibc NSS doesn't bother, of
1570
         * course.) */
1571
        if (!FLAGS_SET(flags, FORK_ALLOW_DLOPEN))
32,234✔
1572
                block_dlopen();
32,195✔
1573

1574
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL))
32,234✔
1575
                if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) {
30,827✔
1576
                        log_full_errno(prio, errno, "Failed to set death signal: %m");
×
1577
                        _exit(EXIT_FAILURE);
×
1578
                }
1579

1580
        if (flags & FORK_RESET_SIGNALS) {
32,234✔
1581
                r = reset_all_signal_handlers();
27,070✔
1582
                if (r < 0) {
27,070✔
1583
                        log_full_errno(prio, r, "Failed to reset signal handlers: %m");
×
1584
                        _exit(EXIT_FAILURE);
×
1585
                }
1586

1587
                /* This implicitly undoes the signal mask stuff we did before the fork()ing above */
1588
                r = reset_signal_mask();
27,070✔
1589
                if (r < 0) {
27,070✔
1590
                        log_full_errno(prio, r, "Failed to reset signal mask: %m");
×
1591
                        _exit(EXIT_FAILURE);
×
1592
                }
1593
        } else if (block_signals) { /* undo what we did above */
5,164✔
1594
                if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
4,653✔
1595
                        log_full_errno(prio, errno, "Failed to restore signal mask: %m");
×
1596
                        _exit(EXIT_FAILURE);
×
1597
                }
1598
        }
1599

1600
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL|FORK_DEATHSIG_SIGINT)) {
32,234✔
1601
                pid_t ppid;
30,827✔
1602
                /* Let's see if the parent PID is still the one we started from? If not, then the parent
1603
                 * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
1604

1605
                ppid = getppid();
30,827✔
1606
                if (ppid == 0)
30,827✔
1607
                        /* Parent is in a different PID namespace. */;
1608
                else if (ppid != original_pid) {
30,789✔
1609
                        int sig = fork_flags_to_signal(flags);
×
1610
                        log_debug("Parent died early, raising %s.", signal_to_string(sig));
×
1611
                        (void) raise(sig);
×
1612
                        _exit(EXIT_FAILURE);
×
1613
                }
1614
        }
1615

1616
        if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) {
32,234✔
1617
                /* Optionally, make sure we never propagate mounts to the host. */
1618
                if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
197✔
1619
                        log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
×
1620
                        _exit(EXIT_FAILURE);
×
1621
                }
1622
        }
1623

1624
        if (FLAGS_SET(flags, FORK_PRIVATE_TMP)) {
32,234✔
1625
                assert(FLAGS_SET(flags, FORK_NEW_MOUNTNS));
×
1626

1627
                /* Optionally, overmount new tmpfs instance on /tmp/. */
1628
                r = mount_nofollow("tmpfs", "/tmp", "tmpfs",
×
1629
                                   MS_NOSUID|MS_NODEV,
1630
                                   "mode=01777" TMPFS_LIMITS_RUN);
1631
                if (r < 0) {
×
1632
                        log_full_errno(prio, r, "Failed to overmount /tmp/: %m");
×
1633
                        _exit(EXIT_FAILURE);
×
1634
                }
1635
        }
1636

1637
        if (flags & FORK_REARRANGE_STDIO) {
32,234✔
1638
                if (stdio_fds) {
15,911✔
1639
                        r = rearrange_stdio(stdio_fds[0], stdio_fds[1], stdio_fds[2]);
15,893✔
1640
                        if (r < 0) {
15,893✔
1641
                                log_full_errno(prio, r, "Failed to rearrange stdio fds: %m");
×
1642
                                _exit(EXIT_FAILURE);
×
1643
                        }
1644

1645
                        /* Turn off O_NONBLOCK on the fdio fds, in case it was left on */
1646
                        stdio_disable_nonblock();
15,893✔
1647
                } else {
1648
                        r = make_null_stdio();
18✔
1649
                        if (r < 0) {
18✔
1650
                                log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
×
1651
                                _exit(EXIT_FAILURE);
×
1652
                        }
1653
                }
1654
        } else if (flags & FORK_STDOUT_TO_STDERR) {
16,323✔
1655
                if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
2✔
1656
                        log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
×
1657
                        _exit(EXIT_FAILURE);
×
1658
                }
1659
        }
1660

1661
        if (flags & FORK_CLOSE_ALL_FDS) {
32,234✔
1662
                /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
1663
                log_close();
25,515✔
1664

1665
                r = close_all_fds(except_fds, n_except_fds);
25,515✔
1666
                if (r < 0) {
25,515✔
1667
                        log_full_errno(prio, r, "Failed to close all file descriptors: %m");
×
1668
                        _exit(EXIT_FAILURE);
×
1669
                }
1670
        }
1671

1672
        if (flags & FORK_PACK_FDS) {
32,234✔
1673
                /* FORK_CLOSE_ALL_FDS ensures that except_fds are the only FDs >= 3 that are
1674
                 * open, this is including the log. This is required by pack_fds, which will
1675
                 * get stuck in an infinite loop of any FDs other than except_fds are open. */
1676
                assert(FLAGS_SET(flags, FORK_CLOSE_ALL_FDS));
145✔
1677

1678
                r = pack_fds(except_fds, n_except_fds);
145✔
1679
                if (r < 0) {
145✔
1680
                        log_full_errno(prio, r, "Failed to pack file descriptors: %m");
×
1681
                        _exit(EXIT_FAILURE);
×
1682
                }
1683
        }
1684

1685
        if (flags & FORK_CLOEXEC_OFF) {
32,234✔
1686
                r = fd_cloexec_many(except_fds, n_except_fds, false);
162✔
1687
                if (r < 0) {
162✔
1688
                        log_full_errno(prio, r, "Failed to turn off O_CLOEXEC on file descriptors: %m");
×
1689
                        _exit(EXIT_FAILURE);
×
1690
                }
1691
        }
1692

1693
        /* When we were asked to reopen the logs, do so again now */
1694
        if (flags & FORK_REOPEN_LOG) {
32,234✔
1695
                log_open();
8,524✔
1696
                log_set_open_when_needed(false);
8,524✔
1697
        }
1698

1699
        if (flags & FORK_RLIMIT_NOFILE_SAFE) {
32,234✔
1700
                r = rlimit_nofile_safe();
16,723✔
1701
                if (r < 0) {
16,723✔
1702
                        log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
×
1703
                        _exit(EXIT_FAILURE);
×
1704
                }
1705
        }
1706

1707
        if (!FLAGS_SET(flags, FORK_KEEP_NOTIFY_SOCKET)) {
32,234✔
1708
                r = RET_NERRNO(unsetenv("NOTIFY_SOCKET"));
32,234✔
1709
                if (r < 0) {
×
1710
                        log_full_errno(prio, r, "Failed to unset $NOTIFY_SOCKET: %m");
×
1711
                        _exit(EXIT_FAILURE);
×
1712
                }
1713
        }
1714

1715
        if (FLAGS_SET(flags, FORK_FREEZE))
32,234✔
1716
                freeze();
×
1717

1718
        if (ret) {
32,234✔
1719
                r = pidref_set_self(ret);
29,964✔
1720
                if (r < 0) {
29,964✔
1721
                        log_full_errno(prio, r, "Failed to acquire PID reference on ourselves: %m");
×
1722
                        _exit(EXIT_FAILURE);
×
1723
                }
1724
        }
1725

1726
        return 0;
1727
}
1728

1729
int namespace_fork_full(
141✔
1730
                const char *outer_name,
1731
                const char *inner_name,
1732
                int except_fds[],
1733
                size_t n_except_fds,
1734
                ForkFlags flags,
1735
                int pidns_fd,
1736
                int mntns_fd,
1737
                int netns_fd,
1738
                int userns_fd,
1739
                int root_fd,
1740
                PidRef *ret) {
1741

1742
        _cleanup_(pidref_done_sigkill_wait) PidRef pidref_outer = PIDREF_NULL;
×
1743
        _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
239✔
1744
        int r, prio = FLAGS_SET(flags, FORK_LOG) ? LOG_ERR : LOG_DEBUG;
141✔
1745

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

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

1759
        /* We want read() to block as a synchronization point */
1760
        assert_cc(sizeof(int) <= PIPE_BUF);
141✔
1761
        if (pipe2(errno_pipe_fd, O_CLOEXEC) < 0)
141✔
1762
                return log_full_errno(prio, errno, "Failed to create pipe: %m");
×
1763

1764
        r = pidref_safe_fork_full(
379✔
1765
                        outer_name,
1766
                        /* stdio_fds= */ NULL, /* except_fds= */ NULL, /* n_except_fds= */ 0,
1767
                        (flags|FORK_DEATHSIG_SIGKILL) & ~(FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_NEW_NETNS|FORK_NEW_PIDNS|FORK_CLOSE_ALL_FDS|FORK_PACK_FDS|FORK_CLOEXEC_OFF|FORK_RLIMIT_NOFILE_SAFE),
141✔
1768
                        &pidref_outer);
1769
        if (r == -EPROTO && FLAGS_SET(flags, FORK_WAIT)) {
238✔
1770
                errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
8✔
1771

1772
                int k = read_errno(errno_pipe_fd[0]);
8✔
1773
                if (k < 0 && k != -EIO)
8✔
1774
                        return k;
1775
        }
1776
        if (r < 0)
238✔
1777
                return r;
1778
        if (r == 0) {
230✔
1779
                _cleanup_(pidref_done) PidRef pidref_inner = PIDREF_NULL;
×
1780

1781
                /* Child */
1782

1783
                errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
97✔
1784

1785
                r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
97✔
1786
                if (r < 0) {
97✔
1787
                        log_full_errno(prio, r, "Failed to join namespace: %m");
×
1788
                        report_errno_and_exit(errno_pipe_fd[1], r);
×
1789
                }
1790

1791
                /* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */
1792
                r = pidref_safe_fork_full(
292✔
1793
                                inner_name,
1794
                                NULL,
1795
                                except_fds, n_except_fds,
1796
                                flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_REARRANGE_STDIO|FORK_FLUSH_STDIO|FORK_STDOUT_TO_STDERR),
97✔
1797
                                &pidref_inner);
1798
                if (r < 0)
195✔
1799
                        report_errno_and_exit(errno_pipe_fd[1], r);
×
1800
                if (r == 0) {
195✔
1801
                        /* Child */
1802

1803
                        if (!FLAGS_SET(flags, FORK_CLOSE_ALL_FDS)) {
98✔
1804
                                errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
95✔
1805
                                pidref_done(&pidref_outer);
95✔
1806
                        } else {
1807
                                errno_pipe_fd[1] = -EBADF;
3✔
1808
                                pidref_outer = PIDREF_NULL;
3✔
1809
                        }
1810

1811
                        if (ret)
98✔
1812
                                *ret = TAKE_PIDREF(pidref_inner);
98✔
1813
                        return 0;
98✔
1814
                }
1815

1816
                log_forget_fds();
97✔
1817
                log_set_open_when_needed(true);
97✔
1818

1819
                (void) close_all_fds(&pidref_inner.fd, 1);
97✔
1820

1821
                r = pidref_wait_for_terminate_and_check(
194✔
1822
                                inner_name,
1823
                                &pidref_inner,
1824
                                FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
1825
                if (r < 0)
97✔
1826
                        _exit(EXIT_FAILURE);
×
1827

1828
                _exit(r);
97✔
1829
        }
1830

1831
        errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
133✔
1832

1833
        r = read_errno(errno_pipe_fd[0]);
133✔
1834
        if (r < 0)
133✔
1835
                return r; /* the child logs about failures on its own, no need to duplicate here */
1836

1837
        if (ret)
133✔
1838
                *ret = TAKE_PIDREF(pidref_outer);
107✔
1839
        else
1840
                pidref_done(&pidref_outer); /* disarm sigkill_wait */
26✔
1841

1842
        return 1;
1843
}
1844

1845
bool oom_score_adjust_is_valid(int oa) {
12,078✔
1846
        return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
12,078✔
1847
}
1848

1849
int set_oom_score_adjust(int value) {
3,357✔
1850
        char t[DECIMAL_STR_MAX(int)];
3,357✔
1851

1852
        if (!oom_score_adjust_is_valid(value))
3,357✔
1853
                return -EINVAL;
3,357✔
1854

1855
        xsprintf(t, "%i", value);
3,357✔
1856

1857
        return write_string_file("/proc/self/oom_score_adj", t,
3,357✔
1858
                                 WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
1859
}
1860

1861
int get_oom_score_adjust(int *ret) {
7,226✔
1862
        _cleanup_free_ char *t = NULL;
7,226✔
1863
        int r, a;
7,226✔
1864

1865
        r = read_virtual_file("/proc/self/oom_score_adj", SIZE_MAX, &t, NULL);
7,226✔
1866
        if (r < 0)
7,226✔
1867
                return r;
1868

1869
        delete_trailing_chars(t, WHITESPACE);
7,226✔
1870

1871
        r = safe_atoi(t, &a);
7,226✔
1872
        if (r < 0)
7,226✔
1873
                return r;
1874

1875
        if (!oom_score_adjust_is_valid(a))
7,226✔
1876
                return -ENODATA;
1877

1878
        if (ret)
7,226✔
1879
                *ret = a;
7,226✔
1880

1881
        return 0;
1882
}
1883

1884
static int rlimit_to_nice(rlim_t limit) {
2✔
1885
        if (limit <= 1)
2✔
1886
                return PRIO_MAX-1; /* i.e. 19 */
1887

1888
        if (limit >= -PRIO_MIN + PRIO_MAX)
2✔
1889
                return PRIO_MIN; /* i.e. -20 */
1890

1891
        return PRIO_MAX - (int) limit;
2✔
1892
}
1893

1894
int setpriority_closest(int priority) {
29✔
1895
        struct rlimit highest;
29✔
1896
        int r, current, limit;
29✔
1897

1898
        /* Try to set requested nice level */
1899
        r = RET_NERRNO(setpriority(PRIO_PROCESS, 0, priority));
29✔
1900
        if (r >= 0)
2✔
1901
                return 1;
29✔
1902
        if (!ERRNO_IS_NEG_PRIVILEGE(r))
2✔
1903
                return r;
1904

1905
        errno = 0;
2✔
1906
        current = getpriority(PRIO_PROCESS, 0);
2✔
1907
        if (errno != 0)
2✔
1908
                return -errno;
×
1909

1910
        if (priority == current)
2✔
1911
                return 1;
1912

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

1919
        if (getrlimit(RLIMIT_NICE, &highest) < 0)
2✔
1920
                return -errno;
×
1921

1922
        limit = rlimit_to_nice(highest.rlim_cur);
2✔
1923

1924
        /* Push to the allowed limit if we're higher than that. Note that we could also be less nice than
1925
         * limit allows us, but still higher than what's requested. In that case our current value is
1926
         * the best choice. */
1927
        if (current > limit)
2✔
1928
                if (setpriority(PRIO_PROCESS, 0, limit) < 0)
2✔
1929
                        return -errno;
×
1930

1931
        log_debug("Cannot set requested nice level (%i), using next best (%i).", priority, MIN(current, limit));
2✔
1932
        return 0;
1933
}
1934

1935
_noreturn_ void freeze(void) {
×
1936
        log_close();
×
1937

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

1943
        /* Let's not freeze right away, but keep reaping zombies. */
1944
        for (;;) {
×
1945
                siginfo_t si = {};
×
1946

1947
                if (waitid(P_ALL, 0, &si, WEXITED) < 0 && errno != EINTR)
×
1948
                        break;
1949
        }
1950

1951
        /* waitid() failed with an ECHLD error (because there are no left-over child processes) or any other
1952
         * (unexpected) error. Freeze for good now! */
1953
        for (;;)
×
1954
                pause();
×
1955
}
1956

1957
int get_process_threads(pid_t pid) {
7✔
1958
        _cleanup_free_ char *t = NULL;
7✔
1959
        int n, r;
7✔
1960

1961
        if (pid < 0)
7✔
1962
                return -EINVAL;
1963

1964
        r = procfs_file_get_field(pid, "status", "Threads", &t);
7✔
1965
        if (r == -ENOENT)
7✔
1966
                return -ESRCH;
1967
        if (r < 0)
7✔
1968
                return r;
1969

1970
        r = safe_atoi(t, &n);
7✔
1971
        if (r < 0)
7✔
1972
                return r;
1973
        if (n < 0)
7✔
1974
                return -EINVAL;
×
1975

1976
        return n;
1977
}
1978

1979
int is_reaper_process(void) {
9,123✔
1980
        int b = 0;
9,123✔
1981

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

1985
        if (getpid_cached() == 1)
9,123✔
1986
                return true;
9,123✔
1987

1988
        if (prctl(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0UL, 0UL, 0UL) < 0)
404✔
1989
                return -errno;
×
1990

1991
        return b != 0;
404✔
1992
}
1993

1994
int make_reaper_process(bool b) {
749✔
1995

1996
        if (getpid_cached() == 1) {
749✔
1997

1998
                if (!b)
73✔
1999
                        return -EINVAL;
2000

2001
                return 0;
73✔
2002
        }
2003

2004
        /* Some prctl()s insist that all 5 arguments are specified, others do not. Let's always specify all,
2005
         * to avoid any ambiguities */
2006
        if (prctl(PR_SET_CHILD_SUBREAPER, (unsigned long) b, 0UL, 0UL, 0UL) < 0)
676✔
2007
                return -errno;
×
2008

2009
        return 0;
2010
}
2011

2012
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(posix_spawnattr_t*, posix_spawnattr_destroy, NULL);
×
2013

2014
int posix_spawn_wrapper(
4,438✔
2015
                const char *path,
2016
                char * const *argv,
2017
                char * const *envp,
2018
                const char *cgroup,
2019
                PidRef *ret_pidref) {
2020

2021
        short flags = POSIX_SPAWN_SETSIGMASK;
4,438✔
2022
        posix_spawnattr_t attr;
4,438✔
2023
        sigset_t mask;
4,438✔
2024
        int r;
4,438✔
2025

2026
        /* Forks and invokes 'path' with 'argv' and 'envp' using CLONE_VM and CLONE_VFORK, which means the
2027
         * caller will be blocked until the child either exits or exec's. The memory of the child will be
2028
         * fully shared with the memory of the parent, so that there are no copy-on-write or memory.max
2029
         * issues.
2030
         *
2031
         * Also, move the newly-created process into 'cgroup' through POSIX_SPAWN_SETCGROUP (clone3())
2032
         * if available.
2033
         * returns 1: We're already in the right cgroup
2034
         *         0: 'cgroup' not specified or POSIX_SPAWN_SETCGROUP is not supported. The caller
2035
         *            needs to call 'cg_attach' on their own */
2036

2037
        assert(path);
4,438✔
2038
        assert(argv);
4,438✔
2039
        assert(ret_pidref);
4,438✔
2040

2041
        assert_se(sigfillset(&mask) >= 0);
4,438✔
2042

2043
        r = posix_spawnattr_init(&attr);
4,438✔
2044
        if (r != 0)
4,438✔
2045
                return -r; /* These functions return a positive errno on failure */
×
2046

2047
        /* Initialization needs to succeed before we can set up a destructor. */
2048
        _unused_ _cleanup_(posix_spawnattr_destroyp) posix_spawnattr_t *attr_destructor = &attr;
4,438✔
2049

2050
        static bool have_clone_into_cgroup = true; /* kernel 5.7+ */
4,438✔
2051
        _cleanup_close_ int cgroup_fd = -EBADF;
4,438✔
2052

2053
        if (cgroup && have_clone_into_cgroup) {
4,438✔
2054
                _cleanup_free_ char *resolved_cgroup = NULL;
4,438✔
2055

2056
                r = cg_get_path(cgroup, /* suffix= */ NULL, &resolved_cgroup);
4,438✔
2057
                if (r < 0)
4,438✔
2058
                        return r;
2059

2060
                cgroup_fd = open(resolved_cgroup, O_PATH|O_DIRECTORY|O_CLOEXEC);
4,438✔
2061
                if (cgroup_fd < 0)
4,438✔
2062
                        return -errno;
×
2063

2064
                r = posix_spawnattr_setcgroup_np(&attr, cgroup_fd);
4,438✔
2065
                if (r == 0)
4,438✔
2066
                        flags |= POSIX_SPAWN_SETCGROUP;
2067
                else if (r != ENOSYS)
×
2068
                        return -r;
×
2069
                /* If libc lacks posix_spawnattr_setcgroup_np we silently skip POSIX_SPAWN_SETCGROUP — the
2070
                 * caller will then need to attach the child to the cgroup themselves. */
2071
        }
2072

2073
        r = posix_spawnattr_setflags(&attr, flags);
4,438✔
2074
        if (r != 0)
4,438✔
2075
                return -r;
×
2076
        r = posix_spawnattr_setsigmask(&attr, &mask);
4,438✔
2077
        if (r != 0)
4,438✔
2078
                return -r;
×
2079

2080
        _cleanup_close_ int pidfd = -EBADF;
4,438✔
2081

2082
        r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
4,438✔
2083
        if (ERRNO_IS_NOT_SUPPORTED(r) && FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP) && cg_is_threaded(cgroup) > 0)
4,438✔
2084
                return -EUCLEAN; /* clone3() could also return EOPNOTSUPP if the target cgroup is in threaded mode,
2085
                                    turn that into something recognizable */
2086
        if ((ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r)) &&
4,438✔
2087
            FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP)) {
2088
                /* Compiled on a newer host, or seccomp&friends blocking clone3()? Fallback, but
2089
                 * need to disable POSIX_SPAWN_SETCGROUP, which is what redirects to clone3().
2090
                 * CLONE_INTO_CGROUP definitely won't work, hence remember the fact so that we don't
2091
                 * retry every time.
2092
                 * Note, CLONE_INTO_CGROUP is supported since kernel v5.7, but some architectures still
2093
                 * do not support clone3(). Hence, we need to keep the fallback logic for a while. */
2094
                have_clone_into_cgroup = false;
×
2095

2096
                flags &= ~POSIX_SPAWN_SETCGROUP;
×
2097
                r = posix_spawnattr_setflags(&attr, flags);
×
2098
                if (r != 0)
×
2099
                        return -r;
×
2100

2101
                r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
×
2102
        }
2103
        if (r == 0) {
4,438✔
2104
                r = pidref_set_pidfd_consume(ret_pidref, TAKE_FD(pidfd));
4,438✔
2105
                if (r < 0)
4,438✔
2106
                        return r;
2107

2108
                return FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP);
4,438✔
2109
        }
2110
        if (!ERRNO_IS_NOT_SUPPORTED(r))
×
2111
                return -r;
×
2112

2113
        /* pidfd_spawn unavailable (libc or kernel missing) — fall back to plain posix_spawn. */
2114

2115
        pid_t pid;
×
2116

2117
        r = posix_spawn(&pid, path, NULL, &attr, argv, envp);
×
2118
        if (r != 0)
×
2119
                return -r;
×
2120

2121
        r = pidref_set_pid(ret_pidref, pid);
×
2122
        if (r < 0)
×
2123
                return r;
×
2124

2125
        return 0; /* We did not use CLONE_INTO_CGROUP so return 0, the caller will have to move the child */
2126
}
2127

2128
int proc_dir_open(DIR **ret) {
18✔
2129
        DIR *d;
18✔
2130

2131
        assert(ret);
18✔
2132

2133
        d = opendir("/proc");
18✔
2134
        if (!d)
18✔
2135
                return -errno;
×
2136

2137
        *ret = d;
18✔
2138
        return 0;
18✔
2139
}
2140

2141
int proc_dir_read(DIR *d, pid_t *ret) {
1,497✔
2142
        assert(d);
1,497✔
2143

2144
        for (;;) {
2,581✔
2145
                struct dirent *de;
2,581✔
2146

2147
                errno = 0;
2,581✔
2148
                de = readdir_no_dot(d);
2,581✔
2149
                if (!de) {
2,581✔
2150
                        if (errno != 0)
18✔
2151
                                return -errno;
×
2152

2153
                        break;
18✔
2154
                }
2155

2156
                if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
2,563✔
2157
                        continue;
886✔
2158

2159
                if (parse_pid(de->d_name, ret) >= 0)
1,677✔
2160
                        return 1;
2161
        }
2162

2163
        if (ret)
18✔
2164
                *ret = 0;
18✔
2165
        return 0;
2166
}
2167

2168
int proc_dir_read_pidref(DIR *d, PidRef *ret) {
1,453✔
2169
        int r;
1,453✔
2170

2171
        assert(d);
1,453✔
2172

2173
        for (;;) {
1,453✔
2174
                pid_t pid;
1,453✔
2175

2176
                r = proc_dir_read(d, &pid);
1,453✔
2177
                if (r < 0)
1,453✔
2178
                        return r;
1,436✔
2179
                if (r == 0)
1,453✔
2180
                        break;
2181

2182
                r = pidref_set_pid(ret, pid);
1,436✔
2183
                if (r == -ESRCH) /* gone by now? skip it */
1,436✔
UNCOV
2184
                        continue;
×
2185
                if (r < 0)
1,436✔
2186
                        return r;
×
2187

2188
                return 1;
2189
        }
2190

2191
        if (ret)
17✔
2192
                *ret = PIDREF_NULL;
17✔
2193
        return 0;
2194
}
2195

2196
int safe_mlockall(int flags) {
169✔
2197
        int r;
169✔
2198

2199
        /* When dealing with sensitive data, let's lock ourselves into memory. We do this only when
2200
         * privileged however, as otherwise the amount of lockable memory that RLIMIT_MEMLOCK grants us is
2201
         * frequently too low to make this work. The resource limit has no effect on CAP_IPC_LOCK processes,
2202
         * hence that's the capability we check for. */
2203
        r = have_effective_cap(CAP_IPC_LOCK);
169✔
2204
        if (r < 0)
169✔
2205
                return log_debug_errno(r, "Failed to determine if we have CAP_IPC_LOCK: %m");
×
2206
        if (r == 0)
169✔
2207
                return log_debug_errno(SYNTHETIC_ERRNO(EPERM), "Lacking CAP_IPC_LOCK, skipping mlockall().");
×
2208

2209
        if (mlockall(flags) < 0)
169✔
2210
                return log_debug_errno(errno, "Failed to call mlockall(): %m");
×
2211

2212
        log_debug("Successfully called mlockall().");
169✔
2213
        return 0;
2214
}
2215

2216
static const char *const sigchld_code_table[] = {
2217
        [CLD_EXITED] = "exited",
2218
        [CLD_KILLED] = "killed",
2219
        [CLD_DUMPED] = "dumped",
2220
        [CLD_TRAPPED] = "trapped",
2221
        [CLD_STOPPED] = "stopped",
2222
        [CLD_CONTINUED] = "continued",
2223
};
2224

2225
DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
18,369✔
2226

2227
static const char* const sched_policy_table[] = {
2228
        [SCHED_OTHER] = "other",
2229
        [SCHED_BATCH] = "batch",
2230
        [SCHED_IDLE]  = "idle",
2231
        [SCHED_FIFO]  = "fifo",
2232
        [SCHED_EXT]   = "ext",
2233
        [SCHED_RR]    = "rr",
2234
};
2235

2236
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
1,854✔
2237

2238
_noreturn_ void report_errno_and_exit(int errno_fd, int error) {
198✔
2239
        int r;
198✔
2240

2241
        if (error >= 0)
198✔
2242
                _exit(EXIT_SUCCESS);
197✔
2243

2244
        assert(errno_fd >= 0);
1✔
2245

2246
        r = loop_write(errno_fd, &error, sizeof(error));
1✔
2247
        if (r < 0)
1✔
2248
                log_debug_errno(r, "Failed to write errno to errno_fd=%d: %m", errno_fd);
×
2249

2250
        _exit(EXIT_FAILURE);
1✔
2251
}
2252

2253
int read_errno(int errno_fd) {
152✔
2254
        int r;
152✔
2255

2256
        assert(errno_fd >= 0);
152✔
2257

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

2261
        ssize_t n = loop_read(errno_fd, &r, sizeof(r), /* do_poll= */ false);
152✔
2262
        if (n < 0) {
152✔
2263
                log_debug_errno(n, "Failed to read errno: %m");
×
2264
                return -EIO;
152✔
2265
        }
2266
        if (n == 0) /* the process exited without reporting an error, assuming success */
152✔
2267
                return 0;
2268
        if (n != sizeof(r))
8✔
2269
                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received unexpected amount of bytes (%zi) while reading errno.", n);
×
2270

2271
        if (r == 0)
8✔
2272
                return 0;
2273
        if (r < 0) /* child process reported an error, return it */
8✔
2274
                return log_debug_errno(r, "Child process failed with errno: %m");
8✔
2275

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