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

systemd / systemd / 14630481637

23 Apr 2025 07:04PM UTC coverage: 72.178% (-0.002%) from 72.18%
14630481637

push

github

DaanDeMeyer
mkosi: Run clangd within the tools tree instead of the build container

Running within the build sandbox has a number of disadvantages:
- We have a separate clangd cache for each distribution/release combo
- It requires to build the full image before clangd can be used
- It breaks every time the image becomes out of date and requires a
  rebuild
- We can't look at system headers as we don't have the knowledge to map
  them from inside the build sandbox to the corresponding path on the host

Instead, let's have mkosi.clangd run clangd within the tools tree. We
already require building systemd for both the host and the target anyway,
and all the dependencies to build systemd are installed in the tools tree
already for that, as well as clangd since it's installed together with the
other clang tooling we install in the tools tree. Unlike the previous approach,
this approach only requires the mkosi tools tree to be built upfront, which has
a much higher chance of not invalidating its cache. We can also trivially map
system header lookups from within the sandbox to the path within mkosi.tools
on the host so that starts working as well.

297054 of 411557 relevant lines covered (72.18%)

686269.58 hits per line

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

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

3
#include <errno.h>
4
#include <fcntl.h>
5
#include <linux/kcmp.h>
6
#include <linux/magic.h>
7
#include <sys/ioctl.h>
8
#include <sys/resource.h>
9
#include <sys/stat.h>
10
#include <unistd.h>
11

12
#include "alloc-util.h"
13
#include "dirent-util.h"
14
#include "fd-util.h"
15
#include "fileio.h"
16
#include "fs-util.h"
17
#include "io-util.h"
18
#include "log.h"
19
#include "macro.h"
20
#include "missing_fcntl.h"
21
#include "missing_fs.h"
22
#include "missing_syscall.h"
23
#include "mountpoint-util.h"
24
#include "parse-util.h"
25
#include "path-util.h"
26
#include "process-util.h"
27
#include "socket-util.h"
28
#include "sort-util.h"
29
#include "stat-util.h"
30
#include "stdio-util.h"
31
#include "tmpfile-util.h"
32

33
/* The maximum number of iterations in the loop to close descriptors in the fallback case
34
 * when /proc/self/fd/ is inaccessible. */
35
#define MAX_FD_LOOP_LIMIT (1024*1024)
36

37
int close_nointr(int fd) {
38,287,469✔
38
        assert(fd >= 0);
38,287,469✔
39

40
        if (close(fd) >= 0)
38,287,469✔
41
                return 0;
42

43
        /*
44
         * Just ignore EINTR; a retry loop is the wrong thing to do on
45
         * Linux.
46
         *
47
         * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
48
         * https://bugzilla.gnome.org/show_bug.cgi?id=682819
49
         * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
50
         * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
51
         */
52
        if (errno == EINTR)
15,886✔
53
                return 0;
54

55
        return -errno;
15,886✔
56
}
57

58
int safe_close(int fd) {
100,423,330✔
59
        /*
60
         * Like close_nointr() but cannot fail. Guarantees errno is unchanged. Is a noop for negative fds,
61
         * and returns -EBADF, so that it can be used in this syntax:
62
         *
63
         * fd = safe_close(fd);
64
         */
65

66
        if (fd >= 0) {
100,423,330✔
67
                PROTECT_ERRNO;
×
68

69
                /* The kernel might return pretty much any error code
70
                 * via close(), but the fd will be closed anyway. The
71
                 * only condition we want to check for here is whether
72
                 * the fd was invalid at all... */
73

74
                assert_se(close_nointr(fd) != -EBADF);
37,858,369✔
75
        }
76

77
        return -EBADF;
100,423,330✔
78
}
79

80
void safe_close_pair(int p[static 2]) {
512,768✔
81
        assert(p);
512,768✔
82

83
        if (p[0] == p[1]) {
512,768✔
84
                /* Special case pairs which use the same fd in both
85
                 * directions... */
86
                p[0] = p[1] = safe_close(p[0]);
479,271✔
87
                return;
479,271✔
88
        }
89

90
        p[0] = safe_close(p[0]);
33,497✔
91
        p[1] = safe_close(p[1]);
33,497✔
92
}
93

94
void close_many(const int fds[], size_t n_fds) {
2,556,401✔
95
        assert(fds || n_fds == 0);
2,556,401✔
96

97
        FOREACH_ARRAY(fd, fds, n_fds)
2,605,469✔
98
                safe_close(*fd);
49,068✔
99
}
2,556,401✔
100

101
void close_many_unset(int fds[], size_t n_fds) {
28✔
102
        assert(fds || n_fds == 0);
28✔
103

104
        FOREACH_ARRAY(fd, fds, n_fds)
29✔
105
                *fd = safe_close(*fd);
1✔
106
}
28✔
107

108
void close_many_and_free(int *fds, size_t n_fds) {
87✔
109
        assert(fds || n_fds == 0);
87✔
110

111
        close_many(fds, n_fds);
87✔
112
        free(fds);
87✔
113
}
87✔
114

115
int fclose_nointr(FILE *f) {
1,584,674✔
116
        assert(f);
1,584,674✔
117

118
        /* Same as close_nointr(), but for fclose() */
119

120
        errno = 0; /* Extra safety: if the FILE* object is not encapsulating an fd, it might not set errno
1,584,674✔
121
                    * correctly. Let's hence initialize it to zero first, so that we aren't confused by any
122
                    * prior errno here */
123
        if (fclose(f) == 0)
1,584,674✔
124
                return 0;
125

126
        if (errno == EINTR)
×
127
                return 0;
128

129
        return errno_or_else(EIO);
×
130
}
131

132
FILE* safe_fclose(FILE *f) {
3,078,246✔
133

134
        /* Same as safe_close(), but for fclose() */
135

136
        if (f) {
3,078,246✔
137
                PROTECT_ERRNO;
×
138

139
                assert_se(fclose_nointr(f) != -EBADF);
1,584,674✔
140
        }
141

142
        return NULL;
3,078,246✔
143
}
144

