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

systemd / systemd / 23927985597

02 Apr 2026 07:45PM UTC coverage: 72.362% (+0.02%) from 72.343%
23927985597

push

github

daandemeyer
ci: Drop base64 encoding in claude review workflow

Doesn't seem to work nearly as good as the previous solution which
just told claude not to escape stuff.

319121 of 441004 relevant lines covered (72.36%)

1167673.48 hits per line

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

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

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

11
#include "alloc-util.h"
12
#include "dirent-util.h"
13
#include "errno-util.h"
14
#include "fd-util.h"
15
#include "fileio.h"
16
#include "format-util.h"
17
#include "fs-util.h"
18
#include "log.h"
19
#include "parse-util.h"
20
#include "path-util.h"
21
#include "process-util.h"
22
#include "sort-util.h"
23
#include "stat-util.h"
24
#include "stdio-util.h"
25
#include "string-util.h"
26

27
/* The maximum number of iterations in the loop to close descriptors in the fallback case
28
 * when /proc/self/fd/ is inaccessible. */
29
#define MAX_FD_LOOP_LIMIT (1024*1024)
30

31
int close_nointr(int fd) {
39,238,327✔
32
        assert(fd >= 0);
39,238,327✔
33

34
        if (close(fd) >= 0)
39,238,327✔
35
                return 0;
36

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

49
        return -errno;
10,992✔
50
}
51

52
int safe_close(int fd) {
114,739,451✔
53
        /*
54
         * Like close_nointr() but cannot fail. Guarantees errno is unchanged. Is a noop for negative fds,
55
         * and returns -EBADF, so that it can be used in this syntax:
56
         *
57
         * fd = safe_close(fd);
58
         */
59

60
        if (fd >= 0) {
114,739,451✔
61
                PROTECT_ERRNO;
×
62

63
                /* The kernel might return pretty much any error code
64
                 * via close(), but the fd will be closed anyway. The
65
                 * only condition we want to check for here is whether
66
                 * the fd was invalid at all... */
67

68
                assert_se(close_nointr(fd) != -EBADF);
38,839,842✔
69
        }
70

71
        return -EBADF;
114,739,451✔
72
}
73

74
void safe_close_pair(int p[static 2]) {
703,468✔
75
        assert(p);
703,468✔
76

77
        if (p[0] == p[1]) {
703,468✔
78
                /* Special case pairs which use the same fd in both
79
                 * directions... */
80
                p[0] = p[1] = safe_close(p[0]);
666,323✔
81
                return;
666,323✔
82
        }
83

84
        p[0] = safe_close(p[0]);
37,145✔
85
        p[1] = safe_close(p[1]);
37,145✔
86
}
87

88
void close_many(const int fds[], size_t n_fds) {
3,750,875✔
89
        assert(fds || n_fds == 0);
3,750,875✔
90

91
        FOREACH_ARRAY(fd, fds, n_fds)
3,809,342✔
92
                safe_close(*fd);
58,467✔
93
}
3,750,875✔
94

95
void close_many_unset(int fds[], size_t n_fds) {
34✔
96
        assert(fds || n_fds == 0);
34✔
97

98
        FOREACH_ARRAY(fd, fds, n_fds)
35✔
99
                *fd = safe_close(*fd);
1✔
100
}
34✔
101

102
void close_many_and_free(int *fds, size_t n_fds) {
853✔
103
        assert(fds || n_fds == 0);
853✔
104

105
        close_many(fds, n_fds);
853✔
106
        free(fds);
853✔
107
}
853✔
108

109
int fclose_nointr(FILE *f) {
2,141,262✔
110
        assert(f);
2,141,262✔
111

112
        /* Same as close_nointr(), but for fclose() */
113

114
        errno = 0; /* Extra safety: if the FILE* object is not encapsulating an fd, it might not set errno
2,141,262✔
115
                    * correctly. Let's hence initialize it to zero first, so that we aren't confused by any
116
                    * prior errno here */
117
        if (fclose(f) == 0)
2,141,262✔
118
                return 0;
119

120
        if (errno == EINTR)
×
121
                return 0;
122

123
        return errno_or_else(EIO);
×
124
}
125

126
FILE* safe_fclose(FILE *f) {
4,019,393✔
127

128
        /* Same as safe_close(), but for fclose() */
129

130
        if (f) {
4,019,393✔
131
                PROTECT_ERRNO;
×
132

133
                assert_se(fclose_nointr(f) != -EBADF);
2,141,262✔
134
        }
135

136
        return NULL;
4,019,393✔
137
}
138

139
DIR* safe_closedir(DIR *d) {
×
140

141
        if (d) {
×
142
                PROTECT_ERRNO;
×
143

144
                assert_se(closedir(d) >= 0 || errno != EBADF);
×
145
        }
146

147
        return NULL;
×
148
}
149

150
int fd_nonblock(int fd, bool nonblock) {
1,964,910✔
151
        int flags, nflags;
1,964,910✔
152

153
        assert(fd >= 0);
1,964,910✔
154

155
        flags = fcntl(fd, F_GETFL, 0);
1,964,910✔
156
        if (flags < 0)
1,964,910✔
157
                return -errno;
×
158

159
        nflags = UPDATE_FLAG(flags, O_NONBLOCK, nonblock);
1,964,910✔
160
        if (nflags == flags)
1,964,910✔
161
                return 0;
162

163
        if (fcntl(fd, F_SETFL, nflags) < 0)
1,939,292✔
164
                return -errno;
×
165

166
        return 1;
167
}
168

