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

systemd / systemd / 13467361532

22 Feb 2025 12:05AM UTC coverage: 71.803% (+0.1%) from 71.665%
13467361532

push

github

DaanDeMeyer
sbsign: Don't set bit in SpcPeImageData->flags

Neither sbsign nor pesign set this flag in SpcPeImageData->flags,
which is about which resources should be included specifying "Which
portions of the Windows PE file are hashed." according to the
authenticode spec. However, this is followed by "Although flags is
always present, it is ignored when calculating the file hash for both
signing and verification purposes". So as it doesn't seem to do
anything useful and the other tools don't set any of these flags
either, let's follow suite and not set this flag ourselves either.

294198 of 409731 relevant lines covered (71.8%)

717663.79 hits per line

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

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

3
#include <ctype.h>
4
#include <errno.h>
5
#include <limits.h>
6
#include <linux/oom.h>
7
#include <pthread.h>
8
#include <spawn.h>
9
#include <stdbool.h>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <sys/mount.h>
13
#include <sys/personality.h>
14
#include <sys/prctl.h>
15
#include <sys/types.h>
16
#include <sys/wait.h>
17
#include <syslog.h>
18
#include <unistd.h>
19
#if HAVE_VALGRIND_VALGRIND_H
20
#include <valgrind/valgrind.h>
21
#endif
22

23
#include "sd-messages.h"
24

25
#include "alloc-util.h"
26
#include "architecture.h"
27
#include "argv-util.h"
28
#include "cgroup-util.h"
29
#include "dirent-util.h"
30
#include "env-file.h"
31
#include "env-util.h"
32
#include "errno-util.h"
33
#include "escape.h"
34
#include "fd-util.h"
35
#include "fileio.h"
36
#include "fs-util.h"
37
#include "hostname-util.h"
38
#include "io-util.h"
39
#include "iovec-util.h"
40
#include "locale-util.h"
41
#include "log.h"
42
#include "macro.h"
43
#include "memory-util.h"
44
#include "missing_sched.h"
45
#include "missing_syscall.h"
46
#include "missing_threads.h"
47
#include "mountpoint-util.h"
48
#include "namespace-util.h"
49
#include "nulstr-util.h"
50
#include "parse-util.h"
51
#include "path-util.h"
52
#include "pidfd-util.h"
53
#include "process-util.h"
54
#include "raw-clone.h"
55
#include "rlimit-util.h"
56
#include "signal-util.h"
57
#include "socket-util.h"
58
#include "stat-util.h"
59
#include "stdio-util.h"
60
#include "string-table.h"
61
#include "string-util.h"
62
#include "terminal-util.h"
63
#include "time-util.h"
64
#include "user-util.h"
65
#include "utf8.h"
66

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

72
static int get_process_state(pid_t pid) {
7,167✔
73
        _cleanup_free_ char *line = NULL;
7,167✔
74
        const char *p;
7,167✔
75
        char state;
7,167✔
76
        int r;
7,167✔
77

78
        assert(pid >= 0);
7,167✔
79

80
        /* Shortcut: if we are enquired about our own state, we are obviously running */
81
        if (pid == 0 || pid == getpid_cached())
7,167✔
82
                return (unsigned char) 'R';
×
83

84
        p = procfs_file_alloca(pid, "stat");
7,167✔
85

86
        r = read_one_line_file(p, &line);
7,167✔
87
        if (r == -ENOENT)
7,167✔
88
                return -ESRCH;
89
        if (r < 0)
5,669✔
90
                return r;
91

92
        p = strrchr(line, ')');
5,668✔
93
        if (!p)
5,668✔
94
                return -EIO;
95

96
        p++;
5,668✔
97

98
        if (sscanf(p, " %c", &state) != 1)
5,668✔
99
                return -EIO;
100

101
        return (unsigned char) state;
5,668✔
102
}
103

104
int pid_get_comm(pid_t pid, char **ret) {
53,102✔
105
        _cleanup_free_ char *escaped = NULL, *comm = NULL;
53,102✔
106
        int r;
53,102✔
107

108
        assert(pid >= 0);
53,102✔
109
        assert(ret);
53,102✔
110

111
        if (pid == 0 || pid == getpid_cached()) {
53,102✔
112
                comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */
26,595✔
113
                if (!comm)
26,595✔
114
                        return -ENOMEM;
115

116
                if (prctl(PR_GET_NAME, comm) < 0)
26,595✔
117
                        return -errno;
×
118
        } else {
119
                const char *p;
26,507✔
120

121
                p = procfs_file_alloca(pid, "comm");
26,507✔
122

123
                /* Note that process names of kernel threads can be much longer than TASK_COMM_LEN */
124
                r = read_one_line_file(p, &comm);
26,507✔
125
                if (r == -ENOENT)
26,507✔
126
                        return -ESRCH;
127
                if (r < 0)
22,896✔
128
                        return r;
129
        }
130

131
        escaped = new(char, COMM_MAX_LEN);
49,487✔
132
        if (!escaped)
49,487✔
133
                return -ENOMEM;
134

135
        /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */
136
        cellescape(escaped, COMM_MAX_LEN, comm);
49,487✔
137

138
        *ret = TAKE_PTR(escaped);
49,487✔
139
        return 0;
49,487✔
140
}
141

142
int pidref_get_comm(const PidRef *pid, char **ret) {
30✔
143
        _cleanup_free_ char *comm = NULL;
30✔
144
        int r;
30✔
145

146
        if (!pidref_is_set(pid))
30✔
147
                return -ESRCH;
148

149
        if (pidref_is_remote(pid))
60✔
150
                return -EREMOTE;
151

152
        r = pid_get_comm(pid->pid, &comm);
30✔
153
        if (r < 0)
30✔
154
                return r;
155

156
        r = pidref_verify(pid);
30✔
157
        if (r < 0)
30✔
158
                return r;
159

160
        if (ret)
30✔
161
                *ret = TAKE_PTR(comm);
30✔
162
        return 0;
163
}
164

165
static int pid_get_cmdline_nulstr(
16,902✔
166
                pid_t pid,
167
                size_t max_size,
168
                ProcessCmdlineFlags flags,
169
                char **ret,
170
                size_t *ret_size) {
171

172
        _cleanup_free_ char *t = NULL;
16,902✔
173
        const char *p;
16,902✔
174
        size_t k;
16,902✔
175
        int r;
16,902✔
176

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

188
        p = procfs_file_alloca(pid, "cmdline");
16,902✔
189
        r = read_virtual_file(p, max_size, &t, &k); /* Let's assume that each input byte results in >= 1
16,902✔
190
                                                     * columns of output. We ignore zero-width codepoints. */
191
        if (r == -ENOENT)
16,902✔
192
                return -ESRCH;
193
        if (r < 0)
14,392✔
194
                return r;
195

196
        if (k == 0) {
14,392✔
197
                if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
811✔
198
                        return -ENOENT;
792✔
199

200
                /* Kernel threads have no argv[] */
201
                _cleanup_free_ char *comm = NULL;
19✔
202

203
                r = pid_get_comm(pid, &comm);
19✔
204
                if (r < 0)
19✔
205
                        return r;
206

207
                free(t);
19✔
208
                t = strjoin("[", comm, "]");
19✔
209
                if (!t)
19✔
210
                        return -ENOMEM;
211

212
                k = strlen(t);
19✔
213
                r = k <= max_size;
19✔
214
                if (r == 0) /* truncation */
19✔
215
                        t[max_size] = '\0';
12✔
216
        }
217

218
        if (ret)
13,600✔
219
                *ret = TAKE_PTR(t);
13,600✔
220
        if (ret_size)
13,600✔
221
                *ret_size = k;
13,600✔
222

223
        return r;
224
}
225

226
int pid_get_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
11,986✔
227
        _cleanup_free_ char *t = NULL;
11,986✔
228
        size_t k;
11,986✔
229
        char *ans;
11,986✔
230

231
        assert(pid >= 0);
11,986✔
232
        assert(ret);
11,986✔
233

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

248
        int full = pid_get_cmdline_nulstr(pid, max_columns, flags, &t, &k);
11,986✔
249
        if (full < 0)
11,986✔
250
                return full;
251

252
        if (flags & (PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_QUOTE_POSIX)) {
8,754✔
253
                ShellEscapeFlags shflags = SHELL_ESCAPE_EMPTY |
8,371✔
254
                        FLAGS_SET(flags, PROCESS_CMDLINE_QUOTE_POSIX) * SHELL_ESCAPE_POSIX;
8,371✔
255

256
                assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
8,371✔
257

258
                _cleanup_strv_free_ char **args = NULL;
8,371✔
259

260
                /* Drop trailing NULs, otherwise strv_parse_nulstr() adds additional empty strings at the end.
261
                 * See also issue #21186. */
262
                args = strv_parse_nulstr_full(t, k, /* drop_trailing_nuls = */ true);
8,371✔
263
                if (!args)
8,371✔
264
                        return -ENOMEM;
265

266
                ans = quote_command_line(args, shflags);
8,371✔
267
                if (!ans)
8,371✔
268
                        return -ENOMEM;
269
        } else {
270
                /* Arguments are separated by NULs. Let's replace those with spaces. */
271
                for (size_t i = 0; i < k - 1; i++)
18,828✔
272
                        if (t[i] == '\0')
18,445✔
273
                                t[i] = ' ';
705✔
274

275
                delete_trailing_chars(t, WHITESPACE);
383✔
276

277
                bool eight_bit = (flags & PROCESS_CMDLINE_USE_LOCALE) && !is_locale_utf8();
383✔
278

279
                ans = escape_non_printable_full(t, max_columns,
1,149✔
280
                                                eight_bit * XESCAPE_8_BIT | !full * XESCAPE_FORCE_ELLIPSIS);
712✔
281
                if (!ans)
383✔
282
                        return -ENOMEM;
283

284
                ans = str_realloc(ans);
383✔
285
        }
286

287
        *ret = ans;
8,754✔
288
        return 0;
8,754✔
289
}
290

291
int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
100✔
292
        _cleanup_free_ char *s = NULL;
100✔
293
        int r;
100✔
294

295
        if (!pidref_is_set(pid))
100✔
296
                return -ESRCH;
297

298
        if (pidref_is_remote(pid))
200✔
299
                return -EREMOTE;
300

301
        r = pid_get_cmdline(pid->pid, max_columns, flags, &s);
100✔
302
        if (r < 0)
100✔
303
                return r;
304

305
        r = pidref_verify(pid);
100✔
306
        if (r < 0)
100✔
307
                return r;
308

309
        if (ret)
100✔
310
                *ret = TAKE_PTR(s);
100✔
311
        return 0;
312
}
313

314
int pid_get_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) {
4,916✔
315
        _cleanup_free_ char *t = NULL;
4,916✔
316
        char **args;
4,916✔
317
        size_t k;
4,916✔
318
        int r;
4,916✔
319

320
        assert(pid >= 0);
4,916✔
321
        assert((flags & ~PROCESS_CMDLINE_COMM_FALLBACK) == 0);
4,916✔
322
        assert(ret);
4,916✔
323

324
        r = pid_get_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k);