145
DIR* safe_closedir(DIR *d) {
×
146

147
        if (d) {
×
148
                PROTECT_ERRNO;
×
149

150
                assert_se(closedir(d) >= 0 || errno != EBADF);
×
151
        }
152

153
        return NULL;
×
154
}
155

156
int fd_nonblock(int fd, bool nonblock) {
1,789,231✔
157
        int flags, nflags;
1,789,231✔
158

159
        assert(fd >= 0);
1,789,231✔
160

161
        flags = fcntl(fd, F_GETFL, 0);
1,789,231✔
162
        if (flags < 0)
1,789,231✔
163
                return -errno;
×
164

165
        nflags = UPDATE_FLAG(flags, O_NONBLOCK, nonblock);
1,789,231✔
166
        if (nflags == flags)
1,789,231✔
167
                return 0;
168

169
        if (fcntl(fd, F_SETFL, nflags) < 0)
1,768,137✔
170
                return -errno;
×
171

172
        return 1;
173
}
174

175
int stdio_disable_nonblock(void) {
14,132✔
176
        int ret = 0;
14,132✔
177

178
        /* stdin/stdout/stderr really should have O_NONBLOCK, which would confuse apps if left on, as
179
         * write()s might unexpectedly fail with EAGAIN. */
180

181
        RET_GATHER(ret, fd_nonblock(STDIN_FILENO, false));
14,132✔
182
        RET_GATHER(ret, fd_nonblock(STDOUT_FILENO, false));
14,132✔
183
        RET_GATHER(ret, fd_nonblock(STDERR_FILENO, false));
14,132✔
184

185
        return ret;
14,132✔
186
}
187

188
int fd_cloexec(int fd, bool cloexec) {
77,652✔
189
        int flags, nflags;
77,652✔
190

191
        assert(fd >= 0);
77,652✔
192

193
        flags = fcntl(fd, F_GETFD, 0);
77,652✔
194
        if (flags < 0)
77,652✔
195
                return -errno;
×
196

197
        nflags = UPDATE_FLAG(flags, FD_CLOEXEC, cloexec);
77,652✔
198
        if (nflags == flags)
77,652✔
199
                return 0;
200

201
        return RET_NERRNO(fcntl(fd, F_SETFD, nflags));
69,648✔
202
}
203

204
int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec) {
100✔
205
        int r = 0;
100✔
206

207
        assert(fds || n_fds == 0);
100✔
208

209
        FOREACH_ARRAY(fd, fds, n_fds) {
126✔
210
                if (*fd < 0) /* Skip gracefully over already invalidated fds */
26✔
211
                        continue;
×
212

213
                RET_GATHER(r, fd_cloexec(*fd, cloexec));
26✔
214
        }
215

216
        return r;
100✔
217
}
218

219
static bool fd_in_set(int fd, const int fds[], size_t n_fds) {
35,395✔
220
        assert(fd >= 0);
35,395✔
221
        assert(fds || n_fds == 0);
35,395✔
222

223
        FOREACH_ARRAY(i, fds, n_fds) {
21,875,002✔
224
                if (*i < 0)
21,844,117✔
225
                        continue;
×
226

227
                if (*i == fd)
21,844,117✔
228
                        return true;
229
        }
230

231
        return false;
232
}
233

234
int get_max_fd(void) {
9✔
235
        struct rlimit rl;
9✔
236
        rlim_t m;
9✔
237

238
        /* Return the highest possible fd, based RLIMIT_NOFILE, but enforcing FD_SETSIZE-1 as lower boundary
239
         * and INT_MAX as upper boundary. */
240

241
        if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
9✔
242
                return -errno;
×
243

244
        m = MAX(rl.rlim_cur, rl.rlim_max);
9✔
245
        if (m < FD_SETSIZE) /* Let's always cover at least 1024 fds */
9✔
246
                return FD_SETSIZE-1;
247

248
        if (m == RLIM_INFINITY || m > INT_MAX) /* Saturate on overflow. After all fds are "int", hence can
9✔
249
                                                * never be above INT_MAX */
250
                return INT_MAX;
251

252
        return (int) (m - 1);
9✔
253
}
254

255
static int close_all_fds_frugal(const int except[], size_t n_except) {
4✔
256
        int max_fd, r = 0;
4✔
257

258
        assert(except || n_except == 0);
4✔
259

260
        /* This is the inner fallback core of close_all_fds(). This never calls malloc() or opendir() or so
261
         * and hence is safe to be called in signal handler context. Most users should call close_all_fds(),
262
         * but when we assume we are called from signal handler context, then use this simpler call
263
         * instead. */
264

265
        max_fd = get_max_fd();
4✔
266
        if (max_fd < 0)
4✔
267
                return max_fd;
4✔
268

269
        /* Refuse to do the loop over more too many elements. It's better to fail immediately than to
270
         * spin the CPU for a long time. */
271
        if (max_fd > MAX_FD_LOOP_LIMIT)
4✔
272
                return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
×
273
                                       "Refusing to loop over %d potential fds.", max_fd);
274

275
        for (int fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -EBADF) {
55,980✔
276
                int q;
27,988✔
277

278
                if (fd_in_set(fd, except, n_except))
27,988✔
279
                        continue;
2,103✔
280

281
                q = close_nointr(fd);
25,885✔
282
                if (q != -EBADF)
25,885✔
283
                        RET_GATHER(r, q);
10,000✔
284
        }
285

286
        return r;
287
}
288

289
static bool have_close_range = true; /* Assume we live in the future */
290

291
static int close_all_fds_special_case(const int except[], size_t n_except) {
43,242✔
292
        assert(n_except == 0 || except);
43,242✔
293

294
        /* Handles a few common special cases separately, since they are common and can be optimized really
295
         * nicely, since we won't need sorting for them. Returns > 0 if the special casing worked, 0
296
         * otherwise. */
297

298
        if (!have_close_range)
43,242✔
299
                return 0;
300

301
        if (n_except == 1 && except[0] < 0) /* Minor optimization: if we only got one fd, and it's invalid,
43,238✔
302
                                             * we got none */
303
                n_except = 0;
304

305
        switch (n_except) {
43,238✔
306

307
        case 0:
8,238✔
308
                /* Close everything. Yay! */
309

310
                if (close_range(3, INT_MAX, 0) >= 0)
8,238✔
311
                        return 1;
312

313
                if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno)) {
×
314
                        have_close_range = false;
×
315
                        return 0;
×
316
                }