169
void nonblock_resetp(int *fd) {
540✔
170
        PROTECT_ERRNO;
540✔
171

172
        if (*fd >= 0)
540✔
173
                (void) fd_nonblock(*fd, false);
×
174
}
540✔
175

176
int stdio_disable_nonblock(void) {
16,409✔
177
        int ret = 0;
16,409✔
178

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

182
        RET_GATHER(ret, fd_nonblock(STDIN_FILENO, false));
16,409✔
183
        RET_GATHER(ret, fd_nonblock(STDOUT_FILENO, false));
16,409✔
184
        RET_GATHER(ret, fd_nonblock(STDERR_FILENO, false));
16,409✔
185

186
        return ret;
16,409✔
187
}
188

189
int fd_cloexec(int fd, bool cloexec) {
84,046✔
190
        int flags, nflags;
84,046✔
191

192
        assert(fd >= 0);
84,046✔
193

194
        flags = fcntl(fd, F_GETFD, 0);
84,046✔
195
        if (flags < 0)
84,046✔
196
                return -errno;
×
197

198
        nflags = UPDATE_FLAG(flags, FD_CLOEXEC, cloexec);
84,046✔
199
        if (nflags == flags)
84,046✔
200
                return 0;
201

202
        return RET_NERRNO(fcntl(fd, F_SETFD, nflags));
70,319✔
203
}
204

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

208
        assert(fds || n_fds == 0);
154✔
209

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

214
                RET_GATHER(r, fd_cloexec(*fd, cloexec));
63✔
215
        }
216

217
        return r;
154✔
218
}
219

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

224
        FOREACH_ARRAY(i, fds, n_fds) {
7,939,362✔
225
                if (*i < 0)
7,919,613✔
226
                        continue;
×
227

228
                if (*i == fd)
7,919,613✔
229
                        return true;
230
        }
231

232
        return false;
233
}
234

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

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

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

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

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

253
        return (int) (m - 1);
6✔
254
}
255

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

259
        assert(except || n_except == 0);
3✔
260

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

265
        max_fd = get_max_fd();
3✔
266
        if (max_fd < 0)
3✔
267
                return max_fd;
3✔
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)
3✔
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) {
20,994✔
276
                int q;
20,991✔
277

278
                if (fd_in_set(fd, except, n_except))
20,991✔
279
                        continue;
1,242✔
280

281
                q = close_nointr(fd);
19,749✔
282
                if (q != -EBADF)
19,749✔
283
                        RET_GATHER(r, q);
8,758✔
284
        }
285

286
        return r;
287
}
288

289
static int close_all_fds_special_case(const int except[], size_t n_except) {
46,609✔
290
        assert(n_except == 0 || except);
46,609✔
291

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

296
        if (n_except == 1 && except[0] < 0) /* Minor optimization: if we only got one fd, and it's invalid,
46,609✔
297
                                             * we got none */
298
                n_except = 0;
299

300
        switch (n_except) {
46,609✔
301

302
        case 0:
10,404✔
303
                /* Close everything. Yay! */
304
                if (close_range(3, INT_MAX, 0) < 0)
10,404✔
305
                        return -errno;
×
306

307
                return 1;
308

309
        case 1:
15,450✔
310
                /* Close all but exactly one, then we don't need no sorting. This is a pretty common
311
                 * case, hence let's handle it specially. */
312

313
                if (except[0] > 3 && close_range(3, except[0] - 1, 0) < 0)
15,450✔
314
                        return -errno;
×
315

316
                if (except[0] < INT_MAX && close_range(MAX(3, except[0] + 1), -1, 0) < 0)
15,450✔
317
                        return -errno;
×
318

319
                return 1;
320

321
        default:
322
                return 0;
323
        }
324
}
325

326
int close_all_fds_without_malloc(const int except[], size_t n_except) {
2✔
327
        int r;
2✔
328

329
        assert(n_except == 0 || except);
2✔
330

331
        r = close_all_fds_special_case(except, n_except);
2✔
332
        if (r < 0)
2✔
333
                return r;
334
        if (r > 0) /* special case worked! */
2✔
335
                return 0;
336

337
        return close_all_fds_frugal(except, n_except);
1✔
338
}
339