4,916✔
325
        if (r < 0)
4,916✔
326
                return r;
327

328
        args = strv_parse_nulstr_full(t, k, /* drop_trailing_nuls = */ true);
4,846✔
329
        if (!args)
4,846✔
330
                return -ENOMEM;
331

332
        *ret = args;
4,846✔
333
        return 0;
4,846✔
334
}
335

336
int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char ***ret) {
×
337
        _cleanup_strv_free_ char **args = NULL;
×
338
        int r;
×
339

340
        if (!pidref_is_set(pid))
×
341
                return -ESRCH;
342

343
        if (pidref_is_remote(pid))
×
344
                return -EREMOTE;
345

346
        r = pid_get_cmdline_strv(pid->pid, flags, &args);
×
347
        if (r < 0)
×
348
                return r;
349

350
        r = pidref_verify(pid);
×
351
        if (r < 0)
×
352
                return r;
353

354
        if (ret)
×
355
                *ret = TAKE_PTR(args);
×
356

357
        return 0;
358
}
359

360
int container_get_leader(const char *machine, pid_t *pid) {
10✔
361
        _cleanup_free_ char *s = NULL, *class = NULL;
10✔
362
        const char *p;
10✔
363
        pid_t leader;
10✔
364
        int r;
10✔
365

366
        assert(machine);
10✔
367
        assert(pid);
10✔
368

369
        if (streq(machine, ".host")) {
10✔
370
                *pid = 1;
1✔
371
                return 0;
1✔
372
        }
373

374
        if (!hostname_is_valid(machine, 0))
9✔
375
                return -EINVAL;
376

377
        p = strjoina("/run/systemd/machines/", machine);
45✔
378
        r = parse_env_file(NULL, p,
9✔
379
                           "LEADER", &s,
380
                           "CLASS", &class);
381
        if (r == -ENOENT)
9✔
382
                return -EHOSTDOWN;
383
        if (r < 0)
9✔
384
                return r;
385
        if (!s)
9✔
386
                return -EIO;
387

388
        if (!streq_ptr(class, "container"))
9✔
389
                return -EIO;
390

391
        r = parse_pid(s, &leader);
9✔
392
        if (r < 0)
9✔
393
                return r;
394
        if (leader <= 1)
9✔
395
                return -EIO;
396

397
        *pid = leader;
9✔
398
        return 0;
9✔
399
}
400

401
int pid_is_kernel_thread(pid_t pid) {
13,482✔
402
        _cleanup_free_ char *line = NULL;
13,482✔
403
        unsigned long long flags;
13,482✔
404
        size_t l, i;
13,482✔
405
        const char *p;
13,482✔
406
        char *q;
13,482✔
407
        int r;
13,482✔
408

409
        if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
13,482✔
410
                return 0;
27✔
411
        if (!pid_is_valid(pid))
13,455✔
412
                return -EINVAL;
413

414
        p = procfs_file_alloca(pid, "stat");
13,455✔
415
        r = read_one_line_file(p, &line);
13,455✔
416
        if (r == -ENOENT)
13,455✔
417
                return -ESRCH;
418
        if (r < 0)
13,455✔
419
                return r;
420

421
        /* Skip past the comm field */
422
        q = strrchr(line, ')');
13,455✔
423
        if (!q)
13,455✔
424
                return -EINVAL;
425
        q++;
13,455✔
426

427
        /* Skip 6 fields to reach the flags field */
428
        for (i = 0; i < 6; i++) {
94,185✔
429
                l = strspn(q, WHITESPACE);
80,730✔
430
                if (l < 1)
80,730✔
431
                        return -EINVAL;
432
                q += l;
80,730✔
433

434
                l = strcspn(q, WHITESPACE);
80,730✔
435
                if (l < 1)
80,730✔
436
                        return -EINVAL;
437
                q += l;
80,730✔
438
        }
439

440
        /* Skip preceding whitespace */
441
        l = strspn(q, WHITESPACE);
13,455✔
442
        if (l < 1)
13,455✔
443
                return -EINVAL;
444
        q += l;
13,455✔
445

446
        /* Truncate the rest */
447
        l = strcspn(q, WHITESPACE);
13,455✔
448
        if (l < 1)
13,455✔
449
                return -EINVAL;
450
        q[l] = 0;
13,455✔
451

452
        r = safe_atollu(q, &flags);
13,455✔
453
        if (r < 0)
13,455✔
454
                return r;
455

456
        return !!(flags & PF_KTHREAD);
13,455✔
457
}
458

459
int pidref_is_kernel_thread(const PidRef *pid) {
7,226✔
460
        int result, r;
7,226✔
461

462
        if (!pidref_is_set(pid))
7,226✔
463
                return -ESRCH;
464

465
        if (pidref_is_remote(pid))
7,226✔
466
                return -EREMOTE;
467

468
        result = pid_is_kernel_thread(pid->pid);
7,226✔
469
        if (result < 0)
7,226✔
470
                return result;
471

472
        r = pidref_verify(pid); /* Verify that the PID wasn't reused since */
7,226✔
473
        if (r < 0)
7,226✔
474
                return r;
61✔
475

476
        return result;
477
}
478

479
static int get_process_link_contents(pid_t pid, const char *proc_file, char **ret) {
11,379✔
480
        const char *p;
11,379✔
481
        int r;
11,379✔
482

483
        assert(proc_file);
11,379✔
484

485
        p = procfs_file_alloca(pid, proc_file);
11,379✔
486

487
        r = readlink_malloc(p, ret);
11,379✔
488
        return (r == -ENOENT && proc_mounted() > 0) ? -ESRCH : r;
11,379✔
489
}
490

491
int get_process_exe(pid_t pid, char **ret) {
11,351✔
492
        char *d;
11,351✔
493
        int r;
11,351✔
494

495
        assert(pid >= 0);
11,351✔
496

497
        r = get_process_link_contents(pid, "exe", ret);
11,351✔
498
        if (r < 0)
11,351✔
499
                return r;
500

501
        if (ret) {
8,674✔
502
                d = endswith(*ret, " (deleted)");
8,674✔
503
                if (d)
8,674✔
504
                        *d = '\0';
×
505
        }
506

507
        return 0;
508
}
509

510
static int get_process_id(pid_t pid, const char *field, uid_t *ret) {
4,576✔
511
        _cleanup_fclose_ FILE *f = NULL;
4,576✔
512
        const char *p;
4,576✔
513
        int r;
4,576✔
514

515
        assert(field);
4,576✔
516
        assert(ret);
4,576✔
517

518
        if (pid < 0)
4,576✔
519
                return -EINVAL;
520

521
        p = procfs_file_alloca(pid, "status");
4,576✔
522
        r = fopen_unlocked(p, "re", &f);
4,576✔
523
        if (r == -ENOENT)
4,576✔
524
                return -ESRCH;
525
        if (r < 0)
350✔
526
                return r;
527

528
        for (;;) {
6,290✔
529
                _cleanup_free_ char *line = NULL;
3,320✔
530
                char *l;
3,320✔
531

532
                r = read_stripped_line(f, LONG_LINE_MAX, &line);
3,320✔
533
                if (r < 0)
3,320✔
534
                        return r;
535
                if (r == 0)
3,320✔
536
                        break;
537

538
                l = startswith(line, field);
3,320✔
539
                if (l) {
3,320✔
540
                        l += strspn(l, WHITESPACE);
350✔
541

542
                        l[strcspn(l, WHITESPACE)] = 0;
350✔
543

544
                        return parse_uid(l, ret);
350✔
545
                }
546
        }
547

548
        return -EIO;
×
549
}
550

551
int pid_get_uid(pid_t pid, uid_t *ret) {
2,295✔
552
        assert(ret);
2,295✔
553

554
        if (pid == 0 || pid == getpid_cached()) {
2,295✔
555
                *ret = getuid();
4✔
556
                return 0;
4✔
557
        }
558

559
        return get_process_id(pid, "Uid:", ret);
2,291✔
560
}
561

562
int pidref_get_uid(const PidRef *pid, uid_t *ret) {
192✔
563
        int r;
192✔
564

565
        if (!pidref_is_set(pid))
192✔
566
                return -ESRCH;
192✔
567

568
        if (pidref_is_remote(pid))
192✔
569
                return -EREMOTE;
570

571
        if (pid->fd >= 0) {
192✔
572
                r = pidfd_get_uid(pid->fd, ret);
192✔
573
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
192✔
574
                        return r;
575
        }
576

577
        uid_t uid;
9✔
578
        r = pid_get_uid(pid->pid, &uid);
9✔
579
        if (r < 0)
9✔
580
                return r;
581

582
        r = pidref_verify(pid);
9✔
583
        if (r < 0)
9✔
584
                return r;
585

586
        if (ret)
9✔
587
                *ret = uid;
9✔
588
        return 0;
589
}
590

591
int get_process_gid(pid_t pid, gid_t *ret) {
2,286✔
592

593
        if (pid == 0 || pid == getpid_cached()) {
2,286✔
594
                *ret = getgid();
1✔
595
                return 0;
1✔
596
        }
597

598
        assert_cc(sizeof(uid_t) == sizeof(gid_t));
2,285✔
599
        return get_process_id(pid, "Gid:", ret);
2,285✔
600
}
601

602
int get_process_cwd(pid_t pid, char **ret) {
14✔
603
        assert(pid >= 0);
14✔
604

605
        if (pid == 0 || pid == getpid_cached())
14✔
606
                return safe_getcwd(ret);
×
607

608
        return get_process_link_contents(pid, "cwd", ret);
14✔
609
}
610

611
int get_process_root(pid_t pid, char **ret) {
14✔
612
        assert(pid >= 0);
14✔
613
        return get_process_link_contents(pid, "root", ret);
14✔
614
}
615

616
#define ENVIRONMENT_BLOCK_MAX (5U*1024U*1024U)
617

618
int get_process_environ(pid_t pid, char **ret) {
16✔
619
        _cleanup_fclose_ FILE *f = NULL;
16✔
620
        _cleanup_free_ char *outcome = NULL;
16✔
621
        size_t sz = 0;
16✔
622
        const char *p;
16✔
623
        int r;
16✔
624

625
        assert(pid >= 0);
16✔
626
        assert(ret);
16✔
627

628
        p = procfs_file_alloca(pid, "environ");
16✔
629

630
        r = fopen_unlocked(p, "re", &f);
16✔
631
        if (r == -ENOENT)
16✔
632
                return -ESRCH;
633
        if (r < 0)
16✔
634
                return r;
635

636
        for (;;) {
6,908✔
637
                char c;
6,924✔
638

639
                if (sz >= ENVIRONMENT_BLOCK_MAX)
6,924✔
640
                        return -ENOBUFS;
×
641

642
                if (!GREEDY_REALLOC(outcome, sz + 5))
6,924✔
643
                        return -ENOMEM;
644

645
                r = safe_fgetc(f, &c);
6,924✔
646
                if (r < 0)
6,924✔
647
                        return r;
648
                if (r == 0)
6,924✔
649
                        break;
650

651
                if (c == '\0')
6,908✔
652
                        outcome[sz++] = '\n';
239✔
653
                else
654
                        sz += cescape_char(c, outcome + sz);
6,669✔
655
        }
656

657
        outcome[sz] = '\0';
16✔
658
        *ret = TAKE_PTR(outcome);
16✔
659

660
        return 0;
16✔
661
}
662