317

318
                return -errno;
×
319

320
        case 1:
13,920✔
321
                /* Close all but exactly one, then we don't need no sorting. This is a pretty common
322
                 * case, hence let's handle it specially. */
323

324
                if ((except[0] <= 3 || close_range(3, except[0]-1, 0) >= 0) &&
13,920✔
325
                    (except[0] >= INT_MAX || close_range(MAX(3, except[0]+1), -1, 0) >= 0))
13,920✔
326
                        return 1;
13,920✔
327

328
                if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno)) {
×
329
                        have_close_range = false;
×
330
                        return 0;
×
331
                }
332

333
                return -errno;
×
334

335
        default:
336
                return 0;
337
        }
338
}
339

340
int close_all_fds_without_malloc(const int except[], size_t n_except) {
×
341
        int r;
×
342

343
        assert(n_except == 0 || except);
×
344

345
        r = close_all_fds_special_case(except, n_except);
×
346
        if (r < 0)
×
347
                return r;
348
        if (r > 0) /* special case worked! */
×
349
                return 0;
350

351
        return close_all_fds_frugal(except, n_except);
×
352
}
353

354
int close_all_fds(const int except[], size_t n_except) {
43,242✔
355
        _cleanup_closedir_ DIR *d = NULL;
43,242✔
356
        int r = 0;
43,242✔
357

358
        assert(n_except == 0 || except);
43,242✔
359

360
        r = close_all_fds_special_case(except, n_except);
43,242✔
361
        if (r < 0)
43,242✔
362
                return r;
363
        if (r > 0) /* special case worked! */
43,242✔
364
                return 0;
365

366
        if (have_close_range) {
21,084✔
367
                _cleanup_free_ int *sorted_malloc = NULL;
21,080✔
368
                size_t n_sorted;
21,080✔
369
                int *sorted;
21,080✔
370

371
                /* In the best case we have close_range() to close all fds between a start and an end fd,
372
                 * which we can use on the "inverted" exception array, i.e. all intervals between all
373
                 * adjacent pairs from the sorted exception array. This changes loop complexity from O(n)
374
                 * where n is number of open fds to O(mâ‹…log(m)) where m is the number of fds to keep
375
                 * open. Given that we assume n ≫ m that's preferable to us. */
376

377
                assert(n_except < SIZE_MAX);
21,080✔
378
                n_sorted = n_except + 1;
21,080✔
379

380
                if (n_sorted > 64) /* Use heap for large numbers of fds, stack otherwise */
21,080✔
381
                        sorted = sorted_malloc = new(int, n_sorted);
4✔
382
                else
383
                        sorted = newa(int, n_sorted);
21,076✔
384

385
                if (sorted) {
21,080✔
386
                        memcpy(sorted, except, n_except * sizeof(int));
21,080✔
387

388
                        /* Let's add fd 2 to the list of fds, to simplify the loop below, as this
389
                         * allows us to cover the head of the array the same way as the body */
390
                        sorted[n_sorted-1] = 2;
21,080✔
391

392
                        typesafe_qsort(sorted, n_sorted, cmp_int);
21,080✔
393

394
                        for (size_t i = 0; i < n_sorted-1; i++) {
96,599✔
395
                                int start, end;
75,521✔
396

397
                                start = MAX(sorted[i], 2); /* The first three fds shall always remain open */
75,521✔
398
                                end = MAX(sorted[i+1], 2);
75,521✔
399

400
                                assert(end >= start);
75,521✔
401

402
                                if (end - start <= 1)
75,521✔
403
                                        continue;
29,513✔
404

405
                                /* Close everything between the start and end fds (both of which shall stay open) */
406
                                if (close_range(start + 1, end - 1, 0) < 0) {
46,008✔
407
                                        if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
2✔
408
                                                return -errno;
×
409

410
                                        have_close_range = false;
2✔
411
                                        break;
2✔
412
                                }
413
                        }
414

415
                        if (have_close_range) {
21,080✔
416
                                /* The loop succeeded. Let's now close everything beyond the end */
417

418
                                if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */
21,078✔
419
                                        return 0;
420

421
                                if (close_range(sorted[n_sorted-1] + 1, INT_MAX, 0) >= 0)
21,078✔
422
                                        return 0;
423

424
                                if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
×
425
                                        return -errno;
×
426

427
                                have_close_range = false;
×
428
                        }
429
                }
430

431
                /* Fallback on OOM or if close_range() is not supported */
432
        }
433

434
        d = opendir("/proc/self/fd");
6✔
435
        if (!d)
6✔
436
                return close_all_fds_frugal(except, n_except); /* ultimate fallback if /proc/ is not available */
4✔
437

438
        FOREACH_DIRENT(de, d, return -errno) {
7,421✔
439
                int fd = -EBADF, q;
7,415✔
440

441
                if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
7,415✔
442
                        continue;
×
443

444
                fd = parse_fd(de->d_name);
7,415✔
445
                if (fd < 0)
7,415✔
446
                        /* Let's better ignore this, just in case */
447
                        continue;
×
448

449
                if (fd < 3)
7,415✔
450
                        continue;
6✔
451

452
                if (fd == dirfd(d))
7,409✔
453
                        continue;
2✔
454

455
                if (fd_in_set(fd, except, n_except))
7,407✔
456
                        continue;
2,407✔
457

458
                q = close_nointr(fd);
5,000✔
459
                if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */
5,000✔
460
                        r = q;
×
461
        }
462

463
        return r;
464
}
465