340
int close_all_fds(const int except[], size_t n_except) {
46,607✔
341
        int r;
46,607✔
342

343
        assert(n_except == 0 || except);
46,607✔
344

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

351
        _cleanup_free_ int *sorted_malloc = NULL;
20,754✔
352
        size_t n_sorted;
20,754✔
353
        int *sorted;
20,754✔
354

355
        /* In the best case we have close_range() to close all fds between a start and an end fd, which we
356
         * can use on the "inverted" exception array, i.e. all intervals between all adjacent pairs from the
357
         * sorted exception array. This changes loop complexity from O(n) where n is number of open fds to
358
         * O(m⋅log(m)) where m is the number of fds to keep open. Given that we assume n ≫ m that's
359
         * preferable to us. */
360

361
        assert(n_except < SIZE_MAX);
20,754✔
362
        n_sorted = n_except + 1;
20,754✔
363

364
        if (n_sorted > ALLOCA_MAX / sizeof(int)) /* Use heap for large numbers of fds, stack otherwise */
20,754✔
365
                sorted = sorted_malloc = new(int, n_sorted);
×
366
        else
367
                sorted = newa(int, n_sorted);
20,754✔
368

369
        if (!sorted) /* Fallback on OOM. */
20,754✔
370
                return close_all_fds_frugal(except, n_except);
×
371

372
        memcpy(sorted, except, n_except * sizeof(int));
20,754✔
373

374
        /* Let's add fd 2 to the list of fds, to simplify the loop below, as this
375
         * allows us to cover the head of the array the same way as the body */
376
        sorted[n_sorted-1] = 2;
20,754✔
377

378
        typesafe_qsort(sorted, n_sorted, cmp_int);
20,754✔
379

380
        for (size_t i = 0; i < n_sorted-1; i++) {
248,132✔
381
                int start, end;
227,378✔
382

383
                start = MAX(sorted[i], 2); /* The first three fds shall always remain open */
227,378✔
384
                end = MAX(sorted[i+1], 2);
227,378✔
385

386
                assert(end >= start);
227,378✔
387

388
                if (end - start <= 1)
227,378✔
389
                        continue;
183,007✔
390

391
                /* Close everything between the start and end fds (both of which shall stay open) */
392
                if (close_range(start + 1, end - 1, 0) < 0)
44,371✔
393
                        return -errno;
×
394
        }
395

396
        /* The loop succeeded. Let's now close everything beyond the end */
397

398
        if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */
20,754✔
399
                return 0;
400

401
        if (close_range(sorted[n_sorted-1] + 1, INT_MAX, 0) < 0)
20,754✔
402
                return -errno;
×
403

404
        return 0;
405
}
406

407
int pack_fds(int fds[], size_t n_fds) {
10,431✔
408
        if (n_fds <= 0)
10,431✔
409
                return 0;
410

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

418
        assert(fds);
1,810✔
419

420
        for (int start = 0;;) {
421
                int restart_from = -1;
1,810✔
422

423
                for (int i = start; i < (int) n_fds; i++) {
6,028✔
424
                        int nfd;
4,218✔
425

426
                        /* Already at right index? */
427
                        if (fds[i] == i + 3)
4,218✔
428
                                continue;
3✔
429

430
                        nfd = fcntl(fds[i], F_DUPFD, i + 3);
4,215✔
431
                        if (nfd < 0)
4,215✔
432
                                return -errno;
×
433

434
                        safe_close(fds[i]);
4,215✔
435
                        fds[i] = nfd;
4,215✔
436

437
                        /* Hmm, the fd we wanted isn't free? Then
438
                         * let's remember that and try again from here */
439
                        if (nfd != i + 3 && restart_from < 0)
4,215✔
440
                                restart_from = i;
×
441
                }
442

443
                if (restart_from < 0)
1,810✔
444
                        break;
445

446
                start = restart_from;
447
        }
448

449
        assert(fds[0] == 3);
1,810✔
450

451
        return 0;
452
}
453

454
int fd_validate(int fd) {
74,863✔
455
        if (fd < 0)
74,863✔
456
                return -EBADF;
457

458
        if (fcntl(fd, F_GETFD) < 0)
74,861✔
459
                return -errno;
27,885✔
460

461
        return 0;
462
}
463