663
int pid_get_ppid(pid_t pid, pid_t *ret) {
1,351✔
664
        _cleanup_free_ char *line = NULL;
1,351✔
665
        unsigned long ppid;
1,351✔
666
        const char *p;
1,351✔
667
        int r;
1,351✔
668

669
        assert(pid >= 0);
1,351✔
670

671
        if (pid == 0)
1,351✔
672
                pid = getpid_cached();
1✔
673
        if (pid == 1) /* PID 1 has no parent, shortcut this case */
1,351✔
674
                return -EADDRNOTAVAIL;
675

676
        if (pid == getpid_cached()) {
1,347✔
677
                if (ret)
6✔
678
                        *ret = getppid();
6✔
679
                return 0;
6✔
680
        }
681

682
        p = procfs_file_alloca(pid, "stat");
1,341✔
683
        r = read_one_line_file(p, &line);
1,341✔
684
        if (r == -ENOENT)
1,341✔
685
                return -ESRCH;
686
        if (r < 0)
1,340✔
687
                return r;
688

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

692
        p = strrchr(line, ')');
1,340✔
693
        if (!p)
1,340✔
694
                return -EIO;
695
        p++;
1,340✔
696

697
        if (sscanf(p, " "
1,340✔
698
                   "%*c "  /* state */
699
                   "%lu ", /* ppid */
700
                   &ppid) != 1)
701
                return -EIO;
702

703
        /* If ppid is zero the process has no parent. Which might be the case for PID 1 (caught above)
704
         * but also for processes originating in other namespaces that are inserted into a pidns.
705
         * Return a recognizable error in this case. */
706
        if (ppid == 0)
1,340✔
707
                return -EADDRNOTAVAIL;
708

709
        if ((pid_t) ppid < 0 || (unsigned long) (pid_t) ppid != ppid)
1,340✔
710
                return -ERANGE;
711

712
        if (ret)
1,340✔
713
                *ret = (pid_t) ppid;
1,340✔
714

715
        return 0;
716
}
717

718
int pidref_get_ppid(const PidRef *pidref, pid_t *ret) {
3,568✔
719
        int r;
3,568✔
720

721
        if (!pidref_is_set(pidref))
3,568✔
722
                return -ESRCH;
3,568✔
723

724
        if (pidref_is_remote(pidref))
3,568✔
725
                return -EREMOTE;
726

727
        if (pidref->fd >= 0) {
3,568✔
728
                r = pidfd_get_ppid(pidref->fd, ret);
3,568✔
729
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
3,568✔
730
                        return r;
731
        }
732

733
        pid_t ppid;
1,345✔
734
        r = pid_get_ppid(pidref->pid, ret ? &ppid : NULL);
1,345✔
735
        if (r < 0)
1,345✔
736
                return r;
737

738
        r = pidref_verify(pidref);
1,344✔
739
        if (r < 0)
1,344✔
740
                return r;
741

742
        if (ret)
1,344✔
743
                *ret = ppid;
1,344✔
744
        return 0;
745
}
746

747
int pidref_get_ppid_as_pidref(const PidRef *pidref, PidRef *ret) {
17✔
748
        pid_t ppid;
17✔
749
        int r;
17✔
750

751
        assert(ret);
17✔
752

753
        r = pidref_get_ppid(pidref, &ppid);
17✔
754
        if (r < 0)
17✔
755
                return r;
17✔
756

757
        for (unsigned attempt = 0; attempt < 16; attempt++) {
16✔
758
                _cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
16✔
759

760
                r = pidref_set_pid(&parent, ppid);
16✔
761
                if (r < 0)
16✔
762
                        return r;
763

764
                /* If we have a pidfd of the original PID, let's verify that the process we acquired really
765
                 * is the parent still */
766
                if (pidref->fd >= 0) {
16✔
767
                        r = pidref_get_ppid(pidref, &ppid);
16✔
768
                        if (r < 0)
16✔
769
                                return r;
770

771
                        /* Did the PPID change since we queried it? if so we might have pinned the wrong
772
                         * process, if its PID got reused by now. Let's try again */
773
                        if (parent.pid != ppid)
16✔
774
                                continue;
×
775
                }
776

777
                *ret = TAKE_PIDREF(parent);
16✔
778
                return 0;
16✔
779
        }
780

781
        /* Give up after 16 tries */
782
        return -ENOTRECOVERABLE;
783
}
784

785
int pid_get_start_time(pid_t pid, usec_t *ret) {
628✔
786
        _cleanup_free_ char *line = NULL;
628✔
787
        const char *p;
628✔
788
        int r;
628✔
789

790
        assert(pid >= 0);
628✔
791

792
        p = procfs_file_alloca(pid, "stat");
628✔
793
        r = read_one_line_file(p, &line);
628✔
794
        if (r == -ENOENT)
628✔
795
                return -ESRCH;
796
        if (r < 0)
628✔
797
                return r;
798

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

802
        p = strrchr(line, ')');
628✔
803
        if (!p)
628✔
804
                return -EIO;
805
        p++;
628✔
806

807
        unsigned long llu;
628✔
808

809
        if (sscanf(p, " "
628✔
810
                   "%*c " /* state */
811
                   "%*u " /* ppid */
812
                   "%*u " /* pgrp */
813
                   "%*u " /* session */
814
                   "%*u " /* tty_nr */
815
                   "%*u " /* tpgid */
816
                   "%*u " /* flags */
817
                   "%*u " /* minflt */
818
                   "%*u " /* cminflt */
819
                   "%*u " /* majflt */
820
                   "%*u " /* cmajflt */
821
                   "%*u " /* utime */
822
                   "%*u " /* stime */
823
                   "%*u " /* cutime */
824
                   "%*u " /* cstime */
825
                   "%*i " /* priority */
826
                   "%*i " /* nice */
827
                   "%*u " /* num_threads */
828
                   "%*u " /* itrealvalue */
829
                   "%lu ", /* starttime */
830
                   &llu) != 1)
831
                return -EIO;
832

833
        if (ret)
628✔
834
                *ret = jiffies_to_usec(llu); /* CLOCK_BOOTTIME */
628✔
835

836
        return 0;
837
}
838

839
int pidref_get_start_time(const PidRef *pid, usec_t *ret) {
628✔
840
        usec_t t;
628✔
841
        int r;
628✔
842

843
        if (!pidref_is_set(pid))
628✔
844
                return -ESRCH;
628✔
845

846
        if (pidref_is_remote(pid))
628✔
847
                return -EREMOTE;
848

849
        r = pid_get_start_time(pid->pid, ret ? &t : NULL);
628✔
850
        if (r < 0)
628✔
851
                return r;
852

853
        r = pidref_verify(pid);
628✔
854
        if (r < 0)
628✔
855
                return r;
856

857
        if (ret)
628✔
858
                *ret = t;
628✔
859

860
        return 0;
861
}
862

863
int get_process_umask(pid_t pid, mode_t *ret) {
13,605✔
864
        _cleanup_free_ char *m = NULL;
13,605✔
865
        const char *p;
13,605✔
866
        int r;
13,605✔
867

868
        assert(pid >= 0);
13,605✔
869
        assert(ret);
13,605✔
870

871
        p = procfs_file_alloca(pid, "status");
13,605✔
872

873
        r = get_proc_field(p, "Umask", WHITESPACE, &m);
13,605✔
874
        if (r == -ENOENT)
13,605✔
875
                return -ESRCH;
876
        if (r < 0)
13,605✔
877
                return r;
878

879
        return parse_mode(m, ret);
13,605✔
880
}
881

882
int wait_for_terminate(pid_t pid, siginfo_t *status) {
9,722✔
883
        siginfo_t dummy;
9,722✔
884

885
        assert(pid >= 1);
9,722✔
886

887
        if (!status)
9,722✔
888
                status = &dummy;
91✔
889

890
        for (;;) {
9,722✔
891
                zero(*status);
9,722✔
892

893
                if (waitid(P_PID, pid, status, WEXITED) < 0) {
9,722✔
894

895
                        if (errno == EINTR)
×
896
                                continue;
×
897

898
                        return negative_errno();
×
899
                }
900

901
                return 0;
902
        }
903
}
904

905
/*
906
 * Return values:
907
 * < 0 : wait_for_terminate() failed to get the state of the
908
 *       process, the process was terminated by a signal, or
909
 *       failed for an unknown reason.
910
 * >=0 : The process terminated normally, and its exit code is
911
 *       returned.
912
 *
913
 * That is, success is indicated by a return value of zero, and an
914
 * error is indicated by a non-zero value.
915
 *
916
 * A warning is emitted if the process terminates abnormally,
917
 * and also if it returns non-zero unless check_exit_code is true.
918
 */
919
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
9,389✔
920
        _cleanup_free_ char *buffer = NULL;
9,389✔
921
        siginfo_t status;
9,389✔
922
        int r, prio;
9,389✔
923

924
        assert(pid > 1);
9,389✔
925

926
        if (!name) {
9,389✔
927
                r = pid_get_comm(pid, &buffer);
×
928
                if (r < 0)
×
929
                        log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid);
×
930
                else
931
                        name = buffer;
×
932
        }
933

934
        prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG;
9,389✔
935

936
        r = wait_for_terminate(pid, &status);
9,389✔
937
        if (r < 0)
9,389✔
938
                return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name));
×
939

940
        if (status.si_code == CLD_EXITED) {
9,389✔
941
                if (status.si_status != EXIT_SUCCESS)
9,389✔
942
                        log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
96✔
943
                                 "%s failed with exit status %i.", strna(name), status.si_status);
944
                else
945
                        log_debug("%s succeeded.", name);
9,341✔
946

947
                return status.si_status;
9,389✔
948

949
        } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) {
×
950

951
                log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status));
×
952
                return -EPROTO;
×
953
        }
954

955
        log_full(prio, "%s failed due to unknown reason.", strna(name));
9,389✔
956
        return -EPROTO;
957
}
958

959
/*
960
 * Return values:
961
 *
962
 * < 0 : wait_for_terminate_with_timeout() failed to get the state of the process, the process timed out, the process
963
 *       was terminated by a signal, or failed for an unknown reason.
964
 *
965
 * >=0 : The process terminated normally with no failures.
966
 *
967
 * Success is indicated by a return value of zero, a timeout is indicated by ETIMEDOUT, and all other child failure
968
 * states are indicated by error is indicated by a non-zero value.
969
 *
970
 * This call assumes SIGCHLD has been blocked already, in particular before the child to wait for has been forked off
971
 * to remain entirely race-free.
972
 */