466
int pack_fds(int fds[], size_t n_fds) {
9,614✔
467
        if (n_fds <= 0)
9,614✔
468
                return 0;
469

470
        /* Shifts around the fds in the provided array such that they
471
         * all end up packed next to each-other, in order, starting
472
         * from SD_LISTEN_FDS_START. This must be called after close_all_fds();
473
         * it is likely to freeze up otherwise. You should probably use safe_fork_full
474
         * with FORK_CLOSE_ALL_FDS|FORK_PACK_FDS set, to ensure that this is done correctly.
475
         * The fds array is modified in place with the new FD numbers. */
476

477
        assert(fds);
1,376✔
478

479
        for (int start = 0;;) {
480
                int restart_from = -1;
1,376✔
481

482
                for (int i = start; i < (int) n_fds; i++) {
3,631✔
483
                        int nfd;
2,255✔
484

485
                        /* Already at right index? */
486
                        if (fds[i] == i + 3)
2,255✔
487
                                continue;
2✔
488

489
                        nfd = fcntl(fds[i], F_DUPFD, i + 3);
2,253✔
490
                        if (nfd < 0)
2,253✔
491
                                return -errno;
×
492

493
                        safe_close(fds[i]);
2,253✔
494
                        fds[i] = nfd;
2,253✔
495

496
                        /* Hmm, the fd we wanted isn't free? Then
497
                         * let's remember that and try again from here */
498
                        if (nfd != i + 3 && restart_from < 0)
2,253✔
499
                                restart_from = i;
×
500
                }
501

502
                if (restart_from < 0)
1,376✔
503
                        break;
504

505
                start = restart_from;
506
        }
507

508
        assert(fds[0] == 3);
1,376✔
509

510
        return 0;
511
}
512

513
int fd_validate(int fd) {
113,760✔
514
        if (fd < 0)
113,760✔
515
                return -EBADF;
516

517
        if (fcntl(fd, F_GETFD) < 0)
113,758✔
518
                return -errno;
42,224✔
519

520
        return 0;
521
}
522

523
int same_fd(int a, int b) {
13,753✔
524
        struct stat sta, stb;
13,753✔
525
        pid_t pid;
13,753✔
526
        int r, fa, fb;
13,753✔
527

528
        assert(a >= 0);
13,753✔
529
        assert(b >= 0);
13,753✔
530

531
        /* Compares two file descriptors. Note that semantics are quite different depending on whether we
532
         * have F_DUPFD_QUERY/kcmp() or we don't. If we have F_DUPFD_QUERY/kcmp() this will only return true
533
         * for dup()ed file descriptors, but not otherwise. If we don't have F_DUPFD_QUERY/kcmp() this will
534
         * also return true for two fds of the same file, created by separate open() calls. Since we use this
535
         * call mostly for filtering out duplicates in the fd store this difference hopefully doesn't matter
536
         * too much.
537
         *
538
         * Guarantees that if either of the passed fds is not allocated we'll return -EBADF. */
539

540
        if (a == b) {
13,753✔
541
                /* Let's validate that the fd is valid */
542
                r = fd_validate(a);
7✔
543
                if (r < 0)
7✔
544
                        return r;
13,753✔
545

546
                return true;
6✔
547
        }
548

549
        /* Try to use F_DUPFD_QUERY if we have it first, as it is the nicest API */
550
        r = fcntl(a, F_DUPFD_QUERY, b);
13,746✔
551
        if (r > 0)
13,746✔
552
                return true;
553
        if (r == 0) {
13,738✔
554
                /* The kernel will return 0 in case the first fd is allocated, but the 2nd is not. (Which is different in the kcmp() case) Explicitly validate it hence. */
555
                r = fd_validate(b);
13,737✔
556
                if (r < 0)
13,737✔
557
                        return r;
558

559
                return false;
13,736✔
560
        }
561
        /* On old kernels (< 6.10) that do not support F_DUPFD_QUERY this will return EINVAL for regular fds, and EBADF on O_PATH fds. Confusing. */
562
        if (errno == EBADF) {
1✔
563
                /* EBADF could mean two things: the first fd is not valid, or it is valid and is O_PATH and
564
                 * F_DUPFD_QUERY is not supported. Let's validate the fd explicitly, to distinguish this
565
                 * case. */
566
                r = fd_validate(a);
1✔
567
                if (r < 0)
1✔
568
                        return r;
569

570
                /* If the fd is valid, but we got EBADF, then let's try kcmp(). */
571
        } else if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno) && errno != EINVAL)
×
572
                return -errno;
×
573

574
        /* Try to use kcmp() if we have it. */
575
        pid = getpid_cached();
×
576
        r = kcmp(pid, pid, KCMP_FILE, a, b);
×
577
        if (r >= 0)
×
578
                return !r;
×
579
        if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
×
580
                return -errno;
×
581

582
        /* We have neither F_DUPFD_QUERY nor kcmp(), use fstat() instead. */
583
        if (fstat(a, &sta) < 0)
×
584
                return -errno;
×
585

586
        if (fstat(b, &stb) < 0)
×
587
                return -errno;
×
588

589
        if (!stat_inode_same(&sta, &stb))
×
590
                return false;
591

592
        /* We consider all device fds different, since two device fds might refer to quite different device
593
         * contexts even though they share the same inode and backing dev_t. */
594

595
        if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
×
596
                return false;
597

598
        /* The fds refer to the same inode on disk, let's also check if they have the same fd flags. This is
599
         * useful to distinguish the read and write side of a pipe created with pipe(). */
600
        fa = fcntl(a, F_GETFL);
×
601
        if (fa < 0)
×
602
                return -errno;
×
603

604
        fb = fcntl(b, F_GETFL);
×
605
        if (fb < 0)
×
606
                return -errno;
×
607

608
        return fa == fb;
×
609
}
610