464
int same_fd(int a, int b) {
14,856✔
465
        struct stat sta, stb;
14,856✔
466
        pid_t pid;
14,856✔
467
        int r, fa, fb;
14,856✔
468

469
        assert(a >= 0);
14,856✔
470
        assert(b >= 0);
14,856✔
471

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

481
        if (a == b) {
14,856✔
482
                /* Let's validate that the fd is valid */
483
                r = fd_validate(a);
7✔
484
                if (r < 0)
7✔
485
                        return r;
14,856✔
486

487
                return true;
6✔
488
        }
489

490
        /* Try to use F_DUPFD_QUERY if we have it first, as it is the nicest API */
491
        r = fcntl(a, F_DUPFD_QUERY, b);
14,849✔
492
        if (r > 0)
14,849✔
493
                return true;
494
        if (r == 0) {
14,841✔
495
                /* 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. */
496
                r = fd_validate(b);
14,839✔
497
                if (r < 0)
14,839✔
498
                        return r;
499

500
                return false;
14,839✔
501
        }
502
        /* 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. */
503
        if (errno == EBADF) {
2✔
504
                /* EBADF could mean two things: the first fd is not valid, or it is valid and is O_PATH and
505
                 * F_DUPFD_QUERY is not supported. Let's validate the fd explicitly, to distinguish this
506
                 * case. */
507
                r = fd_validate(a);
2✔
508
                if (r < 0)
2✔
509
                        return r;
510

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

515
        /* Try to use kcmp() if we have it. */
516
        pid = getpid_cached();
1✔
517
        r = kcmp(pid, pid, KCMP_FILE, a, b);
1✔
518
        if (r >= 0)
1✔
519
                return !r;
×
520
        if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
1✔
521
                return -errno;
1✔
522

523
        /* We have neither F_DUPFD_QUERY nor kcmp(), use fstat() instead. */
524
        if (fstat(a, &sta) < 0)
×
525
                return -errno;
×
526

527
        if (fstat(b, &stb) < 0)
×
528
                return -errno;
×
529

530
        if (!stat_inode_same(&sta, &stb))
×
531
                return false;
532

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

536
        if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
×
537
                return false;
538

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

545
        fb = fcntl(b, F_GETFL);
×
546
        if (fb < 0)
×
547
                return -errno;
×
548

549
        return fa == fb;
×
550
}
551

552
bool fdname_is_valid(const char *s) {
17,785✔
553
        const char *p;
17,785✔
554

555
        /* Validates a name for $LISTEN_FDNAMES. We basically allow
556
         * everything ASCII that's not a control character. Also, as
557
         * special exception the ":" character is not allowed, as we
558
         * use that as field separator in $LISTEN_FDNAMES.
559
         *
560
         * Note that the empty string is explicitly allowed
561
         * here. However, we limit the length of the names to 255
562
         * characters. */
563

564
        if (!s)
17,785✔
565
                return false;
566

567
        for (p = s; *p; p++) {
259,808✔
568
                if (*p < ' ')
242,034✔
569
                        return false;
570
                if (*p >= 127)
242,034✔
571
                        return false;
572
                if (*p == ':')
242,034✔
573
                        return false;
574
        }
575

576
        return p - s <= FDNAME_MAX;
17,774✔
577
}
578

579
int fd_get_path(int fd, char **ret) {
3,831,732✔
580
        int r;
3,831,732✔
581

582
        assert(fd >= 0 || IN_SET(fd, AT_FDCWD, XAT_FDROOT));
3,831,732✔
583

584
        if (fd == AT_FDCWD)
18,739✔
585
                return safe_getcwd(ret);
11✔
586
        if (fd == XAT_FDROOT)
3,831,721✔
587
                return strdup_to(ret, "/");
18,728✔
588

589
        r = readlink_malloc(FORMAT_PROC_FD_PATH(fd), ret);
3,812,993✔
590
        if (r == -ENOENT)
3,812,993✔
591
                return proc_fd_enoent_errno();
4✔
592
        return r;
593
}
594

595
int move_fd(int from, int to, int cloexec) {
19,335✔
596
        int r;
19,335✔
597

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

602
        if (from < 0)
19,335✔
603
                return -EBADF;
604
        if (to < 0)
19,335✔
605
                return -EBADF;
606

607
        if (from == to) {
19,335✔
608

609
                if (cloexec >= 0) {
×
610
                        r = fd_cloexec(to, cloexec);
×
611
                        if (r < 0)
×
612
                                return r;
613
                }
614

615
                return to;
×
616
        }
617

618
        if (cloexec < 0) {
19,335✔
619
                int fl;
×
620

621
                fl = fcntl(from, F_GETFD, 0);
×
622
                if (fl < 0)
×
623
                        return -errno;
×
624

625
                cloexec = FLAGS_SET(fl, FD_CLOEXEC);
×
626
        }
627

628
        r = dup3(from, to, cloexec ? O_CLOEXEC : 0);
38,670✔
629
        if (r < 0)
19,335✔
630
                return -errno;
×
631

632
        assert(r == to);
19,335✔
633

634
        safe_close(from);
19,335✔
635

636
        return to;
19,335✔
637
}
638

639
int fd_move_above_stdio(int fd) {
759,478✔
640
        int flags, copy;
759,478✔
641
        PROTECT_ERRNO;
759,478✔
642

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

656
        if (fd < 0 || fd > 2)
759,478✔
657
                return fd;
658

659
        flags = fcntl(fd, F_GETFD, 0);
132✔
660
        if (flags < 0)
132✔
661
                return fd;
662

663
        if (flags & FD_CLOEXEC)
132✔
664
                copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
118✔
665
        else
666
                copy = fcntl(fd, F_DUPFD, 3);
14✔
667
        if (copy < 0)
132✔
668
                return fd;
669

670
        assert(copy > 2);
132✔
671

672
        (void) close(fd);
132✔
673
        return copy;
674
}
675

676
int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd) {
16,721✔
677
        int fd[3] = { original_input_fd,             /* Put together an array of fds we work on */
16,721✔
678
                      original_output_fd,
679
                      original_error_fd },
680
            null_fd = -EBADF,                        /* If we open /dev/null, we store the fd to it here */
16,721✔
681
            copy_fd[3] = EBADF_TRIPLET,              /* This contains all fds we duplicate here
16,721✔
682
                                                      * temporarily, and hence need to close at the end. */
683
            r;
684
        bool null_readable, null_writable;
16,721✔
685

686
        /* Sets up stdin, stdout, stderr with the three file descriptors passed in. If any of the descriptors
687
         * is specified as -EBADF it will be connected with /dev/null instead. If any of the file descriptors
688
         * is passed as itself (e.g. stdin as STDIN_FILENO) it is left unmodified, but the O_CLOEXEC bit is
689
         * turned off should it be on.
690
         *
691
         * Note that if any of the passed file descriptors are > 2 they will be closed — both on success and
692
         * on failure! Thus, callers should assume that when this function returns the input fds are
693
         * invalidated.
694
         *
695
         * Note that when this function fails stdin/stdout/stderr might remain half set up!
696
         *
697
         * O_CLOEXEC is turned off for all three file descriptors (which is how it should be for
698
         * stdin/stdout/stderr). */
699

700
        null_readable = original_input_fd < 0;
16,721✔
701
        null_writable = original_output_fd < 0 || original_error_fd < 0;
16,721✔
702

703
        /* First step, open /dev/null once, if we need it */
704
        if (null_readable || null_writable) {
16,721✔
705

706
                /* Let's open this with O_CLOEXEC first, and convert it to non-O_CLOEXEC when we move the fd to the final position. */
707
                null_fd = open("/dev/null", (null_readable && null_writable ? O_RDWR :
27,291✔
708
                                             null_readable ? O_RDONLY : O_WRONLY) | O_CLOEXEC);
13,590✔
709
                if (null_fd < 0) {
13,701✔
710
                        r = -errno;
×
711
                        goto finish;
×
712
                }
713

714
                /* If this fd is in the 0…2 range, let's move it out of it */
715
                if (null_fd < 3) {
13,701✔
716
                        int copy;
13✔
717

718
                        copy = fcntl(null_fd, F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
13✔
719
                        if (copy < 0) {
13✔
720
                                r = -errno;
×
721
                                goto finish;
×
722
                        }
723

724
                        close_and_replace(null_fd, copy);
13✔
725
                }
726
        }
727

728
        /* Let's assemble fd[] with the fds to install in place of stdin/stdout/stderr */
729
        for (int i = 0; i < 3; i++)
66,884✔
730
                if (fd[i] < 0)
50,163✔
731
                        fd[i] = null_fd;        /* A negative parameter means: connect this one to /dev/null */
13,893✔
732
                else if (fd[i] != i && fd[i] < 3) {
36,270✔
733
                        /* 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. */
734
                        copy_fd[i] = fcntl(fd[i], F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
117✔
735
                        if (copy_fd[i] < 0) {
117✔
736
                                r = -errno;
×
737
                                goto finish;
×
738
                        }
739

740
                        fd[i] = copy_fd[i];
117✔
741
                }
742

743
        /* At this point we now have the fds to use in fd[], and they are all above the stdio range, so that
744
         * we have freedom to move them around. If the fds already were at the right places then the specific
745
         * fds are -EBADF. Let's now move them to the right places. This is the point of no return. */
746
        for (int i = 0; i < 3; i++)
66,884✔
747
                if (fd[i] == i) {
50,163✔
748
                        /* fd is already in place, but let's make sure O_CLOEXEC is off */
749
                        r = fd_cloexec(i, false);
6,165✔
750
                        if (r < 0)
6,165✔
751
                                goto finish;
×
752
                } else {
753
                        assert(fd[i] > 2);
43,998✔
754

755
                        if (dup2(fd[i], i) < 0) { /* Turns off O_CLOEXEC on the new fd. */
43,998✔
756
                                r = -errno;
×
757
                                goto finish;
×
758
                        }
759
                }
760

761
        r = 0;
762

763
finish:
16,721✔
764
        /* Close the original fds, but only if they were outside of the stdio range. Also, properly check for the same
765
         * fd passed in multiple times. */
766
        safe_close_above_stdio(original_input_fd);
16,721✔
767
        if (original_output_fd != original_input_fd)
16,721✔
768
                safe_close_above_stdio(original_output_fd);
16,429✔
769
        if (original_error_fd != original_input_fd && original_error_fd != original_output_fd)
16,721✔
770
                safe_close_above_stdio(original_error_fd);
16,255✔
771

772
        /* Close the copies we moved > 2 */
773
        close_many(copy_fd, 3);
16,721✔
774

775
        /* Close our null fd, if it's > 2 */
776
        safe_close_above_stdio(null_fd);
16,721✔
777

778
        return r;
16,721✔
779
}
780

781
int fd_reopen(int fd, int flags) {
1,551,059✔
782
        assert(fd >= 0 || IN_SET(fd, AT_FDCWD, XAT_FDROOT));
1,551,059✔
783
        assert(!FLAGS_SET(flags, O_CREAT));
1,551,059✔
784

785
        /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to
786
         * turn O_RDWR fds into O_RDONLY fds.
787
         *
788
         * This doesn't work on sockets (since they cannot be open()ed, ever).
789
         *
790
         * This implicitly resets the file read index to 0.
791
         *
792
         * If AT_FDCWD is specified as file descriptor gets an fd to the current cwd.
793
         *
794
         * If XAT_FDROOT is specified as fd get an fd to the root directory.
795
         *
796
         * If the specified file descriptor refers to a symlink via O_PATH, then this function cannot be used
797
         * to follow that symlink. Because we cannot have non-O_PATH fds to symlinks reopening it without
798
         * O_PATH will always result in -ELOOP. Or in other words: if you have an O_PATH fd to a symlink you
799
         * can reopen it only if you pass O_PATH again. */
800

801
        if (FLAGS_SET(flags, O_NOFOLLOW))
1,551,059✔
802
                /* O_NOFOLLOW is not allowed in fd_reopen(), because after all this is primarily implemented
803
                 * via a symlink-based interface in /proc/self/fd. Let's refuse this here early. Note that
804
                 * the kernel would generate ELOOP here too, hence this manual check is mostly redundant –
805
                 * the only reason we add it here is so that the O_DIRECTORY special case (see below) behaves
806
                 * the same way as the non-O_DIRECTORY case. */
807
                return -ELOOP;
1,551,059✔
808

809
        if (fd == XAT_FDROOT)
1,551,057✔
810
                return RET_NERRNO(open("/", flags | O_DIRECTORY));
1✔
811

812
        if (FLAGS_SET(flags, O_DIRECTORY) || fd == AT_FDCWD)
1,551,056✔
813
                /* If we shall reopen the fd as directory we can just go via "." and thus bypass the whole
814
                 * magic /proc/ directory, and make ourselves independent of that being mounted. */
815
                return RET_NERRNO(openat(fd, ".", flags | O_DIRECTORY));
240,199✔
816

817
        int new_fd = open(FORMAT_PROC_FD_PATH(fd), flags);
1,310,859✔
818
        if (new_fd < 0) {
1,310,859✔
819
                if (errno != ENOENT)
48,757✔
820
                        return -errno;
48,756✔
821

822
                return proc_fd_enoent_errno();
1✔
823
        }
824

825
        return new_fd;
826
}
827

828
int fd_reopen_propagate_append_and_position(int fd, int flags) {
42✔
829
        /* Invokes fd_reopen(fd, flags), but propagates O_APPEND if set on original fd, and also tries to
830
         * keep current file position.
831
         *
832
         * You should use this if the original fd potentially is O_APPEND, otherwise we get rather
833
         * "unexpected" behavior. Unless you intentionally want to overwrite pre-existing data, and have
834
         * your output overwritten by the next user.
835
         *
836
         * Use case: "systemd-run --pty >> some-log".
837
         *
838
         * The "keep position" part is obviously nonsense for the O_APPEND case, but should reduce surprises
839
         * if someone carefully pre-positioned the passed in original input or non-append output FDs. */
840

841
        assert(fd >= 0);
42✔
842
        assert(!(flags & (O_APPEND|O_DIRECTORY)));
42✔
843

844
        int existing_flags = fcntl(fd, F_GETFL);
42✔
845
        if (existing_flags < 0)
42✔
846
                return -errno;
×
847

848
        int new_fd = fd_reopen(fd, flags | (existing_flags & O_APPEND));
42✔
849
        if (new_fd < 0)
42✔
850
                return new_fd;
851

852
        /* Try to adjust the offset, but ignore errors. */
853
        off_t p = lseek(fd, 0, SEEK_CUR);
31✔
854
        if (p > 0) {
31✔
855
                off_t new_p = lseek(new_fd, p, SEEK_SET);
×
856
                if (new_p < 0)
×
857
                        log_debug_errno(errno,
×
858
                                        "Failed to propagate file position for re-opened fd %d, ignoring: %m",
859
                                        fd);
860
                else if (new_p != p)
×
861
                        log_debug("Failed to propagate file position for re-opened fd %d (%lld != %lld), ignoring.",
×
862
                                  fd, (long long) new_p, (long long) p);
863
        }
864

865
        return new_fd;
866
}
867

868
int fd_reopen_condition(
1,166,422✔
869
                int fd,
870
                int flags,
871
                int mask,
872
                int *ret_new_fd) {
873

874
        int r, new_fd;
1,166,422✔
875

876
        assert(fd >= 0);
1,166,422✔
877
        assert(!FLAGS_SET(flags, O_CREAT));
1,166,422✔
878

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

883
        r = fcntl(fd, F_GETFL);
1,166,422✔
884
        if (r < 0)
1,166,422✔
885
                return -errno;
×
886

887
        if ((r & mask) == (flags & mask)) {
1,166,422✔
888
                *ret_new_fd = -EBADF;
1,159,579✔
889
                return fd;
1,159,579✔
890
        }
891

892
        new_fd = fd_reopen(fd, flags);
6,843✔
893
        if (new_fd < 0)
6,843✔
894
                return new_fd;
895

896
        *ret_new_fd = new_fd;
6,843✔
897
        return new_fd;
6,843✔
898
}
899

900
int fd_is_opath(int fd) {
456,318✔
901
        int r;
456,318✔
902

903
        assert(fd >= 0);
456,318✔
904

905
        r = fcntl(fd, F_GETFL);
456,318✔
906
        if (r < 0)
456,318✔
907
                return -errno;
×
908

909
        return FLAGS_SET(r, O_PATH);
456,318✔
910
}
911

912
int fd_vet_accmode(int fd, int mode) {
1,542✔
913
        int flags;
1,542✔
914

915
        /* Check if fd is opened with desired access mode.
916
         *
917
         * Returns > 0 on strict match, == 0 if opened for both reading and writing (partial match),
918
         * -EPROTOTYPE otherwise. O_PATH fds are always refused with -EBADFD.
919
         *
920
         * Note that while on O_DIRECTORY -EISDIR will be returned, this should not be relied upon as
921
         * the flag might not have been specified when open() was called originally. */
922

923
        assert(fd >= 0);
1,542✔
924
        assert(IN_SET(mode, O_RDONLY, O_WRONLY, O_RDWR));
1,542✔
925

926
        flags = fcntl(fd, F_GETFL);
1,542✔
927
        if (flags < 0)
1,542✔
928
                return -errno;
1✔
929

930
        /* O_TMPFILE in userspace is defined with O_DIRECTORY OR'ed in, so explicitly permit it.
931
         *
932
         * C.f. https://elixir.bootlin.com/linux/v6.17.7/source/include/uapi/asm-generic/fcntl.h#L92 */
933
        if (FLAGS_SET(flags, O_DIRECTORY) && !FLAGS_SET(flags, O_TMPFILE))
1,541✔
934
                return -EISDIR;
935

936
        if (FLAGS_SET(flags, O_PATH))
1,541✔
937
                return -EBADFD;
938

939
        flags &= O_ACCMODE_STRICT;
1,537✔
940

941
        if (flags == mode)
1,537✔
942
                return 1;
943

944
        if (flags == O_RDWR)
953✔
945
                return 0;
948✔
946

947
        return -EPROTOTYPE;
948
}
949

950
int fd_is_writable(int fd) {
198✔
951
        int r;
198✔
952

953
        assert(fd >= 0);
198✔
954

955
        r = fd_vet_accmode(fd, O_WRONLY);
198✔
956
        if (r >= 0)
198✔
957
                return true;
958

959
        if (IN_SET(r, -EPROTOTYPE, -EBADFD, -EISDIR))
3✔
960
                return false;
2✔
961

962
        return r;
963
}
964

965
int fd_verify_safe_flags_full(int fd, int extra_flags) {
1,011✔
966
        int flags, unexpected_flags;
1,011✔
967

968
        /* Check if an extrinsic fd is safe to work on (by a privileged service). This ensures that clients
969
         * can't trick a privileged service into giving access to a file the client doesn't already have
970
         * access to (especially via something like O_PATH).
971
         *
972
         * O_NOFOLLOW: For some reason the kernel will return this flag from fcntl(); it doesn't go away
973
         *             immediately after open(). It should have no effect whatsoever to an already-opened FD,
974
         *             and since we refuse O_PATH it should be safe.
975
         *
976
         * RAW_O_LARGEFILE: glibc secretly sets this and neglects to hide it from us if we call fcntl.
977
         *                  See comment in src/basic/include/fcntl.h for more details about this.
978
         *
979
         * If 'extra_flags' is specified as non-zero the included flags are also allowed.
980
         */
981

982
        assert(fd >= 0);
1,011✔
983

984
        flags = fcntl(fd, F_GETFL);
1,011✔
985
        if (flags < 0)
1,011✔
986
                return -errno;
×
987

988
        unexpected_flags = flags & ~(O_ACCMODE_STRICT|O_NOFOLLOW|RAW_O_LARGEFILE|extra_flags);
1,011✔
989
        if (unexpected_flags != 0)
1,011✔
990
                return log_debug_errno(SYNTHETIC_ERRNO(EREMOTEIO),
×
991
                                       "Unexpected flags set for extrinsic fd: 0%o",
992
                                       (unsigned) unexpected_flags);
993

994
        return flags & (O_ACCMODE_STRICT | extra_flags); /* return the flags variable, but remove the noise */
1,011✔
995
}
996

997
unsigned read_nr_open(void) {
26,552✔
998
        _cleanup_free_ char *nr_open = NULL;
26,552✔
999
        int r;
26,552✔
1000

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

1004
        r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
26,552✔
1005
        if (r < 0)
26,552✔
1006
                log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m");
26,552✔
1007
        else {
1008
                unsigned v;
26,552✔
1009

1010
                r = safe_atou(nr_open, &v);
26,552✔
1011
                if (r < 0)
26,552✔
1012
                        log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open);
×
1013
                else
1014
                        return v;
26,552✔
1015
        }
1016

1017
        /* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */
1018
        return NR_OPEN_DEFAULT;
1019
}
1020

1021
int fd_get_diskseq(int fd, uint64_t *ret) {
71,183✔
1022
        uint64_t diskseq;
71,183✔
1023

1024
        assert(fd >= 0);
71,183✔
1025
        assert(ret);
71,183✔
1026

1027
        if (ioctl(fd, BLKGETDISKSEQ, &diskseq) < 0) {
71,183✔
1028
                /* Note that the kernel is weird: non-existing ioctls currently return EINVAL
1029
                 * rather than ENOTTY on loopback block devices. They should fix that in the kernel,
1030
                 * but in the meantime we accept both here. */
1031
                if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EINVAL)
×
1032
                        return -errno;
×
1033

1034
                return -EOPNOTSUPP;
1035
        }
1036

1037
        *ret = diskseq;
71,183✔
1038

1039
        return 0;
71,183✔
1040
}
1041