973
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
×
974
        sigset_t mask;
×
975
        int r;
×
976
        usec_t until;
×
977

978
        assert_se(sigemptyset(&mask) == 0);
×
979
        assert_se(sigaddset(&mask, SIGCHLD) == 0);
×
980

981
        /* Drop into a sigtimewait-based timeout. Waiting for the
982
         * pid to exit. */
983
        until = usec_add(now(CLOCK_MONOTONIC), timeout);
×
984
        for (;;) {
×
985
                usec_t n;
×
986
                siginfo_t status = {};
×
987

988
                n = now(CLOCK_MONOTONIC);
×
989
                if (n >= until)
×
990
                        break;
991

992
                r = RET_NERRNO(sigtimedwait(&mask, NULL, TIMESPEC_STORE(until - n)));
×
993
                /* Assuming we woke due to the child exiting. */
994
                if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
×
995
                        if (status.si_pid == pid) {
×
996
                                /* This is the correct child. */
997
                                if (status.si_code == CLD_EXITED)
×
998
                                        return status.si_status == 0 ? 0 : -EPROTO;
×
999
                                else
1000
                                        return -EPROTO;
1001
                        }
1002
                }
1003
                /* Not the child, check for errors and proceed appropriately */
1004
                if (r < 0) {
×
1005
                        switch (r) {
×
1006
                        case -EAGAIN:
1007
                                /* Timed out, child is likely hung. */
1008
                                return -ETIMEDOUT;
1009
                        case -EINTR:
×
1010
                                /* Received a different signal and should retry */
1011
                                continue;
×
1012
                        default:
×
1013
                                /* Return any unexpected errors */
1014
                                return r;
×
1015
                        }
1016
                }
1017
        }
1018

1019
        return -EPROTO;
×
1020
}
1021

1022
void sigkill_wait(pid_t pid) {
31✔
1023
        assert(pid > 1);
31✔
1024

1025
        (void) kill(pid, SIGKILL);
31✔
1026
        (void) wait_for_terminate(pid, NULL);
31✔
1027
}
31✔
1028

1029
void sigkill_waitp(pid_t *pid) {
12,737✔
1030
        PROTECT_ERRNO;
12,737✔
1031

1032
        if (!pid)
12,737✔
1033
                return;
1034
        if (*pid <= 1)
12,737✔
1035
                return;
1036

1037
        sigkill_wait(*pid);
30✔
1038
}
1039

1040
void sigterm_wait(pid_t pid) {
58✔
1041
        assert(pid > 1);
58✔
1042

1043
        (void) kill_and_sigcont(pid, SIGTERM);
58✔
1044
        (void) wait_for_terminate(pid, NULL);
58✔
1045
}
58✔
1046

1047
void sigkill_nowait(pid_t pid) {
×
1048
        assert(pid > 1);
×
1049

1050
        (void) kill(pid, SIGKILL);
×
1051
}
×
1052

1053
void sigkill_nowaitp(pid_t *pid) {
×
1054
        PROTECT_ERRNO;
×
1055

1056
        if (!pid)
×
1057
                return;
1058
        if (*pid <= 1)
×
1059
                return;
1060

1061
        sigkill_nowait(*pid);
×
1062
}
1063

1064
int kill_and_sigcont(pid_t pid, int sig) {
58✔
1065
        int r;
58✔
1066

1067
        r = RET_NERRNO(kill(pid, sig));
58✔
1068

1069
        /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't
1070
         * affected by a process being suspended anyway. */
1071
        if (r >= 0 && !IN_SET(sig, SIGCONT, SIGKILL))
58✔
1072
                (void) kill(pid, SIGCONT);
58✔
1073

1074
        return r;
58✔
1075
}
1076

1077
int getenv_for_pid(pid_t pid, const char *field, char **ret) {
5,492✔
1078
        _cleanup_fclose_ FILE *f = NULL;
5,492✔
1079
        const char *path;
5,492✔
1080
        size_t sum = 0;
5,492✔
1081
        int r;
5,492✔
1082

1083
        assert(pid >= 0);
5,492✔
1084
        assert(field);
5,492✔
1085
        assert(ret);
5,492✔
1086

1087
        if (pid == 0 || pid == getpid_cached())
5,492✔
1088
                return strdup_to_full(ret, getenv(field));
13✔
1089

1090
        if (!pid_is_valid(pid))
5,479✔
1091
                return -EINVAL;
1092

1093
        path = procfs_file_alloca(pid, "environ");
5,479✔
1094

1095
        r = fopen_unlocked(path, "re", &f);
5,479✔
1096
        if (r == -ENOENT)
5,479✔
1097
                return -ESRCH;
1098
        if (r < 0)
4,963✔
1099
                return r;
1100

1101
        for (;;) {
67,299✔
1102
                _cleanup_free_ char *line = NULL;
31,943✔
1103
                const char *match;
35,358✔
1104

1105
                if (sum > ENVIRONMENT_BLOCK_MAX) /* Give up searching eventually */
35,358✔
1106
                        return -ENOBUFS;
1107

1108
                r = read_nul_string(f, LONG_LINE_MAX, &line);
35,358✔
1109
                if (r < 0)
35,358✔
1110
                        return r;
1111
                if (r == 0)  /* EOF */
35,358✔
1112
                        break;
1113

1114
                sum += r;
31,943✔
1115

1116
                match = startswith(line, field);
31,943✔
1117
                if (match && *match == '=')
31,943✔
1118
                        return strdup_to_full(ret, match + 1);
2✔
1119
        }
1120

1121
        *ret = NULL;
3,415✔
1122
        return 0;
3,415✔
1123
}
1124

1125
int pidref_is_my_child(PidRef *pid) {
3,534✔
1126
        int r;
3,534✔
1127

1128
        if (!pidref_is_set(pid))
3,534✔
1129
                return -ESRCH;
3,534✔
1130

1131
        if (pidref_is_remote(pid))
3,534✔
1132
                return -EREMOTE;
1133

1134
        if (pid->pid == 1 || pidref_is_self(pid))
3,534✔
1135
                return false;
×
1136

1137
        pid_t ppid;
3,534✔
1138
        r = pidref_get_ppid(pid, &ppid);
3,534✔
1139
        if (r == -EADDRNOTAVAIL) /* if this process is outside of our pidns, it is definitely not our child */
3,534✔
1140
                return false;
1141
        if (r < 0)
3,534✔
1142
                return r;
1143

1144
        return ppid == getpid_cached();
3,534✔
1145
}
1146

1147
int pid_is_my_child(pid_t pid) {
×
1148

1149
        if (pid == 0)
×
1150
                return false;
×
1151

1152
        return pidref_is_my_child(&PIDREF_MAKE_FROM_PID(pid));
×
1153
}
1154

1155
int pidref_is_unwaited(PidRef *pid) {
7,823✔
1156
        int r;
7,823✔
1157

1158
        /* Checks whether a PID is still valid at all, including a zombie */
1159

1160
        if (!pidref_is_set(pid))
7,823✔
1161
                return -ESRCH;
1162

1163
        if (pidref_is_remote(pid))
7,822✔
1164
                return -EREMOTE;
1165

1166
        if (pid->pid == 1 || pidref_is_self(pid))
7,822✔
1167
                return true;
9✔
1168

1169
        r = pidref_kill(pid, 0);
7,813✔
1170
        if (r == -ESRCH)
7,813✔
1171
                return false;
1172
        if (r < 0)
1,419✔
1173
                return r;
72✔
1174

1175
        return true;
1176
}
1177

1178
int pid_is_unwaited(pid_t pid) {
7,196✔
1179

1180
        if (pid == 0)
7,196✔
1181
                return true;
7,196✔
1182

1183
        return pidref_is_unwaited(&PIDREF_MAKE_FROM_PID(pid));
7,196✔
1184
}
1185

1186
int pid_is_alive(pid_t pid) {
7,169✔
1187
        int r;
7,169✔
1188

1189
        /* Checks whether a PID is still valid and not a zombie */
1190

1191
        if (pid < 0)
7,169✔
1192
                return -ESRCH;
1193

1194
        if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
7,168✔
1195
                return true;
1196

1197
        if (pid == getpid_cached())
7,168✔
1198
                return true;
1199

1200
        r = get_process_state(pid);
7,167✔
1201
        if (r == -ESRCH)
7,167✔
1202
                return false;
1203
        if (r < 0)
5,668✔
1204
                return r;
1205

1206
        return r != 'Z';
5,668✔
1207
}
1208

1209
int pidref_is_alive(const PidRef *pidref) {
7,164✔
1210
        int r, result;
7,164✔
1211

1212
        if (!pidref_is_set(pidref))
7,164✔
1213
                return -ESRCH;
1214

1215
        if (pidref_is_remote(pidref))
7,164✔
1216
                return -EREMOTE;
1217

1218
        result = pid_is_alive(pidref->pid);
7,164✔
1219
        if (result < 0) {
7,164✔
1220
                assert(result != -ESRCH);
×
1221
                return result;
1222
        }
1223

1224
        r = pidref_verify(pidref);
7,164✔
1225
        if (r == -ESRCH)
7,164✔
1226
                return false;
1227
        if (r < 0)
5,664✔
1228
                return r;
×
1229

1230
        return result;
1231
}
1232

1233
int pidref_from_same_root_fs(PidRef *a, PidRef *b) {
13,663✔
1234
        _cleanup_(pidref_done) PidRef self = PIDREF_NULL;
×
1235
        int r;
13,663✔
1236

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

1240
        if (!a || !b) {
13,663✔
1241
                r = pidref_set_self(&self);
13,642✔
1242
                if (r < 0)
13,642✔
1243
                        return r;
1244
                if (!a)
13,642✔
1245
                        a = &self;
×
1246
                if (!b)
13,642✔
1247
                        b = &self;
13,642✔
1248
        }
1249

1250
        if (!pidref_is_set(a) || !pidref_is_set(b))
13,663✔
1251
                return -ESRCH;
×
1252

1253
        /* If one of the two processes have the same root they cannot have the same root fs, but if both of
1254
         * them do we don't know */
1255
        if (pidref_is_remote(a) && pidref_is_remote(b))
13,663✔
1256
                return -EREMOTE;
1257
        if (pidref_is_remote(a) || pidref_is_remote(b))
40,989✔
1258
                return false;
1259

1260
        if (pidref_equal(a, b))
13,663✔
1261
                return true;
1262

1263
        const char *roota = procfs_file_alloca(a->pid, "root");
13,393✔
1264
        const char *rootb = procfs_file_alloca(b->pid, "root");
13,393✔
1265

1266
        int result = inode_same(roota, rootb, 0);
13,393✔
1267
        if (result == -ENOENT)
13,393✔
1268
                return proc_mounted() == 0 ? -ENOSYS : -ESRCH;
×
1269
        if (result < 0)
13,393✔
1270
                return result;
1271

1272
        r = pidref_verify(a);
13,281✔
1273
        if (r < 0)
13,281✔
1274
                return r;
1275
        r = pidref_verify(b);
13,281✔
1276
        if (r < 0)
13,281✔
1277
                return r;
×
1278

1279
        return result;
1280
}
1281