611
void cmsg_close_all(struct msghdr *mh) {
83,254✔
612
        assert(mh);
83,254✔
613

614
        struct cmsghdr *cmsg;
83,254✔
615
        CMSG_FOREACH(cmsg, mh) {
293,152✔
616
                if (cmsg->cmsg_level != SOL_SOCKET)
63,322✔
617
                        continue;
×
618

619
                if (cmsg->cmsg_type == SCM_RIGHTS)
63,322✔
620
                        close_many(CMSG_TYPED_DATA(cmsg, int),
×
621
                                   (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
×
622
                else if (cmsg->cmsg_type == SCM_PIDFD) {
63,322✔
623
                        assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
×
624
                        safe_close(*CMSG_TYPED_DATA(cmsg, int));
×
625
                }
626
        }
627
}
83,254✔
628

629
bool fdname_is_valid(const char *s) {
13,141✔
630
        const char *p;
13,141✔
631

632
        /* Validates a name for $LISTEN_FDNAMES. We basically allow
633
         * everything ASCII that's not a control character. Also, as
634
         * special exception the ":" character is not allowed, as we
635
         * use that as field separator in $LISTEN_FDNAMES.
636
         *
637
         * Note that the empty string is explicitly allowed
638
         * here. However, we limit the length of the names to 255
639
         * characters. */
640

641
        if (!s)
13,141✔
642
                return false;
643

644
        for (p = s; *p; p++) {
200,148✔
645
                if (*p < ' ')
187,012✔
646
                        return false;
647
                if (*p >= 127)
187,012✔
648
                        return false;
649
                if (*p == ':')
187,012✔
650
                        return false;
651
        }
652

653
        return p - s <= FDNAME_MAX;
13,136✔
654
}
655

656
int fd_get_path(int fd, char **ret) {
1,744,955✔
657
        int r;
1,744,955✔
658

659
        assert(fd >= 0 || fd == AT_FDCWD);
1,744,955✔
660

661
        if (fd == AT_FDCWD)
1,744,955✔
662
                return safe_getcwd(ret);
5,107✔
663

664
        r = readlink_malloc(FORMAT_PROC_FD_PATH(fd), ret);
1,739,848✔
665
        if (r == -ENOENT)
1,739,848✔
666
                return proc_fd_enoent_errno();
4✔
667
        return r;
668
}
669

670
int move_fd(int from, int to, int cloexec) {
21,574✔
671
        int r;
21,574✔
672

673
        /* Move fd 'from' to 'to', make sure FD_CLOEXEC remains equal if requested, and release the old fd. If
674
         * 'cloexec' is passed as -1, the original FD_CLOEXEC is inherited for the new fd. If it is 0, it is turned
675
         * off, if it is > 0 it is turned on. */
676

677
        if (from < 0)
21,574✔
678
                return -EBADF;
679
        if (to < 0)
21,574✔
680
                return -EBADF;
681

682
        if (from == to) {
21,574✔
683

684
                if (cloexec >= 0) {
×
685
                        r = fd_cloexec(to, cloexec);
×
686
                        if (r < 0)
×
687
                                return r;
688
                }
689

690
                return to;
×
691
        }
692

693
        if (cloexec < 0) {
21,574✔
694
                int fl;
×
695

696
                fl = fcntl(from, F_GETFD, 0);
×
697
                if (fl < 0)
×
698
                        return -errno;
×
699

700
                cloexec = FLAGS_SET(fl, FD_CLOEXEC);
×
701
        }
702

703
        r = dup3(from, to, cloexec ? O_CLOEXEC : 0);
43,148✔
704
        if (r < 0)
21,574✔
705
                return -errno;
×
706

707
        assert(r == to);
21,574✔
708

709
        safe_close(from);
21,574✔
710

711
        return to;
21,574✔
712
}
713

714
int fd_move_above_stdio(int fd) {
631,204✔
715
        int flags, copy;
631,204✔
716
        PROTECT_ERRNO;
631,204✔
717

718
        /* Moves the specified file descriptor if possible out of the range [0…2], i.e. the range of
719
         * stdin/stdout/stderr. If it can't be moved outside of this range the original file descriptor is
720
         * returned. This call is supposed to be used for long-lasting file descriptors we allocate in our code that
721
         * might get loaded into foreign code, and where we want ensure our fds are unlikely used accidentally as
722
         * stdin/stdout/stderr of unrelated code.
723
         *
724
         * Note that this doesn't fix any real bugs, it just makes it less likely that our code will be affected by
725
         * buggy code from others that mindlessly invokes 'fprintf(stderr, …' or similar in places where stderr has
726
         * been closed before.
727
         *
728
         * This function is written in a "best-effort" and "least-impact" style. This means whenever we encounter an
729
         * error we simply return the original file descriptor, and we do not touch errno. */
730

731
        if (fd < 0 || fd > 2)
631,204✔
732
                return fd;
733

734
        flags = fcntl(fd, F_GETFD, 0);
105✔
735
        if (flags < 0)
105✔
736
                return fd;
737

738
        if (flags & FD_CLOEXEC)
105✔
739
                copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
103✔
740
        else
741
                copy = fcntl(fd, F_DUPFD, 3);
2✔
742
        if (copy < 0)
105✔
743
                return fd;
744

745
        assert(copy > 2);
105✔
746

747
        (void) close(fd);
105✔
748
        return copy;
749
}
750

751
int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd) {
14,429✔
752
        int fd[3] = { original_input_fd,             /* Put together an array of fds we work on */
14,429✔
753
                      original_output_fd,
754
                      original_error_fd },
755
            null_fd = -EBADF,                        /* If we open /dev/null, we store the fd to it here */
14,429✔
756
            copy_fd[3] = EBADF_TRIPLET,              /* This contains all fds we duplicate here
14,429✔
757
                                                      * temporarily, and hence need to close at the end. */
758
            r;
759
        bool null_readable, null_writable;
14,429✔
760

761
        /* Sets up stdin, stdout, stderr with the three file descriptors passed in. If any of the descriptors
762
         * is specified as -EBADF it will be connected with /dev/null instead. If any of the file descriptors
763
         * is passed as itself (e.g. stdin as STDIN_FILENO) it is left unmodified, but the O_CLOEXEC bit is
764
         * turned off should it be on.
765
         *
766
         * Note that if any of the passed file descriptors are > 2 they will be closed — both on success and
767
         * on failure! Thus, callers should assume that when this function returns the input fds are
768
         * invalidated.
769
         *
770
         * Note that when this function fails stdin/stdout/stderr might remain half set up!
771
         *
772
         * O_CLOEXEC is turned off for all three file descriptors (which is how it should be for
773
         * stdin/stdout/stderr). */
774

775
        null_readable = original_input_fd < 0;
14,429✔
776
        null_writable = original_output_fd < 0 || original_error_fd < 0;
14,429✔
777

778
        /* First step, open /dev/null once, if we need it */
779
        if (null_readable || null_writable) {
14,429✔
780

781
                /* Let's open this with O_CLOEXEC first, and convert it to non-O_CLOEXEC when we move the fd to the final position. */
782
                null_fd = open("/dev/null", (null_readable && null_writable ? O_RDWR :
23,871✔
783
                                             null_readable ? O_RDONLY : O_WRONLY) | O_CLOEXEC);
11,891✔
784
                if (null_fd < 0) {
11,980✔
785
                        r = -errno;
×
786
                        goto finish;
×
787
                }
788

789
                /* If this fd is in the 0…2 range, let's move it out of it */
790
                if (null_fd < 3) {
11,980✔
791
                        int copy;
13✔
792

793
                        copy = fcntl(null_fd, F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
13✔
794
                        if (copy < 0) {
13✔
795
                                r = -errno;
×
796
                                goto finish;
×
797
                        }
798

799
                        close_and_replace(null_fd, copy);
13✔
800
                }
801
        }
802

803
        /* Let's assemble fd[] with the fds to install in place of stdin/stdout/stderr */
804
        for (int i = 0; i < 3; i++)
57,716✔
805
                if (fd[i] < 0)
43,287✔
806
                        fd[i] = null_fd;        /* A negative parameter means: connect this one to /dev/null */
12,153✔
807
                else if (fd[i] != i && fd[i] < 3) {
31,134✔
808
                        /* This fd is in the 0…2 territory, but not at its intended place, move it out of there, so that we can work there. */
809
                        copy_fd[i] = fcntl(fd[i], F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
82✔
810
                        if (copy_fd[i] < 0) {
82✔
811
                                r = -errno;
×
812
                                goto finish;
×
813
                        }
814

815
                        fd[i] = copy_fd[i];
82✔
816
                }
817

818
        /* At this point we now have the fds to use in fd[], and they are all above the stdio range, so that
819
         * we have freedom to move them around. If the fds already were at the right places then the specific
820
         * fds are -EBADF. Let's now move them to the right places. This is the point of no return. */
821
        for (int i = 0; i < 3; i++)
57,716✔
822
                if (fd[i] == i) {
43,287✔
823
                        /* fd is already in place, but let's make sure O_CLOEXEC is off */
824
                        r = fd_cloexec(i, false);
4,756✔
825
                        if (r < 0)
4,756✔
826
                                goto finish;
×
827
                } else {
828
                        assert(fd[i] > 2);
38,531✔
829

830
                        if (dup2(fd[i], i) < 0) { /* Turns off O_CLOEXEC on the new fd. */
38,531✔
831
                                r = -errno;
×
832
                                goto finish;
×
833
                        }
834
                }
835

836
        r = 0;
837

838
finish:
14,429✔
839
        /* Close the original fds, but only if they were outside of the stdio range. Also, properly check for the same
840
         * fd passed in multiple times. */
841
        safe_close_above_stdio(original_input_fd);
14,429✔
842
        if (original_output_fd != original_input_fd)
14,429✔
843
                safe_close_above_stdio(original_output_fd);
14,196✔
844
        if (original_error_fd != original_input_fd && original_error_fd != original_output_fd)
14,429✔
845
                safe_close_above_stdio(original_error_fd);
14,018✔
846

847
        /* Close the copies we moved > 2 */
848
        close_many(copy_fd, 3);
14,429✔
849

850
        /* Close our null fd, if it's > 2 */
851
        safe_close_above_stdio(null_fd);
14,429✔
852

853
        return r;
14,429✔
854
}
855

856
int fd_reopen(int fd, int flags) {
1,407,312✔
857
        assert(fd >= 0 || fd == AT_FDCWD);
1,407,312✔
858
        assert(!FLAGS_SET(flags, O_CREAT));
1,407,312✔
859

860
        /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to
861
         * turn O_RDWR fds into O_RDONLY fds.
862
         *
863
         * This doesn't work on sockets (since they cannot be open()ed, ever).
864
         *
865
         * This implicitly resets the file read index to 0.
866
         *
867
         * If AT_FDCWD is specified as file descriptor gets an fd to the current cwd.
868
         *
869
         * If the specified file descriptor refers to a symlink via O_PATH, then this function cannot be used
870
         * to follow that symlink. Because we cannot have non-O_PATH fds to symlinks reopening it without
871
         * O_PATH will always result in -ELOOP. Or in other words: if you have an O_PATH fd to a symlink you
872
         * can reopen it only if you pass O_PATH again. */
873

874
        if (FLAGS_SET(flags, O_NOFOLLOW))
1,407,312✔
875
                /* O_NOFOLLOW is not allowed in fd_reopen(), because after all this is primarily implemented
876
                 * via a symlink-based interface in /proc/self/fd. Let's refuse this here early. Note that
877
                 * the kernel would generate ELOOP here too, hence this manual check is mostly redundant –
878
                 * the only reason we add it here is so that the O_DIRECTORY special case (see below) behaves
879
                 * the same way as the non-O_DIRECTORY case. */
880
                return -ELOOP;
1,407,312✔
881

882
        if (FLAGS_SET(flags, O_DIRECTORY) || fd == AT_FDCWD)
1,407,306✔
883
                /* If we shall reopen the fd as directory we can just go via "." and thus bypass the whole
884
                 * magic /proc/ directory, and make ourselves independent of that being mounted. */
885
                return RET_NERRNO(openat(fd, ".", flags | O_DIRECTORY));
217,970✔
886

887
        int new_fd = open(FORMAT_PROC_FD_PATH(fd), flags);
1,189,342✔
888
        if (new_fd < 0) {
1,189,342✔
889
                if (errno != ENOENT)
48,226✔
890
                        return -errno;
48,223✔
891

892
                return proc_fd_enoent_errno();
3✔
893
        }
894

895
        return new_fd;
896
}
897

898
int fd_reopen_propagate_append_and_position(int fd, int flags) {
28✔
899
        /* Invokes fd_reopen(fd, flags), but propagates O_APPEND if set on original fd, and also tries to
900
         * keep current file position.
901
         *
902
         * You should use this if the original fd potentially is O_APPEND, otherwise we get rather
903
         * "unexpected" behavior. Unless you intentionally want to overwrite pre-existing data, and have
904
         * your output overwritten by the next user.
905
         *
906
         * Use case: "systemd-run --pty >> some-log".
907
         *
908
         * The "keep position" part is obviously nonsense for the O_APPEND case, but should reduce surprises
909
         * if someone carefully pre-positioned the passed in original input or non-append output FDs. */
910

911
        assert(fd >= 0);
28✔
912
        assert(!(flags & (O_APPEND|O_DIRECTORY)));
28✔
913

914
        int existing_flags = fcntl(fd, F_GETFL);
28✔
915
        if (existing_flags < 0)
28✔
916
                return -errno;
×
917

918
        int new_fd = fd_reopen(fd, flags | (existing_flags & O_APPEND));
28✔
919
        if (new_fd < 0)
28✔
920
                return new_fd;
921

922
        /* Try to adjust the offset, but ignore errors. */
923
        off_t p = lseek(fd, 0, SEEK_CUR);
19✔
924
        if (p > 0) {
19✔
925
                off_t new_p = lseek(new_fd, p, SEEK_SET);
×
926
                if (new_p < 0)
×
927
                        log_debug_errno(errno,
×
928
                                        "Failed to propagate file position for re-opened fd %d, ignoring: %m",
929
                                        fd);
930
                else if (new_p != p)
×
931
                        log_debug("Failed to propagate file position for re-opened fd %d (%lld != %lld), ignoring.",
×
932
                                  fd, (long long) new_p, (long long) p);
933
        }
934

935
        return new_fd;
936
}
937

938
int fd_reopen_condition(
1,201,826✔
939
                int fd,
940
                int flags,
941
                int mask,
942
                int *ret_new_fd) {
943

944
        int r, new_fd;
1,201,826✔
945

946
        assert(fd >= 0);
1,201,826✔
947
        assert(!FLAGS_SET(flags, O_CREAT));
1,201,826✔
948

949
        /* Invokes fd_reopen(fd, flags), but only if the existing F_GETFL flags don't match the specified
950
         * flags (masked by the specified mask). This is useful for converting O_PATH fds into real fds if
951
         * needed, but only then. */
952

953
        r = fcntl(fd, F_GETFL);
1,201,826✔
954
        if (r < 0)
1,201,826✔
955
                return -errno;
×
956

957
        if ((r & mask) == (flags & mask)) {
1,201,826✔
958
                *ret_new_fd = -EBADF;
1,197,795✔
959
                return fd;
1,197,795✔
960
        }
961

962
        new_fd = fd_reopen(fd, flags);
4,031✔
963
        if (new_fd < 0)
4,031✔
964
                return new_fd;
965

966
        *ret_new_fd = new_fd;
4,031✔
967
        return new_fd;
4,031✔
968
}
969

970
int fd_is_opath(int fd) {
444,802✔
971
        int r;
444,802✔
972

973
        assert(fd >= 0);
444,802✔
974

975
        r = fcntl(fd, F_GETFL);
444,802✔
976
        if (r < 0)
444,802✔
977
                return -errno;
×
978

979
        return FLAGS_SET(r, O_PATH);
444,802✔
980
}
981

982
int fd_verify_safe_flags_full(int fd, int extra_flags) {
482✔
983
        int flags, unexpected_flags;
482✔
984

985
        /* Check if an extrinsic fd is safe to work on (by a privileged service). This ensures that clients
986
         * can't trick a privileged service into giving access to a file the client doesn't already have
987
         * access to (especially via something like O_PATH).
988
         *
989
         * O_NOFOLLOW: For some reason the kernel will return this flag from fcntl(); it doesn't go away
990
         *             immediately after open(). It should have no effect whatsoever to an already-opened FD,
991
         *             and since we refuse O_PATH it should be safe.
992
         *
993
         * RAW_O_LARGEFILE: glibc secretly sets this and neglects to hide it from us if we call fcntl.
994
         *                  See comment in missing_fcntl.h for more details about this.
995
         *
996
         * If 'extra_flags' is specified as non-zero the included flags are also allowed.
997
         */
998

999
        assert(fd >= 0);
482✔
1000

1001
        flags = fcntl(fd, F_GETFL);
482✔
1002
        if (flags < 0)
482✔
1003
                return -errno;
×
1004

1005
        unexpected_flags = flags & ~(O_ACCMODE_STRICT|O_NOFOLLOW|RAW_O_LARGEFILE|extra_flags);
482✔
1006
        if (unexpected_flags != 0)
482✔
1007
                return log_debug_errno(SYNTHETIC_ERRNO(EREMOTEIO),
×
1008
                                       "Unexpected flags set for extrinsic fd: 0%o",
1009
                                       (unsigned) unexpected_flags);
1010

1011
        return flags & (O_ACCMODE_STRICT | extra_flags); /* return the flags variable, but remove the noise */
482✔
1012
}
1013

1014
int read_nr_open(void) {
28,828✔
1015
        _cleanup_free_ char *nr_open = NULL;
28,828✔
1016
        int r;
28,828✔
1017

1018
        /* Returns the kernel's current fd limit, either by reading it of /proc/sys if that works, or using the
1019
         * hard-coded default compiled-in value of current kernels (1M) if not. This call will never fail. */
1020

1021
        r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
28,828✔
1022
        if (r < 0)
28,828✔
1023
                log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m");
28,828✔
1024
        else {
1025
                int v;
28,825✔
1026

1027
                r = safe_atoi(nr_open, &v);
28,825✔
1028
                if (r < 0)
28,825✔
1029
                        log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open);
×
1030
                else
1031
                        return v;
28,825✔
1032
        }
1033

1034
        /* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */
1035
        return 1024 * 1024;
1036
}
1037

1038
int fd_get_diskseq(int fd, uint64_t *ret) {
61,193✔
1039
        uint64_t diskseq;
61,193✔
1040

1041
        assert(fd >= 0);
61,193✔
1042
        assert(ret);
61,193✔
1043

1044
        if (ioctl(fd, BLKGETDISKSEQ, &diskseq) < 0) {
61,193✔
1045
                /* Note that the kernel is weird: non-existing ioctls currently return EINVAL
1046
                 * rather than ENOTTY on loopback block devices. They should fix that in the kernel,
1047
                 * but in the meantime we accept both here. */
1048
                if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EINVAL)
×
1049
                        return -errno;
×
1050

1051
                return -EOPNOTSUPP;
1052
        }
1053

1054
        *ret = diskseq;
61,193✔
1055

1056
        return 0;
61,193✔
1057
}
1058

1059
int path_is_root_at(int dir_fd, const char *path) {
3,172,722✔
1060
        _cleanup_close_ int fd = -EBADF, pfd = -EBADF;
3,172,722✔
1061

1062
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
3,172,722✔
1063

1064
        if (!isempty(path)) {
3,172,722✔
1065
                fd = openat(dir_fd, path, O_PATH|O_DIRECTORY|O_CLOEXEC);
100,778✔
1066
                if (fd < 0)
100,778✔
1067
                        return errno == ENOTDIR ? false : -errno;
14,538✔
1068

1069
                dir_fd = fd;
1070
        }
1071

1072
        pfd = openat(dir_fd, "..", O_PATH|O_DIRECTORY|O_CLOEXEC);
3,158,184✔
1073
        if (pfd < 0)
3,158,184✔
1074
                return errno == ENOTDIR ? false : -errno;
2✔
1075

1076
        /* Even if the parent directory has the same inode, the fd may not point to the root directory "/",
1077
         * and we also need to check that the mount ids are the same. Otherwise, a construct like the
1078
         * following could be used to trick us:
1079
         *
1080
         * $ mkdir /tmp/x /tmp/x/y
1081
         * $ mount --bind /tmp/x /tmp/x/y
1082
         */
1083

1084
        return fds_are_same_mount(dir_fd, pfd);
3,158,182✔
1085
}
1086

1087
int fds_are_same_mount(int fd1, int fd2) {
3,158,200✔
1088
        struct statx sx1 = {}, sx2 = {}; /* explicitly initialize the struct to make msan silent. */
3,158,200✔
1089
        int r;
3,158,200✔
1090

1091
        assert(fd1 >= 0);
3,158,200✔
1092
        assert(fd2 >= 0);
3,158,200✔
1093

1094
        if (statx(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1) < 0)
3,158,200✔
1095
                return -errno;
×
1096

1097
        if (statx(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2) < 0)
3,158,200✔
1098
                return -errno;
×
1099

1100
        /* First, compare inode. If these are different, the fd does not point to the root directory "/". */
1101
        if (!statx_inode_same(&sx1, &sx2))
3,158,200✔
1102
                return false;
1103

1104
        /* Note, statx() does not provide the mount ID and path_get_mnt_id_at() does not work when an old
1105
         * kernel is used. In that case, let's assume that we do not have such spurious mount points in an
1106
         * early boot stage, and silently skip the following check. */
1107

1108
        if (!FLAGS_SET(sx1.stx_mask, STATX_MNT_ID)) {
2,903,403✔
1109
                int mntid;
×
1110

1111
                r = path_get_mnt_id_at_fallback(fd1, "", &mntid);
×
1112
                if (r < 0)
×
1113
                        return r;
×
1114
                assert(mntid >= 0);
×
1115

1116
                sx1.stx_mnt_id = mntid;
×
1117
                sx1.stx_mask |= STATX_MNT_ID;
×
1118
        }
1119

1120
        if (!FLAGS_SET(sx2.stx_mask, STATX_MNT_ID)) {
2,903,403✔
1121
                int mntid;
×
1122

1123
                r = path_get_mnt_id_at_fallback(fd2, "", &mntid);
×
1124
                if (r < 0)
×
1125
                        return r;
×
1126
                assert(mntid >= 0);
×
1127

1128
                sx2.stx_mnt_id = mntid;
×
1129
                sx2.stx_mask |= STATX_MNT_ID;
×
1130
        }
1131

1132
        return statx_mount_same(&sx1, &sx2);
2,903,403✔
1133
}
1134

1135
const char* accmode_to_string(int flags) {
176✔
1136
        switch (flags & O_ACCMODE_STRICT) {
176✔
1137
        case O_RDONLY:
1138
                return "ro";
1139
        case O_WRONLY:
3✔
1140
                return "wo";
3✔
1141
        case O_RDWR:
170✔
1142
                return "rw";
170✔
1143
        default:
×
1144
                return NULL;
×
1145
        }
1146
}
1147

1148
char* format_proc_pid_fd_path(char buf[static PROC_PID_FD_PATH_MAX], pid_t pid, int fd) {
1✔
1149
        assert(buf);
1✔
1150
        assert(fd >= 0);
1✔
1151
        assert(pid >= 0);
1✔
1152
        assert_se(snprintf_ok(buf, PROC_PID_FD_PATH_MAX, "/proc/" PID_FMT "/fd/%i", pid == 0 ? getpid_cached() : pid, fd));
1✔
1153
        return buf;
1✔
1154
}
1155

1156
int proc_fd_enoent_errno(void) {
7✔
1157
        int r;
7✔
1158

1159
        /* When ENOENT is returned during the use of FORMAT_PROC_FD_PATH, it can mean two things:
1160
         * that the fd does not exist or that /proc/ is not mounted.
1161
         * Let's make things debuggable and figure out the most appropriate errno. */
1162

1163
        r = proc_mounted();
7✔
1164
        if (r == 0)
7✔
1165
                return -ENOSYS;  /* /proc/ is not available or not set up properly, we're most likely
1166
                                    in some chroot environment. */
1167
        if (r > 0)
7✔
1168
                return -EBADF;   /* If /proc/ is definitely around then this means the fd is not valid. */
7✔
1169

1170
        return -ENOENT;          /* Otherwise let's propagate the original ENOENT. */
1171
}
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