1042
static bool is_literal_root(const char *p) {
107,803✔
1043
        if (!p)
107,803✔
1044
                return false;
1045

1046
        /* Check if string consists of at least one '/', and possibly more, but nothing else */
1047
        size_t n = strspn(p, "/");
80,631✔
1048
        return n >= 1 && p[n] == 0;
161,250✔
1049
}
1050

1051
int path_is_root_at(int dir_fd, const char *path) {
3,732,703✔
1052
        assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT));
3,732,703✔
1053

1054
        if (dir_fd == XAT_FDROOT && isempty(path))
107,804✔
1055
                return true;
3,732,703✔
1056

1057
        if (IN_SET(dir_fd, XAT_FDROOT, AT_FDCWD) && is_literal_root(path))
3,732,702✔
1058
                return true;
1059

1060
        _cleanup_close_ int fd = -EBADF;
3,732,703✔
1061
        if (!isempty(path)) {
3,732,690✔
1062
                fd = xopenat(dir_fd, path, O_PATH|O_DIRECTORY|O_CLOEXEC);
81,052✔
1063
                if (fd == -ENOTDIR)
81,052✔
1064
                        return false; /* the root dir must be a dir */
1065
                if (fd < 0)
79,667✔
1066
                        return fd;
1067

1068
                dir_fd = fd;
1069
        }