1282
bool is_main_thread(void) {
7,264,072✔
1283
        static thread_local int cached = -1;
7,264,072✔
1284

1285
        if (cached < 0)
7,264,072✔
1286
                cached = getpid_cached() == gettid();
70,206✔
1287

1288
        return cached;
7,264,072✔
1289
}
1290

1291
bool oom_score_adjust_is_valid(int oa) {
6,767✔
1292
        return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
6,767✔
1293
}
1294

1295
unsigned long personality_from_string(const char *p) {
9✔
1296
        Architecture architecture;
9✔
1297

1298
        if (!p)
9✔
1299
                return PERSONALITY_INVALID;
1300

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

1305
        architecture = architecture_from_string(p);
8✔
1306
        if (architecture < 0)
8✔
1307
                return PERSONALITY_INVALID;
1308

1309
        if (architecture == native_architecture())
6✔
1310
                return PER_LINUX;
1311
#ifdef ARCHITECTURE_SECONDARY
1312
        if (architecture == ARCHITECTURE_SECONDARY)
3✔
1313
                return PER_LINUX32;
2✔
1314
#endif
1315

1316
        return PERSONALITY_INVALID;
1317
}
1318

1319
const char* personality_to_string(unsigned long p) {
1,070✔
1320
        Architecture architecture = _ARCHITECTURE_INVALID;
1,070✔
1321

1322
        if (p == PER_LINUX)
1,070✔
1323
                architecture = native_architecture();
1324
#ifdef ARCHITECTURE_SECONDARY
1325
        else if (p == PER_LINUX32)
1,065✔
1326
                architecture = ARCHITECTURE_SECONDARY;
1327
#endif
1328

1329
        if (architecture < 0)
1330
                return NULL;
1331

1332
        return architecture_to_string(architecture);
7✔
1333
}
1334

1335
int safe_personality(unsigned long p) {
2,068✔
1336
        int ret;
2,068✔
1337

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

1345
        errno = 0;
2,068✔
1346
        ret = personality(p);
2,068✔
1347
        if (ret < 0) {
2,068✔
1348
                if (errno != 0)
12✔
1349
                        return -errno;
12✔
1350

1351
                errno = -ret;
×
1352
        }
1353

1354
        return ret;
1355
}
1356

1357
int opinionated_personality(unsigned long *ret) {
2,053✔
1358
        int current;
2,053✔
1359

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

1364
        current = safe_personality(PERSONALITY_INVALID);
2,053✔
1365
        if (current < 0)
2,053✔
1366
                return current;
1367

1368
        if (((unsigned long) current & OPINIONATED_PERSONALITY_MASK) == PER_LINUX32)
2,053✔
1369
                *ret = PER_LINUX32;
×
1370
        else
1371
                *ret = PER_LINUX;
2,053✔
1372

1373
        return 0;
1374
}
1375

1376
void valgrind_summary_hack(void) {
99✔
1377
#if HAVE_VALGRIND_VALGRIND_H
1378
        if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) {
1379
                pid_t pid;
1380
                pid = raw_clone(SIGCHLD);
1381
                if (pid < 0)
1382
                        log_struct_errno(
1383
                                LOG_EMERG, errno,
1384
                                "MESSAGE_ID=" SD_MESSAGE_VALGRIND_HELPER_FORK_STR,
1385
                                LOG_MESSAGE( "Failed to fork off valgrind helper: %m"));
1386
                else if (pid == 0)
1387
                        exit(EXIT_SUCCESS);
1388
                else {
1389
                        log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
1390
                        (void) wait_for_terminate(pid, NULL);
1391
                }
1392
        }
1393
#endif
1394
}
99✔
1395

1396
int pid_compare_func(const pid_t *a, const pid_t *b) {
1,372✔
1397
        /* Suitable for usage in qsort() */
1398
        return CMP(*a, *b);
1,372✔
1399
}
1400

1401
/* The cached PID, possible values:
1402
 *
1403
 *     == UNSET [0]  → cache not initialized yet
1404
 *     == BUSY [-1]  → some thread is initializing it at the moment
1405
 *     any other     → the cached PID
1406
 */
1407

1408
#define CACHED_PID_UNSET ((pid_t) 0)
1409
#define CACHED_PID_BUSY ((pid_t) -1)
1410

1411
static pid_t cached_pid = CACHED_PID_UNSET;
1412

1413
void reset_cached_pid(void) {
3,539✔
1414
        /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
1415
        cached_pid = CACHED_PID_UNSET;
3,539✔
1416
}
3,539✔
1417

1418
pid_t getpid_cached(void) {
80,204,526✔
1419
        static bool installed = false;
80,204,526✔
1420
        pid_t current_value = CACHED_PID_UNSET;
80,204,526✔
1421

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

1431
        (void) __atomic_compare_exchange_n(
80,204,526✔
1432
                        &cached_pid,
1433
                        &current_value,
1434
                        CACHED_PID_BUSY,
1435
                        false,
1436
                        __ATOMIC_SEQ_CST,
1437
                        __ATOMIC_SEQ_CST);
1438

1439
        switch (current_value) {
80,204,526✔
1440

1441
        case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */
1442
                pid_t new_pid;
120,011✔
1443

1444
                new_pid = raw_getpid();
120,011✔
1445

1446
                if (!installed) {
120,011✔
1447
                        /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's
1448
                         * only half-documented (glibc doesn't document it but LSB does — though only superficially)
1449
                         * we'll check for errors only in the most generic fashion possible. */
1450

1451
                        if (pthread_atfork(NULL, NULL, reset_cached_pid) != 0) {
92,785✔
1452
                                /* OOM? Let's try again later */
1453
                                cached_pid = CACHED_PID_UNSET;
×
1454
                                return new_pid;
×
1455
                        }
1456

1457
                        installed = true;
92,785✔
1458
                }
1459

1460
                cached_pid = new_pid;
120,011✔
1461
                return new_pid;
120,011✔
1462
        }
1463

1464
        case CACHED_PID_BUSY: /* Somebody else is currently initializing */
1465
                return raw_getpid();
×
1466

1467
        default: /* Properly initialized */
1468
                return current_value;
1469
        }
1470
}
1471

1472
int must_be_root(void) {
108✔
1473

1474
        if (geteuid() == 0)
108✔
1475
                return 0;
1476

1477
        return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root.");
×
1478
}
1479

1480
pid_t clone_with_nested_stack(int (*fn)(void *), int flags, void *userdata) {
4,282✔
1481
        size_t ps;
4,282✔
1482
        pid_t pid;
4,282✔
1483
        void *mystack;
4,282✔
1484

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

1493
        assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
4,282✔
1494
                         CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
1495

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

1503
        ps = page_size();
4,282✔
1504
        mystack = alloca(ps*3);
4,282✔
1505
        mystack = (uint8_t*) mystack + ps; /* move pointer one page ahead since stacks usually grow backwards */
4,282✔
1506
        mystack = (void*) ALIGN_TO((uintptr_t) mystack, ps); /* align to page size (moving things further ahead) */
4,282✔
1507

1508
#if HAVE_CLONE
1509
        pid = clone(fn, mystack, flags, userdata);
4,282✔
1510
#else
1511
        pid = __clone2(fn, mystack, ps, flags, userdata);
1512
#endif
1513
        if (pid < 0)
4,282✔
1514
                return -errno;
×
1515

1516
        return pid;
1517
}
1518

1519
static void restore_sigsetp(sigset_t **ssp) {
58,533✔
1520
        if (*ssp)
58,533✔
1521
                (void) sigprocmask(SIG_SETMASK, *ssp, NULL);
25,638✔
1522
}
58,533✔
1523

1524
static int fork_flags_to_signal(ForkFlags flags) {
26,439✔
1525
        return (flags & FORK_DEATHSIG_SIGTERM) ? SIGTERM :
26,439✔
1526
                (flags & FORK_DEATHSIG_SIGINT) ? SIGINT :
924✔
1527
                                                 SIGKILL;
1528
}
1529

1530
int pidref_safe_fork_full(
32,901✔
1531
                const char *name,
1532
                const int stdio_fds[3],
1533
                int except_fds[],
1534
                size_t n_except_fds,
1535
                ForkFlags flags,
1536
                PidRef *ret_pid) {
1537

1538
        pid_t original_pid, pid;
32,901✔
1539
        sigset_t saved_ss, ss;
32,901✔
1540
        _unused_ _cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
×
1541
        bool block_signals = false, block_all = false, intermediary = false;
32,901✔
1542
        _cleanup_close_pair_ int pidref_transport_fds[2] = EBADF_PAIR;
58,533✔
1543
        int prio, r;
32,901✔
1544

1545
        assert(!FLAGS_SET(flags, FORK_WAIT|FORK_FREEZE));
32,901✔
1546
        assert(!FLAGS_SET(flags, FORK_DETACH) ||
32,901✔
1547
               (flags & (FORK_WAIT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL)) == 0);
1548

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

1553
        prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG;
32,901✔
1554

1555
        original_pid = getpid_cached();
32,901✔
1556

1557
        if (flags & FORK_FLUSH_STDIO) {
32,901✔
1558
                fflush(stdout);
5✔
1559
                fflush(stderr); /* This one shouldn't be necessary, stderr should be unbuffered anyway, but let's better be safe than sorry */
5✔
1560
        }
1561

1562
        if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT)) {
32,901✔
1563
                /* We temporarily block all signals, so that the new child has them blocked initially. This
1564
                 * way, we can be sure that SIGTERMs are not lost we might send to the child. (Note that for
1565
                 * FORK_DEATHSIG_SIGKILL we don't bother, since it cannot be blocked anyway.) */
1566

1567
                assert_se(sigfillset(&ss) >= 0);
28,169✔
1568
                block_signals = block_all = true;
1569

1570
        } else if (flags & FORK_WAIT) {
4,732✔
1571
                /* Let's block SIGCHLD at least, so that we can safely watch for the child process */
1572

1573
                assert_se(sigemptyset(&ss) >= 0);
106✔
1574
                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
106✔
1575
                block_signals = true;
1576
        }
1577

1578
        if (block_signals) {
1579
                if (sigprocmask(SIG_BLOCK, &ss, &saved_ss) < 0)
28,275✔
1580
                        return log_full_errno(prio, errno, "Failed to block signal mask: %m");
×
1581
                saved_ssp = &saved_ss;
28,275✔
1582
        }
1583