1070

1071
        /* Even if the root directory has the same inode as our fd, the fd may not point to the root
1072
         * directory "/", and we also need to check that the mount ids are the same. Otherwise, a construct
1073
         * like the following could be used to trick us:
1074
         *
1075
         * $ mkdir /tmp/x
1076
         * $ mount --bind / /tmp/x
1077
         */
1078

1079
        return fds_inode_and_mount_same(dir_fd, XAT_FDROOT);
3,714,006✔
1080
}
1081

1082
int fds_inode_and_mount_same(int fd1, int fd2) {
3,714,023✔
1083
        struct statx sx1, sx2;
3,714,023✔
1084
        int r;
3,714,023✔
1085

1086
        assert(fd1 >= 0 || IN_SET(fd1, AT_FDCWD, XAT_FDROOT));
3,714,023✔
1087
        assert(fd2 >= 0 || IN_SET(fd2, AT_FDCWD, XAT_FDROOT));
3,714,023✔
1088

1089
        r = xstatx(fd1, /* path = */ NULL, AT_EMPTY_PATH,
3,714,023✔
1090
                   STATX_TYPE|STATX_INO|STATX_MNT_ID,
1091
                   &sx1);
1092
        if (r < 0)
3,714,023✔
1093
                return r;
3,714,023✔
1094

1095
        if (fd1 == fd2) /* Shortcut things if fds are the same (only after validating the fd) */
3,714,023✔
1096
                return true;
1097

1098
        r = xstatx(fd2, /* path = */ NULL, AT_EMPTY_PATH,
3,714,021✔
1099
                   STATX_TYPE|STATX_INO|STATX_MNT_ID,
1100
                   &sx2);
1101
        if (r < 0)
3,714,021✔
1102
                return r;
1103

1104
        r = statx_mount_same(&sx1, &sx2);
3,714,021✔
1105
        if (r <= 0)
3,714,021✔
1106
                return r;
1107

1108
        return statx_inode_same(&sx1, &sx2);
3,467,908✔
1109
}
1110