1584
        if (FLAGS_SET(flags, FORK_DETACH)) {
32,901✔
1585
                /* Fork off intermediary child if needed */
1586

1587
                r = is_reaper_process();
200✔
1588
                if (r < 0)
200✔
1589
                        return log_full_errno(prio, r, "Failed to determine if we are a reaper process: %m");
×
1590

1591
                if (!r) {
200✔
1592
                        /* Not a reaper process, hence do a double fork() so we are reparented to one */
1593

1594
                        if (ret_pid && socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pidref_transport_fds) < 0)
10✔
1595
                                return log_full_errno(prio, errno, "Failed to allocate pidref socket: %m");
×
1596

1597
                        pid = fork();
10✔
1598
                        if (pid < 0)
26✔
1599
                                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
×
1600
                        if (pid > 0) {
26✔
1601
                                log_debug("Successfully forked off intermediary '%s' as PID " PID_FMT ".", strna(name), pid);
10✔
1602

1603
                                pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
10✔
1604

1605
                                if (pidref_transport_fds[0] >= 0) {
10✔
1606
                                        /* Wait for the intermediary child to exit so the caller can be certain the actual child
1607
                                         * process has been reparented by the time this function returns. */
1608
                                        r = wait_for_terminate_and_check(name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
16✔
1609
                                        if (r < 0)
8✔
1610
                                                return log_full_errno(prio, r, "Failed to wait for intermediary process: %m");
×
1611
                                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
8✔
1612
                                                return -EPROTO;
1613

1614
                                        int pidfd;
8✔
1615
                                        ssize_t n = receive_one_fd_iov(
16✔
1616
                                                        pidref_transport_fds[0],
1617
                                                        &IOVEC_MAKE(&pid, sizeof(pid)),
8✔
1618
                                                        /* iovlen= */ 1,
1619
                                                        /* flags= */ 0,
1620
                                                        &pidfd);
1621
                                        if (n < 0)
8✔
1622
                                                return log_full_errno(prio, n, "Failed to receive child pidref: %m");
×
1623

1624
                                        *ret_pid = (PidRef) { .pid = pid, .fd = pidfd };
8✔
1625
                                }
1626

1627
                                return 1; /* return in the parent */
10✔
1628
                        }
1629

1630
                        pidref_transport_fds[0] = safe_close(pidref_transport_fds[0]);
16✔
1631
                        intermediary = true;
16✔
1632
                }
1633
        }
1634

1635
        if ((flags & (FORK_NEW_MOUNTNS|FORK_NEW_USERNS|FORK_NEW_NETNS|FORK_NEW_PIDNS)) != 0)
32,907✔
1636
                pid = raw_clone(SIGCHLD|
11,081✔
1637
                                (FLAGS_SET(flags, FORK_NEW_MOUNTNS) ? CLONE_NEWNS : 0) |
11,081✔
1638
                                (FLAGS_SET(flags, FORK_NEW_USERNS) ? CLONE_NEWUSER : 0) |
11,081✔
1639
                                (FLAGS_SET(flags, FORK_NEW_NETNS) ? CLONE_NEWNET : 0) |
11,081✔
1640
                                (FLAGS_SET(flags, FORK_NEW_PIDNS) ? CLONE_NEWPID : 0));
11,081✔
1641
        else
1642
                pid = fork();
21,826✔
1643
        if (pid < 0)
58,533✔
1644
                return log_full_errno(prio, errno, "Failed to fork off '%s': %m", strna(name));
2✔
1645
        if (pid > 0) {
58,532✔
1646

1647
                /* If we are in the intermediary process, exit now */
1648
                if (intermediary) {
30,263✔
1649
                        if (pidref_transport_fds[1] >= 0) {
10✔
1650
                                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
8✔
1651

1652
                                r = pidref_set_pid(&pidref, pid);
8✔
1653
                                if (r < 0) {
8✔
1654
                                        log_full_errno(prio, r, "Failed to open reference to PID "PID_FMT": %m", pid);
×
1655
                                        _exit(EXIT_FAILURE);
×
1656
                                }
1657

1658
                                r = send_one_fd_iov(
8✔
1659
                                                pidref_transport_fds[1],
1660
                                                pidref.fd,
1661
                                                &IOVEC_MAKE(&pidref.pid, sizeof(pidref.pid)),
1662
                                                /* iovlen= */ 1,
1663
                                                /* flags= */ 0);
1664
                                if (r < 0) {
8✔
1665
                                        log_full_errno(prio, r, "Failed to send child pidref: %m");
×
1666
                                        _exit(EXIT_FAILURE);
×
1667
                                }
1668
                        }
1669

1670
                        _exit(EXIT_SUCCESS);
10✔
1671
                }
1672

1673
                /* We are in the parent process */
1674
                log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
30,253✔
1675

1676
                if (flags & FORK_WAIT) {
30,253✔
1677
                        if (block_all) {
3,656✔
1678
                                /* undo everything except SIGCHLD */
1679
                                ss = saved_ss;
3,550✔
1680
                                assert_se(sigaddset(&ss, SIGCHLD) >= 0);
3,550✔
1681
                                (void) sigprocmask(SIG_SETMASK, &ss, NULL);
3,550✔
1682
                        }
1683

1684
                        r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
6,894✔
1685
                        if (r < 0)
3,656✔
1686
                                return r;
1687
                        if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
3,656✔
1688
                                return -EPROTO;
1689

1690
                        /* If we are in the parent and successfully waited, then the process doesn't exist anymore. */
1691
                        if (ret_pid)
3,656✔
1692
                                *ret_pid = PIDREF_NULL;
5✔
1693

1694
                        return 1;
3,656✔
1695
                }
1696

1697
                if (ret_pid) {
26,597✔
1698
                        if (FLAGS_SET(flags, FORK_PID_ONLY))
26,098✔
1699
                                *ret_pid = PIDREF_MAKE_FROM_PID(pid);
21,813✔
1700
                        else {
1701
                                r = pidref_set_pid(ret_pid, pid);
4,285✔
1702
                                if (r < 0) /* Let's not fail for this, no matter what, the process exists after all, and that's key */
4,285✔
1703
                                        *ret_pid = PIDREF_MAKE_FROM_PID(pid);
×
1704
                        }
1705
                }
1706

1707
                return 1;
26,597✔
1708
        }
1709

1710
        /* We are in the child process */
1711

1712
        pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
28,269✔
1713

1714
        /* Restore signal mask manually */
1715
        saved_ssp = NULL;
28,269✔
1716

1717
        if (flags & FORK_REOPEN_LOG) {
28,269✔
1718
                /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
1719
                log_close();
3,252✔
1720
                log_set_open_when_needed(true);
3,252✔
1721
                log_settle_target();
3,252✔
1722
        }
1723

1724
        if (name) {
28,269✔
1725
                r = rename_process(name);
28,269✔
1726
                if (r < 0)
28,269✔
1727
                        log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG,
×
1728
                                       r, "Failed to rename process, ignoring: %m");
1729
        }
1730

1731
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL))
28,269✔
1732
                if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) {
26,439✔
1733
                        log_full_errno(prio, errno, "Failed to set death signal: %m");
×
1734
                        _exit(EXIT_FAILURE);
×
1735
                }
1736

1737
        if (flags & FORK_RESET_SIGNALS) {
28,269✔
1738
                r = reset_all_signal_handlers();
20,437✔
1739
                if (r < 0) {
20,437✔
1740
                        log_full_errno(prio, r, "Failed to reset signal handlers: %m");
×
1741
                        _exit(EXIT_FAILURE);
×
1742
                }
1743

1744
                /* This implicitly undoes the signal mask stuff we did before the fork()ing above */
1745
                r = reset_signal_mask();
20,437✔
1746
                if (r < 0) {
20,437✔
1747
                        log_full_errno(prio, r, "Failed to reset signal mask: %m");
×
1748
                        _exit(EXIT_FAILURE);
×
1749
                }
1750
        } else if (block_signals) { /* undo what we did above */
7,832✔
1751
                if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
7,508✔
1752
                        log_full_errno(prio, errno, "Failed to restore signal mask: %m");
×
1753
                        _exit(EXIT_FAILURE);
×
1754
                }
1755
        }
1756

1757
        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL|FORK_DEATHSIG_SIGINT)) {
28,269✔
1758
                pid_t ppid;
26,439✔
1759
                /* Let's see if the parent PID is still the one we started from? If not, then the parent
1760
                 * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
1761

1762
                ppid = getppid();
26,439✔
1763
                if (ppid == 0)
26,439✔
1764
                        /* Parent is in a different PID namespace. */;
1765
                else if (ppid != original_pid) {
26,401✔
1766
                        int sig = fork_flags_to_signal(flags);
×
1767
                        log_debug("Parent died early, raising %s.", signal_to_string(sig));
×
1768
                        (void) raise(sig);
×
1769
                        _exit(EXIT_FAILURE);
×
1770
                }
1771
        }
1772

1773
        if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) {
28,269✔
1774
                /* Optionally, make sure we never propagate mounts to the host. */
1775
                if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
102✔
1776
                        log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
×
1777
                        _exit(EXIT_FAILURE);
×
1778
                }
1779
        }
1780

1781
        if (FLAGS_SET(flags, FORK_PRIVATE_TMP)) {
28,269✔
1782
                assert(FLAGS_SET(flags, FORK_NEW_MOUNTNS));
×
1783

1784
                /* Optionally, overmount new tmpfs instance on /tmp/. */
1785
                r = mount_nofollow("tmpfs", "/tmp", "tmpfs",
×
1786
                                   MS_NOSUID|MS_NODEV,
1787
                                   "mode=01777" TMPFS_LIMITS_RUN);
1788
                if (r < 0) {
×
1789
                        log_full_errno(prio, r, "Failed to overmount /tmp/: %m");
×
1790
                        _exit(EXIT_FAILURE);
×
1791
                }
1792
        }
1793

1794
        if (flags & FORK_REARRANGE_STDIO) {
28,269✔
1795
                if (stdio_fds) {
13,635✔
1796
                        r = rearrange_stdio(stdio_fds[0], stdio_fds[1], stdio_fds[2]);
13,628✔
1797
                        if (r < 0) {
13,628✔
1798
                                log_full_errno(prio, r, "Failed to rearrange stdio fds: %m");
×
1799
                                _exit(EXIT_FAILURE);
×
1800
                        }
1801

1802
                        /* Turn off O_NONBLOCK on the fdio fds, in case it was left on */
1803
                        stdio_disable_nonblock();
13,628✔
1804
                } else {
1805
                        r = make_null_stdio();
7✔
1806
                        if (r < 0) {
7✔
1807
                                log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
×
1808
                                _exit(EXIT_FAILURE);
×
1809
                        }
1810
                }
1811
        } else if (flags & FORK_STDOUT_TO_STDERR) {
14,634✔
1812
                if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
2✔
1813
                        log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
×
1814
                        _exit(EXIT_FAILURE);
×
1815
                }
1816
        }
1817

1818
        if (flags & FORK_CLOSE_ALL_FDS) {
28,269✔
1819
                /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
1820
                log_close();
19,906✔
1821

1822
                r = close_all_fds(except_fds, n_except_fds);
19,906✔
1823
                if (r < 0) {
19,906✔
1824
                        log_full_errno(prio, r, "Failed to close all file descriptors: %m");
×
1825
                        _exit(EXIT_FAILURE);
×
1826
                }
1827
        }
1828

1829
        if (flags & FORK_PACK_FDS) {
28,269✔
1830
                /* FORK_CLOSE_ALL_FDS ensures that except_fds are the only FDs >= 3 that are
1831
                 * open, this is including the log. This is required by pack_fds, which will
1832
                 * get stuck in an infinite loop of any FDs other than except_fds are open. */
1833
                assert(FLAGS_SET(flags, FORK_CLOSE_ALL_FDS));
62✔
1834

1835
                r = pack_fds(except_fds, n_except_fds);
62✔
1836
                if (r < 0) {
62✔
1837
                        log_full_errno(prio, r, "Failed to pack file descriptors: %m");
×
1838
                        _exit(EXIT_FAILURE);
×
1839
                }
1840
        }
1841

1842
        if (flags & FORK_CLOEXEC_OFF) {
28,269✔
1843
                r = fd_cloexec_many(except_fds, n_except_fds, false);
68✔
1844
                if (r < 0) {
68✔
1845
                        log_full_errno(prio, r, "Failed to turn off O_CLOEXEC on file descriptors: %m");
×
1846
                        _exit(EXIT_FAILURE);
×
1847
                }
1848
        }
1849

1850
        /* When we were asked to reopen the logs, do so again now */
1851
        if (flags & FORK_REOPEN_LOG) {
28,269✔
1852
                log_open();
3,252✔
1853
                log_set_open_when_needed(false);
3,252✔
1854
        }
1855

1856
        if (flags & FORK_RLIMIT_NOFILE_SAFE) {
28,269✔
1857
                r = rlimit_nofile_safe();
14,880✔
1858
                if (r < 0) {
14,880✔
1859
                        log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
×
1860
                        _exit(EXIT_FAILURE);
×
1861
                }
1862
        }
1863

1864
        if (!FLAGS_SET(flags, FORK_KEEP_NOTIFY_SOCKET)) {
28,269✔
1865
                r = RET_NERRNO(unsetenv("NOTIFY_SOCKET"));
28,269✔
1866
                if (r < 0) {
×
1867
                        log_full_errno(prio, r, "Failed to unset $NOTIFY_SOCKET: %m");
×
1868
                        _exit(EXIT_FAILURE);
×
1869
                }
1870
        }
1871

1872
        if (FLAGS_SET(flags, FORK_FREEZE))
28,269✔
1873
                freeze();
×
1874

1875
        if (ret_pid) {
28,269✔
1876
                if (FLAGS_SET(flags, FORK_PID_ONLY))
23,336✔
1877
                        *ret_pid = PIDREF_MAKE_FROM_PID(getpid_cached());
23,188✔
1878
                else {
1879
                        r = pidref_set_self(ret_pid);
148✔
1880
                        if (r < 0) {
148✔
1881
                                log_full_errno(prio, r, "Failed to acquire PID reference on ourselves: %m");
×
1882
                                _exit(EXIT_FAILURE);
×
1883
                        }
1884
                }
1885
        }
1886

1887
        return 0;
1888
}
1889

1890
int safe_fork_full(
28,605✔
1891
                const char *name,
1892
                const int stdio_fds[3],
1893
                int except_fds[],
1894
                size_t n_except_fds,
1895
                ForkFlags flags,
1896
                pid_t *ret_pid) {
1897

1898
        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
54,090✔
1899
        int r;
28,605✔
1900

1901
        /* Getting the detached child process pid without pidfd is racy, so don't allow it if not returning
1902
         * a pidref to the caller. */
1903
        assert(!FLAGS_SET(flags, FORK_DETACH) || !ret_pid);
28,605✔
1904

1905
        r = pidref_safe_fork_full(name, stdio_fds, except_fds, n_except_fds, flags|FORK_PID_ONLY, ret_pid ? &pidref : NULL);
35,066✔
1906
        if (r < 0 || !ret_pid)
54,090✔
1907
                return r;
1908

1909
        *ret_pid = pidref.pid;
45,004✔
1910

1911
        return r;
45,004✔
1912
}
1913

1914
int namespace_fork(
167✔
1915
                const char *outer_name,
1916
                const char *inner_name,
1917
                int except_fds[],
1918
                size_t n_except_fds,
1919
                ForkFlags flags,
1920
                int pidns_fd,
1921
                int mntns_fd,
1922
                int netns_fd,
1923
                int userns_fd,
1924
                int root_fd,
1925
                pid_t *ret_pid) {
1926

1927
        int r;
167✔
1928

1929
        /* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle
1930
         * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
1931
         * /proc/self/fd works correctly. */
1932

1933
        r = safe_fork_full(outer_name,
489✔
1934
                           NULL,
1935
                           except_fds, n_except_fds,
1936
                           (flags|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
167✔
1937
        if (r < 0)
322✔
1938
                return r;
1939
        if (r == 0) {
322✔
1940
                pid_t pid;
155✔
1941

1942
                /* Child */
1943

1944
                r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
155✔
1945
                if (r < 0) {
155✔
1946
                        log_full_errno(FLAGS_SET(flags, FORK_LOG) ? LOG_ERR : LOG_DEBUG, r, "Failed to join namespace: %m");
×
1947
                        _exit(EXIT_FAILURE);
×
1948
                }
1949

1950
                /* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */
1951
                r = safe_fork_full(inner_name,
466✔
1952
                                   NULL,
1953
                                   except_fds, n_except_fds,
1954
                                   flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO), &pid);
155✔
1955
                if (r < 0)
311✔
1956
                        _exit(EXIT_FAILURE);
×
1957
                if (r == 0) {
311✔
1958
                        /* Child */
1959
                        if (ret_pid)
156✔
1960
                                *ret_pid = pid;
156✔
1961
                        return 0;
156✔
1962
                }
1963

1964
                r = wait_for_terminate_and_check(inner_name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
310✔
1965
                if (r < 0)
155✔
1966
                        _exit(EXIT_FAILURE);
×
1967

1968
                _exit(r);
155✔
1969
        }
1970

1971
        return 1;
1972
}
1973

1974
int set_oom_score_adjust(int value) {
4,952✔
1975
        char t[DECIMAL_STR_MAX(int)];
4,952✔
1976

1977
        if (!oom_score_adjust_is_valid(value))
4,952✔
1978
                return -EINVAL;
4,952✔
1979

1980
        xsprintf(t, "%i", value);
4,952✔
1981

1982
        return write_string_file("/proc/self/oom_score_adj", t,
4,952✔
1983
                                 WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
1984
}
1985

1986
int get_oom_score_adjust(int *ret) {
885✔
1987
        _cleanup_free_ char *t = NULL;
885✔
1988
        int r, a;
885✔
1989

1990
        r = read_virtual_file("/proc/self/oom_score_adj", SIZE_MAX, &t, NULL);
885✔
1991
        if (r < 0)
885✔
1992
                return r;
1993

1994
        delete_trailing_chars(t, WHITESPACE);
885✔
1995

1996
        r = safe_atoi(t, &a);
885✔
1997
        if (r < 0)
885✔
1998
                return r;
1999

2000
        if (!oom_score_adjust_is_valid(a))
885✔
2001
                return -ENODATA;
2002

2003
        if (ret)
885✔
2004
                *ret = a;
885✔
2005

2006
        return 0;
2007
}
2008

2009
static int rlimit_to_nice(rlim_t limit) {
2✔
2010
        if (limit <= 1)
2✔
2011
                return PRIO_MAX-1; /* i.e. 19 */
2012

2013
        if (limit >= -PRIO_MIN + PRIO_MAX)
2✔
2014
                return PRIO_MIN; /* i.e. -20 */
2015

2016
        return PRIO_MAX - (int) limit;
2✔
2017
}
2018

2019
int setpriority_closest(int priority) {
24✔
2020
        struct rlimit highest;
24✔
2021
        int r, current, limit;
24✔
2022

2023
        /* Try to set requested nice level */
2024
        r = RET_NERRNO(setpriority(PRIO_PROCESS, 0, priority));
24✔
2025
        if (r >= 0)
2✔
2026
                return 1;
22✔
2027
        if (!ERRNO_IS_NEG_PRIVILEGE(r))
2✔
2028
                return r;
2029

2030
        errno = 0;
2✔
2031
        current = getpriority(PRIO_PROCESS, 0);
2✔
2032
        if (errno != 0)
2✔
2033
                return -errno;
×
2034

2035
        if (priority == current)
2✔
2036
                return 1;
2037

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

2044
        if (getrlimit(RLIMIT_NICE, &highest) < 0)
2✔
2045
                return -errno;
×
2046

2047
        limit = rlimit_to_nice(highest.rlim_cur);
2✔
2048

2049
        /* Push to the allowed limit if we're higher than that. Note that we could also be less nice than
2050
         * limit allows us, but still higher than what's requested. In that case our current value is
2051
         * the best choice. */
2052
        if (current > limit)
2✔
2053
                if (setpriority(PRIO_PROCESS, 0, limit) < 0)
2✔
2054
                        return -errno;
×
2055

2056
        log_debug("Cannot set requested nice level (%i), using next best (%i).", priority, MIN(current, limit));
2✔
2057
        return 0;
2058
}
2059

2060
_noreturn_ void freeze(void) {
×
2061
        log_close();
×
2062

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

2068
        /* Let's not freeze right away, but keep reaping zombies. */
2069
        for (;;) {
×
2070
                siginfo_t si = {};
×
2071

2072
                if (waitid(P_ALL, 0, &si, WEXITED) < 0 && errno != EINTR)
×
2073
                        break;
2074
        }
2075

2076
        /* waitid() failed with an ECHLD error (because there are no left-over child processes) or any other
2077
         * (unexpected) error. Freeze for good now! */
2078
        for (;;)
×
2079
                pause();
×
2080
}
2081

2082
int get_process_threads(pid_t pid) {
7✔
2083
        _cleanup_free_ char *t = NULL;
7✔
2084
        const char *p;
7✔
2085
        int n, r;
7✔
2086

2087
        if (pid < 0)
7✔
2088
                return -EINVAL;
2089

2090
        p = procfs_file_alloca(pid, "status");
7✔
2091

2092
        r = get_proc_field(p, "Threads", WHITESPACE, &t);
7✔
2093
        if (r == -ENOENT)
7✔
2094
                return proc_mounted() == 0 ? -ENOSYS : -ESRCH;
×
2095
        if (r < 0)
7✔
2096
                return r;
2097

2098
        r = safe_atoi(t, &n);
7✔
2099
        if (r < 0)
7✔
2100
                return r;
2101
        if (n < 0)
7✔
2102
                return -EINVAL;
×
2103

2104
        return n;
2105
}
2106

2107
int is_reaper_process(void) {
4,486✔
2108
        int b = 0;
4,486✔
2109

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

2113
        if (getpid_cached() == 1)
4,486✔
2114
                return true;
4,486✔
2115

2116
        if (prctl(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0UL, 0UL, 0UL) < 0)
272✔
2117
                return -errno;
×
2118

2119
        return b != 0;
272✔
2120
}
2121

2122
int make_reaper_process(bool b) {
700✔
2123

2124
        if (getpid_cached() == 1) {
700✔
2125

2126
                if (!b)
112✔
2127
                        return -EINVAL;
2128

2129
                return 0;
112✔
2130
        }
2131

2132
        /* Some prctl()s insist that all 5 arguments are specified, others do not. Let's always specify all,
2133
         * to avoid any ambiguities */
2134
        if (prctl(PR_SET_CHILD_SUBREAPER, (unsigned long) b, 0UL, 0UL, 0UL) < 0)
588✔
2135
                return -errno;
×
2136

2137
        return 0;
2138
}
2139

2140
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(posix_spawnattr_t*, posix_spawnattr_destroy, NULL);
×
2141

2142
int posix_spawn_wrapper(
3,821✔
2143
                const char *path,
2144
                char * const *argv,
2145
                char * const *envp,
2146
                const char *cgroup,
2147
                PidRef *ret_pidref) {
2148

2149
        short flags = POSIX_SPAWN_SETSIGMASK;
3,821✔
2150
        posix_spawnattr_t attr;
3,821✔
2151
        sigset_t mask;
3,821✔
2152
        int r;
3,821✔
2153

2154
        /* Forks and invokes 'path' with 'argv' and 'envp' using CLONE_VM and CLONE_VFORK, which means the
2155
         * caller will be blocked until the child either exits or exec's. The memory of the child will be
2156
         * fully shared with the memory of the parent, so that there are no copy-on-write or memory.max
2157
         * issues.
2158
         *
2159
         * Also, move the newly-created process into 'cgroup' through POSIX_SPAWN_SETCGROUP (clone3())
2160
         * if available.
2161
         * returns 1: We're already in the right cgroup
2162
         *         0: 'cgroup' not specified or POSIX_SPAWN_SETCGROUP is not supported. The caller
2163
         *            needs to call 'cg_attach' on their own */
2164

2165
        assert(path);
3,821✔
2166
        assert(argv);
3,821✔
2167
        assert(ret_pidref);
3,821✔
2168

2169
        assert_se(sigfillset(&mask) >= 0);
3,821✔
2170

2171
        r = posix_spawnattr_init(&attr);
3,821✔
2172
        if (r != 0)
3,821✔
2173
                return -r; /* These functions return a positive errno on failure */
3,821✔
2174

2175
        /* Initialization needs to succeed before we can set up a destructor. */
2176
        _unused_ _cleanup_(posix_spawnattr_destroyp) posix_spawnattr_t *attr_destructor = &attr;
7,642✔
2177

2178
#if HAVE_PIDFD_SPAWN
2179
        static bool have_clone_into_cgroup = true; /* kernel 5.7+ */
3,821✔
2180
        _cleanup_close_ int cgroup_fd = -EBADF;
3,821✔
2181

2182
        if (cgroup && have_clone_into_cgroup) {
3,821✔
2183
                _cleanup_free_ char *resolved_cgroup = NULL;
3,821✔
2184

2185
                r = cg_get_path_and_check(
3,821✔
2186
                                SYSTEMD_CGROUP_CONTROLLER,
2187
                                cgroup,
2188
                                /* suffix= */ NULL,
2189
                                &resolved_cgroup);
2190
                if (r < 0)
3,821✔
2191
                        return r;
2192

2193
                cgroup_fd = open(resolved_cgroup, O_PATH|O_DIRECTORY|O_CLOEXEC);
3,821✔
2194
                if (cgroup_fd < 0)
3,821✔
2195
                        return -errno;
×
2196

2197
                r = posix_spawnattr_setcgroup_np(&attr, cgroup_fd);
3,821✔
2198
                if (r != 0)
3,821✔
2199
                        return -r;
×
2200

2201
                flags |= POSIX_SPAWN_SETCGROUP;
3,821✔
2202
        }
2203
#endif
2204

2205
        r = posix_spawnattr_setflags(&attr, flags);
3,821✔
2206
        if (r != 0)
3,821✔
2207
                return -r;
×
2208
        r = posix_spawnattr_setsigmask(&attr, &mask);
3,821✔
2209
        if (r != 0)
3,821✔
2210
                return -r;
×
2211

2212
#if HAVE_PIDFD_SPAWN
2213
        _cleanup_close_ int pidfd = -EBADF;
3,821✔
2214

2215
        r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
3,821✔
2216
        if (ERRNO_IS_NOT_SUPPORTED(r) && FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP) && cg_is_threaded(cgroup) > 0)
3,821✔
2217
                return -EUCLEAN; /* clone3() could also return EOPNOTSUPP if the target cgroup is in threaded mode,
2218
                                    turn that into something recognizable */
2219
        if ((ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || r == E2BIG) &&
3,821✔
2220
            FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP)) {
2221
                /* Compiled on a newer host, or seccomp&friends blocking clone3()? Fallback, but
2222
                 * need to disable POSIX_SPAWN_SETCGROUP, which is what redirects to clone3().
2223
                 * Note that we might get E2BIG here since some kernels (e.g. 5.4) support clone3()
2224
                 * but not CLONE_INTO_CGROUP. */
2225

2226
                /* CLONE_INTO_CGROUP definitely won't work, hence remember the fact so that we don't
2227
                 * retry every time. */
2228
                have_clone_into_cgroup = false;
×
2229

2230
                flags &= ~POSIX_SPAWN_SETCGROUP;
×
2231
                r = posix_spawnattr_setflags(&attr, flags);
×
2232
                if (r != 0)
×
2233
                        return -r;
×
2234

2235
                r = pidfd_spawn(&pidfd, path, NULL, &attr, argv, envp);
×
2236
        }
2237
        if (r != 0)
3,821✔
2238
                return -r;
×
2239

2240
        r = pidref_set_pidfd_consume(ret_pidref, TAKE_FD(pidfd));
3,821✔
2241
        if (r < 0)
3,821✔
2242
                return r;
2243

2244
        return FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP);
3,821✔
2245
#else
2246
        pid_t pid;
2247

2248
        r = posix_spawn(&pid, path, NULL, &attr, argv, envp);
2249
        if (r != 0)
2250
                return -r;
2251

2252
        r = pidref_set_pid(ret_pidref, pid);
2253
        if (r < 0)
2254
                return r;
2255

2256
        return 0; /* We did not use CLONE_INTO_CGROUP so return 0, the caller will have to move the child */
2257
#endif
2258
}
2259