1111
int resolve_xat_fdroot(int *fd, const char **path, char **ret_buffer) {
32,660,447✔
1112
        assert(fd);
32,660,447✔
1113
        assert(path);
32,660,447✔
1114
        assert(ret_buffer);
32,660,447✔
1115

1116
        if (*fd != XAT_FDROOT) {
32,660,447✔
1117
                *ret_buffer = NULL;
28,946,438✔
1118
                return 0;
28,946,438✔
1119
        }
1120

1121
        if (isempty(*path)) {
3,714,009✔
1122
                *path = "/";
3,714,009✔
1123
                *ret_buffer = NULL;
3,714,009✔
1124
        } else if (!path_is_absolute(*path)) {
×
1125
                char *p = strjoin("/", *path);
×
1126
                if (!p)
×
1127
                        return -ENOMEM;
1128

1129
                *path = *ret_buffer = p;
×
1130
        }
1131

1132
        *fd = AT_FDCWD;
3,714,009✔
1133

1134
        return 1;
3,714,009✔
1135
}
1136

1137
char* format_proc_fd_path(char buf[static PROC_FD_PATH_MAX], int fd) {
5,439,160✔
1138
        assert(buf);
5,439,160✔
1139
        assert(fd >= 0);
5,439,160✔
1140
        assert_se(snprintf_ok(buf, PROC_FD_PATH_MAX, "/proc/self/fd/%i", fd));
5,439,160✔
1141
        return buf;
5,439,160✔
1142
}
1143