2260
int proc_dir_open(DIR **ret) {
63✔
2261
        DIR *d;
63✔
2262

2263
        assert(ret);
63✔
2264

2265
        d = opendir("/proc");
63✔
2266
        if (!d)
63✔
2267
                return -errno;
×
2268

2269
        *ret = d;
63✔
2270
        return 0;
63✔
2271
}
2272

2273
int proc_dir_read(DIR *d, pid_t *ret) {
5,989✔
2274
        assert(d);
5,989✔
2275

2276
        for (;;) {
9,773✔
2277
                struct dirent *de;
9,773✔
2278

2279
                errno = 0;
9,773✔
2280
                de = readdir_no_dot(d);
9,773✔
2281
                if (!de) {
9,773✔
2282
                        if (errno != 0)
63✔
2283
                                return -errno;
×
2284

2285
                        break;
63✔
2286
                }
2287

2288
                if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
9,710✔
2289
                        continue;
3,091✔
2290

2291
                if (parse_pid(de->d_name, ret) >= 0)
6,619✔
2292
                        return 1;
2293
        }
2294

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

2300
int proc_dir_read_pidref(DIR *d, PidRef *ret) {
5,945✔
2301
        int r;
5,945✔
2302

2303
        assert(d);
5,945✔
2304

2305
        for (;;) {
5,947✔
2306
                pid_t pid;
5,946✔
2307

2308
                r = proc_dir_read(d, &pid);
5,946✔
2309
                if (r < 0)
5,946✔
2310
                        return r;
5,883✔
2311
                if (r == 0)
5,946✔
2312
                        break;
2313

2314
                r = pidref_set_pid(ret, pid);
5,884✔
2315
                if (r == -ESRCH) /* gone by now? skip it */
5,884✔
2316
                        continue;
1✔
2317
                if (r < 0)
5,883✔
2318
                        return r;
×
2319

2320
                return 1;
2321
        }
2322

2323
        if (ret)
62✔
2324
                *ret = PIDREF_NULL;
62✔
2325
        return 0;
2326
}
2327

2328
static const char *const sigchld_code_table[] = {
2329
        [CLD_EXITED] = "exited",
2330
        [CLD_KILLED] = "killed",
2331
        [CLD_DUMPED] = "dumped",
2332
        [CLD_TRAPPED] = "trapped",
2333
        [CLD_STOPPED] = "stopped",
2334
        [CLD_CONTINUED] = "continued",
2335
};
2336

2337
DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
13,208✔
2338

2339
static const char* const sched_policy_table[] = {
2340
        [SCHED_OTHER] = "other",
2341
        [SCHED_BATCH] = "batch",
2342
        [SCHED_IDLE] = "idle",
2343
        [SCHED_FIFO] = "fifo",
2344
        [SCHED_RR] = "rr",
2345
};
2346

2347
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
3✔
2348

2349
_noreturn_ void report_errno_and_exit(int errno_fd, int error) {
48✔
2350
        int r;
48✔
2351

2352
        if (error >= 0)
48✔
2353
                _exit(EXIT_SUCCESS);
47✔
2354

2355
        assert(errno_fd >= 0);
1✔
2356

2357
        r = loop_write(errno_fd, &error, sizeof(error));
1✔
2358
        if (r < 0)
1✔
2359
                log_debug_errno(r, "Failed to write errno to errno_fd=%d: %m", errno_fd);
×
2360

2361
        _exit(EXIT_FAILURE);
1✔
2362
}
2363

2364
int read_errno(int errno_fd) {
1✔
2365
        int r;
1✔
2366

2367
        assert(errno_fd >= 0);
1✔
2368

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

2372
        ssize_t n = loop_read(errno_fd, &r, sizeof(r), /* do_poll = */ false);
1✔
2373
        if (n < 0) {
1✔
2374
                log_debug_errno(n, "Failed to read errno: %m");
×
2375
                return -EIO;
×
2376
        }
2377
        if (n == sizeof(r)) {
1✔
2378
                if (r == 0)
×
2379
                        return 0;
2380
                if (r < 0) /* child process reported an error, return it */
×
2381
                        return log_debug_errno(r, "Child process failed with errno: %m");
×
2382
                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received an errno, but it's a positive value.");
×
2383
        }
2384
        if (n != 0)
1✔
2385
                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received unexpected amount of bytes while reading errno.");
×
2386

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