1144
const char* accmode_to_string(int flags) {
155✔
1145
        switch (flags & O_ACCMODE_STRICT) {
155✔
1146
        case O_RDONLY:
1147
                return "ro";
1148
        case O_WRONLY:
3✔
1149
                return "wo";
3✔
1150
        case O_RDWR:
149✔
1151
                return "rw";
149✔
1152
        default:
×
1153
                return NULL;
×
1154
        }
1155
}
1156

1157
char* format_proc_pid_fd_path(char buf[static PROC_PID_FD_PATH_MAX], pid_t pid, int fd) {
1✔
1158
        assert(buf);
1✔
1159
        assert(fd >= 0);
1✔
1160
        assert(pid >= 0);
1✔
1161
        assert_se(snprintf_ok(buf, PROC_PID_FD_PATH_MAX, "/proc/" PID_FMT "/fd/%i", pid == 0 ? getpid_cached() : pid, fd));
1✔
1162
        return buf;
1✔
1163
}
1164

1165
int proc_fd_enoent_errno(void) {
5✔
1166
        int r;
5✔
1167

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

1172
        r = proc_mounted();
5✔
1173
        if (r == 0)
5✔
1174
                return -ENOSYS;  /* /proc/ is not available or not set up properly, we're most likely
1175
                                    in some chroot environment. */
1176
        if (r > 0)
5✔
1177
                return -EBADF;   /* If /proc/ is definitely around then this means the fd is not valid. */
5✔
1178

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