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

drakenclimber / libseccomp / 17297658954

28 Aug 2025 01:20PM UTC coverage: 89.436% (-1.3%) from 90.771%
17297658954

push

github

drakenclimber
doc: Add documentation for max kernel version attributes

Add documentation for SCMP_FLTATR_ACT_UNKNOWN and SCMP_FLTATR_CTL_KVER.

Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>

3234 of 3616 relevant lines covered (89.44%)

1248351.32 hits per line

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

81.86
/src/system.c
1
/**
2
 * Seccomp System Interfaces
3
 *
4
 * Copyright (c) 2014 Red Hat <pmoore@redhat.com>
5
 * Author: Paul Moore <paul@paul-moore.com>
6
 */
7

8
/*
9
 * This library is free software; you can redistribute it and/or modify it
10
 * under the terms of version 2.1 of the GNU Lesser General Public License as
11
 * published by the Free Software Foundation.
12
 *
13
 * This library is distributed in the hope that it will be useful, but WITHOUT
14
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
16
 * for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this library; if not, see <http://www.gnu.org/licenses>.
20
 */
21

22
#include <stdlib.h>
23
#include <errno.h>
24
#include <sys/prctl.h>
25

26
#define _GNU_SOURCE
27
#include <unistd.h>
28

29
#include "system.h"
30

31
#include <seccomp.h>
32

33
#include "arch.h"
34
#include "db.h"
35
#include "gen_bpf.h"
36
#include "helper.h"
37

38
/* NOTE: the seccomp syscall allowlist is currently disabled for testing
39
 *       purposes, but unless we can verify all of the supported ABIs before
40
 *       our next release we may have to enable the allowlist */
41
#define SYSCALL_ALLOWLIST_ENABLE        0
42

43
/* task global state */
44
struct task_state {
45
        /* seccomp(2) syscall */
46
        int nr_seccomp;
47

48
        /* userspace notification fd */
49
        int notify_fd;
50

51
        /* runtime support flags */
52
        int sup_syscall;
53
        int sup_flag_tsync;
54
        int sup_flag_log;
55
        int sup_action_log;
56
        int sup_kill_process;
57
        int sup_flag_spec_allow;
58
        int sup_flag_new_listener;
59
        int sup_user_notif;
60
        int sup_flag_tsync_esrch;
61
        int sup_flag_wait_kill;
62
};
63
static struct task_state state = {
64
        .nr_seccomp = -1,
65

66
        .notify_fd = -1,
67

68
        .sup_syscall = -1,
69
        .sup_flag_tsync = -1,
70
        .sup_flag_log = -1,
71
        .sup_action_log = -1,
72
        .sup_kill_process = -1,
73
        .sup_flag_spec_allow = -1,
74
        .sup_flag_new_listener = -1,
75
        .sup_user_notif = -1,
76
        .sup_flag_tsync_esrch = -1,
77
        .sup_flag_wait_kill = -1,
78
};
79

80
/**
81
 * Reset the task state
82
 *
83
 * This function fully resets the library's global "system task state".
84
 *
85
 */
86
void sys_reset_state(void)
1✔
87
{
88
        state.nr_seccomp = -1;
1✔
89

90
        if (state.notify_fd > 0)
1✔
91
                close(state.notify_fd);
×
92
        state.notify_fd = -1;
1✔
93

94
        state.sup_syscall = -1;
1✔
95
        state.sup_flag_tsync = -1;
1✔
96
        state.sup_flag_log = -1;
1✔
97
        state.sup_action_log = -1;
1✔
98
        state.sup_kill_process = -1;
1✔
99
        state.sup_flag_spec_allow = -1;
1✔
100
        state.sup_flag_new_listener = -1;
1✔
101
        state.sup_user_notif = -1;
1✔
102
        state.sup_flag_tsync_esrch = -1;
1✔
103
}
1✔
104

105
/**
106
 * Check to see if the seccomp() syscall is supported
107
 *
108
 * This function attempts to see if the system supports the seccomp() syscall.
109
 * Unfortunately, there are a few reasons why this check may fail, including
110
 * a previously loaded seccomp filter, so it is hard to say for certain.
111
 * Return one if the syscall is supported, zero otherwise.
112
 *
113
 */
114
int sys_chk_seccomp_syscall(void)
77,852✔
115
{
116
        int rc;
77,852✔
117
        int nr_seccomp;
77,852✔
118

119
        /* NOTE: it is reasonably safe to assume that we should be able to call
120
         *       seccomp() when the caller first starts, but we can't rely on
121
         *       it later so we need to cache our findings for use later */
122
        if (state.sup_syscall >= 0)
77,852✔
123
                return state.sup_syscall;
124

125
#if SYSCALL_ALLOWLIST_ENABLE
126
        /* architecture allowlist */
127
        switch (arch_def_native->token) {
128
        case SCMP_ARCH_X86_64:
129
        case SCMP_ARCH_ARM:
130
        case SCMP_ARCH_AARCH64:
131
        case SCMP_ARCH_LOONGARCH64:
132
        case SCMP_ARCH_PPC64:
133
        case SCMP_ARCH_PPC64LE:
134
        case SCMP_ARCH_S390:
135
        case SCMP_ARCH_S390X:
136
        case SCMP_ARCH_RISCV64:
137
                break;
138
        default:
139
                goto unsupported;
140
        }
141
#endif
142

143
        nr_seccomp = arch_syscall_resolve_name(arch_def_native, "seccomp");
7,786✔
144
        if (nr_seccomp < 0)
7,786✔
145
                goto unsupported;
×
146

147
        /* this is an invalid call because the second argument is non-zero, but
148
         * depending on the errno value of ENOSYS or EINVAL we can guess if the
149
         * seccomp() syscall is supported or not */
150
        rc = syscall(nr_seccomp, SECCOMP_SET_MODE_STRICT, 1, NULL);
7,786✔
151
        if (rc < 0 && errno == EINVAL)
7,786✔
152
                goto supported;
7,786✔
153

154
unsupported:
×
155
        state.sup_syscall = 0;
×
156
        return 0;
×
157
supported:
7,786✔
158
        state.nr_seccomp = nr_seccomp;
7,786✔
159
        state.sup_syscall = 1;
7,786✔
160
        return 1;
7,786✔
161
}
162

163
/**
164
 * Force the seccomp() syscall support setting
165
 * @param enable the intended support state
166
 *
167
 * This function overrides the current seccomp() syscall support setting; this
168
 * is very much a "use at your own risk" function.
169
 *
170
 */
171
void sys_set_seccomp_syscall(bool enable)
723✔
172
{
173
        state.sup_syscall = (enable ? 1 : 0);
723✔
174
}
723✔
175

176
/**
177
 * Check to see if a seccomp action is supported
178
 * @param action the seccomp action
179
 *
180
 * This function checks to see if a seccomp action is supported by the system.
181
 * Return one if the action is supported, zero otherwise.
182
 *
183
 */
184
int sys_chk_seccomp_action(uint32_t action)
90,079✔
185
{
186
        if (action == SCMP_ACT_KILL_PROCESS) {
90,079✔
187
                if (state.sup_kill_process < 0) {
8,140✔
188
                        if (sys_chk_seccomp_syscall() == 1 &&
15,570✔
189
                            syscall(state.nr_seccomp,
7,785✔
190
                                    SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0)
191
                                state.sup_kill_process = 1;
7,785✔
192
                        else
193
                                state.sup_kill_process = 0;
×
194
                }
195

196
                return state.sup_kill_process;
8,140✔
197
        } else if (action == SCMP_ACT_KILL_THREAD) {
81,939✔
198
                return 1;
199
        } else if (action == SCMP_ACT_TRAP) {
71,803✔
200
                return 1;
201
        } else if ((action == SCMP_ACT_ERRNO(action & 0x0000ffff)) &&
70,780✔
202
                   ((action & 0x0000ffff) < MAX_ERRNO)) {
203
                return 1;
204
        } else if (action == SCMP_ACT_TRACE(action & 0x0000ffff)) {
63,509✔
205
                return 1;
206
        } else if (action == SCMP_ACT_LOG) {
63,160✔
207
                if (state.sup_action_log < 0) {
8,485✔
208
                        if (sys_chk_seccomp_syscall() == 1 &&
15,570✔
209
                            syscall(state.nr_seccomp,
7,785✔
210
                                    SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0)
211
                                state.sup_action_log = 1;
7,785✔
212
                        else
213
                                state.sup_action_log = 0;
×
214
                }
215

216
                return state.sup_action_log;
8,485✔
217
        } else if (action == SCMP_ACT_ALLOW) {
54,675✔
218
                return 1;
219
        } else if (action == SCMP_ACT_NOTIFY) {
7,789✔
220
                if (state.sup_user_notif < 0) {
7,785✔
221
                        struct seccomp_notif_sizes sizes;
7,785✔
222
                        if (sys_chk_seccomp_syscall() == 1 &&
15,570✔
223
                            syscall(state.nr_seccomp,
7,785✔
224
                                    SECCOMP_GET_NOTIF_SIZES, 0, &sizes) == 0)
225
                                state.sup_user_notif = 1;
7,785✔
226
                        else
227
                                state.sup_user_notif = 0;
×
228
                }
229

230
                return state.sup_user_notif;
7,785✔
231
        }
232

233
        return 0;
234
}
235

236
/**
237
 * Force a seccomp action support setting
238
 * @param action the seccomp action
239
 * @param enable the intended support state
240
 *
241
 * This function overrides the current seccomp action support setting; this
242
 * is very much a "use at your own risk" function.
243
 */
244
void sys_set_seccomp_action(uint32_t action, bool enable)
2,169✔
245
{
246
        switch (action) {
2,169✔
247
        case SCMP_ACT_LOG:
723✔
248
                state.sup_action_log = (enable ? 1 : 0);
723✔
249
                break;
723✔
250
        case SCMP_ACT_KILL_PROCESS:
723✔
251
                state.sup_kill_process = (enable ? 1 : 0);
723✔
252
                break;
723✔
253
        case SCMP_ACT_NOTIFY:
723✔
254
                state.sup_user_notif = (enable ? 1 : 0);
723✔
255
                break;
723✔
256
        }
257
}
2,169✔
258

259
/**
260
 * Check to see if a seccomp() flag is supported by the kernel
261
 * @param flag the seccomp() flag
262
 *
263
 * This function checks to see if a seccomp() flag is supported by the kernel.
264
 * Return one if the flag is supported, zero otherwise.
265
 *
266
 */
267
static int _sys_chk_flag_kernel(int flag)
46,711✔
268
{
269
        /* this is an invalid seccomp(2) call because the last argument
270
         * is NULL, but depending on the errno value of EFAULT we can
271
         * guess if the filter flag is supported or not */
272
        if (sys_chk_seccomp_syscall() == 1 &&
93,422✔
273
            syscall(state.nr_seccomp,
46,711✔
274
                    SECCOMP_SET_MODE_FILTER, flag, NULL) == -1 &&
46,711✔
275
            errno == EFAULT)
46,711✔
276
                return 1;
277

278
        return 0;
279
}
280

281
/**
282
 * Check to see if a seccomp() flag is supported
283
 * @param flag the seccomp() flag
284
 *
285
 * This function checks to see if a seccomp() flag is supported by the system.
286
 * Return one if the syscall is supported, zero if unsupported, negative values
287
 * on error.
288
 *
289
 */
290
int sys_chk_seccomp_flag(int flag)
112,325✔
291
{
292
        switch (flag) {
112,325✔
293
        case SECCOMP_FILTER_FLAG_TSYNC:
7,787✔
294
                if (state.sup_flag_tsync < 0)
7,787✔
295
                        state.sup_flag_tsync = _sys_chk_flag_kernel(flag);
7,785✔
296
                return state.sup_flag_tsync;
7,787✔
297
        case SECCOMP_FILTER_FLAG_LOG:
7,787✔
298
                if (state.sup_flag_log < 0)
7,787✔
299
                        state.sup_flag_log = _sys_chk_flag_kernel(flag);
7,785✔
300
                return state.sup_flag_log;
7,787✔
301
        case SECCOMP_FILTER_FLAG_SPEC_ALLOW:
7,787✔
302
                if (state.sup_flag_spec_allow < 0)
7,787✔
303
                        state.sup_flag_spec_allow = _sys_chk_flag_kernel(flag);
7,785✔
304
                return state.sup_flag_spec_allow;
7,787✔
305
        case SECCOMP_FILTER_FLAG_NEW_LISTENER:
15,570✔
306
                if (state.sup_flag_new_listener < 0)
15,570✔
307
                        state.sup_flag_new_listener = _sys_chk_flag_kernel(flag);
7,785✔
308
                return state.sup_flag_new_listener;
15,570✔
309
        case SECCOMP_FILTER_FLAG_TSYNC_ESRCH:
65,609✔
310
                if (state.sup_flag_tsync_esrch < 0)
65,609✔
311
                        state.sup_flag_tsync_esrch = _sys_chk_flag_kernel(flag);
7,786✔
312
                return state.sup_flag_tsync_esrch;
65,609✔
313
        case SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV:
7,785✔
314
                if (state.sup_flag_wait_kill < 0) {
7,785✔
315
                        /* kernel requires NEW_LISTENER with WAIT_KILLABLE_RECV */
316
                        flag |= SECCOMP_FILTER_FLAG_NEW_LISTENER;
7,785✔
317
                        sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER);
7,785✔
318
                        if (state.sup_flag_new_listener) {
7,785✔
319
                                state.sup_flag_wait_kill = _sys_chk_flag_kernel(flag);
7,785✔
320
                        } else {
321
                                state.sup_flag_wait_kill = 0;
×
322
                        }
323
                }
324
                return state.sup_flag_wait_kill;
7,785✔
325
        }
326

327
        return -EOPNOTSUPP;
328
}
329

330
/**
331
 * Force a seccomp() syscall flag support setting
332
 * @param flag the seccomp() flag
333
 * @param enable the intended support state
334
 *
335
 * This function overrides the current seccomp() syscall support setting for a
336
 * given flag; this is very much a "use at your own risk" function.
337
 *
338
 */
339
void sys_set_seccomp_flag(int flag, bool enable)
4,338✔
340
{
341
        switch (flag) {
4,338✔
342
        case SECCOMP_FILTER_FLAG_TSYNC:
723✔
343
                state.sup_flag_tsync = (enable ? 1 : 0);
723✔
344
                break;
723✔
345
        case SECCOMP_FILTER_FLAG_LOG:
723✔
346
                state.sup_flag_log = (enable ? 1 : 0);
723✔
347
                break;
723✔
348
        case SECCOMP_FILTER_FLAG_SPEC_ALLOW:
723✔
349
                state.sup_flag_spec_allow = (enable ? 1 : 0);
723✔
350
                break;
723✔
351
        case SECCOMP_FILTER_FLAG_NEW_LISTENER:
723✔
352
                state.sup_flag_new_listener = (enable ? 1 : 0);
723✔
353
                break;
723✔
354
        case SECCOMP_FILTER_FLAG_TSYNC_ESRCH:
723✔
355
                state.sup_flag_tsync_esrch = (enable ? 1 : 0);
723✔
356
                break;
723✔
357
        case SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV:
723✔
358
                state.sup_flag_wait_kill = (enable ? 1 : 0);
723✔
359
                break;
723✔
360
        }
361
}
4,338✔
362

363
/**
364
 * Loads the filter into the kernel
365
 * @param col the filter collection
366
 * @param rawrc pass the raw return code if true
367
 *
368
 * This function loads the given seccomp filter context into the kernel.  If
369
 * the filter was loaded correctly, the kernel will be enforcing the filter
370
 * when this function returns.  Returns zero on success, negative values on
371
 * error.
372
 *
373
 */
374
int sys_filter_load(struct db_filter_col *col, bool rawrc)
1✔
375
{
376
        int rc;
1✔
377
        bool tsync_notify;
1✔
378
        bool listener_req;
1✔
379
        struct bpf_program *prgm = NULL;
1✔
380

381
        rc = db_col_precompute(col);
1✔
382
        if (rc < 0)
1✔
383
                return rc;
384
        prgm = col->prgm_bpf;
1✔
385

386
        /* attempt to set NO_NEW_PRIVS */
387
        if (col->attr.nnp_enable) {
1✔
388
                rc = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1✔
389
                if (rc < 0)
1✔
390
                        goto filter_load_out;
×
391
        }
392

393
        tsync_notify = state.sup_flag_tsync_esrch > 0 && state.notify_fd == -1;
1✔
394
        listener_req = state.sup_user_notif > 0 && \
3✔
395
                       col->notify_used && state.notify_fd == -1;
1✔
396

397
        /* load the filter into the kernel */
398
        if (sys_chk_seccomp_syscall() == 1) {
1✔
399
                int flgs = 0;
1✔
400
                if (tsync_notify) {
1✔
401
                        if (col->attr.tsync_enable)
1✔
402
                                flgs |= SECCOMP_FILTER_FLAG_TSYNC | \
1✔
403
                                        SECCOMP_FILTER_FLAG_TSYNC_ESRCH;
404
                        if (listener_req)
1✔
405
                                flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER;
×
406
                } else if (col->attr.tsync_enable) {
×
407
                        if (listener_req) {
×
408
                                /* NOTE: we _should_ catch this in db.c */
409
                                rc = -EFAULT;
×
410
                                goto filter_load_out;
×
411
                        }
412
                        flgs |= SECCOMP_FILTER_FLAG_TSYNC;
413
                } else if (listener_req)
×
414
                        flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER;
×
415
                if ((flgs & SECCOMP_FILTER_FLAG_NEW_LISTENER) &&
1✔
416
                    col->attr.wait_killable_recv)
×
417
                        flgs |= SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV;
×
418
                if (col->attr.log_enable)
1✔
419
                        flgs |= SECCOMP_FILTER_FLAG_LOG;
1✔
420
                if (col->attr.spec_allow)
1✔
421
                        flgs |= SECCOMP_FILTER_FLAG_SPEC_ALLOW;
1✔
422
                rc = syscall(state.nr_seccomp,
1✔
423
                             SECCOMP_SET_MODE_FILTER, flgs, prgm);
424
                if (tsync_notify && rc > 0) {
1✔
425
                        /* return 0 on NEW_LISTENER success, but save the fd */
426
                        state.notify_fd = rc;
×
427
                        rc = 0;
×
428
                } else if (rc > 0 && col->attr.tsync_enable) {
1✔
429
                        /* always return -ESRCH if we fail to sync threads */
430
                        errno = ESRCH;
×
431
                        rc = -errno;
×
432
                } else if (rc > 0 && state.sup_user_notif > 0) {
×
433
                        /* return 0 on NEW_LISTENER success, but save the fd */
434
                        state.notify_fd = rc;
×
435
                        rc = 0;
×
436
                }
437
        } else
438
                rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prgm);
×
439

440
filter_load_out:
1✔
441
        /* cleanup and return */
442
        if (rc == -ESRCH)
1✔
443
                return -ESRCH;
444
        if (rc < 0)
1✔
445
                return (rawrc ? -errno : -ECANCELED);
×
446
        return rc;
447
}
448

449
/**
450
 * Return the userspace notification fd
451
 *
452
 * This function returns the userspace notification fd from
453
 * SECCOMP_FILTER_FLAG_NEW_LISTENER.  If the notification fd has not yet been
454
 * set, or an error has occurred, -1 is returned.
455
 *
456
 */
457
int sys_notify_fd(void)
1✔
458
{
459
        return state.notify_fd;
1✔
460
}
461

462
/**
463
 * Allocate a pair of notification request/response structures
464
 * @param req the request location
465
 * @param resp the response location
466
 *
467
 * This function allocates a pair of request/response structure by computing
468
 * the correct sized based on the currently running kernel. It returns zero on
469
 * success, and negative values on failure.
470
 *
471
 */
472
int sys_notify_alloc(struct seccomp_notif **req,
3✔
473
                     struct seccomp_notif_resp **resp)
474
{
475
        int rc;
3✔
476
        static struct seccomp_notif_sizes sizes = { 0, 0, 0 };
3✔
477

478
        if (state.sup_syscall <= 0)
3✔
479
                return -EOPNOTSUPP;
480

481
        if (sizes.seccomp_notif == 0 && sizes.seccomp_notif_resp == 0) {
3✔
482
                rc = syscall(__NR_seccomp, SECCOMP_GET_NOTIF_SIZES, 0, &sizes);
1✔
483
                if (rc < 0)
1✔
484
                        return -ECANCELED;
485
        }
486
        if (sizes.seccomp_notif == 0 || sizes.seccomp_notif_resp == 0)
3✔
487
                return -EFAULT;
488

489
        if (req) {
3✔
490
                *req = zmalloc(sizes.seccomp_notif);
1✔
491
                if (!*req)
1✔
492
                        return -ENOMEM;
493
        }
494

495
        if (resp) {
3✔
496
                *resp = zmalloc(sizes.seccomp_notif_resp);
1✔
497
                if (!*resp) {
1✔
498
                        if (req)
×
499
                                free(*req);
×
500
                        return -ENOMEM;
×
501
                }
502
        }
503

504
        return 0;
505
}
506

507
/**
508
 * Receive a notification from a seccomp notification fd
509
 * @param fd the notification fd
510
 * @param req the request buffer to save into
511
 *
512
 * Blocks waiting for a notification on this fd. This function is thread safe
513
 * (synchronization is performed in the kernel). Returns zero on success,
514
 * negative values on error.
515
 *
516
 */
517
int sys_notify_receive(int fd, struct seccomp_notif *req)
1✔
518
{
519
        if (state.sup_user_notif <= 0)
1✔
520
                return -EOPNOTSUPP;
521

522
        if (ioctl(fd, SECCOMP_IOCTL_NOTIF_RECV, req) < 0)
×
523
                return -ECANCELED;
×
524

525
        return 0;
526
}
527

528
/**
529
 * Send a notification response to a seccomp notification fd
530
 * @param fd the notification fd
531
 * @param resp the response buffer to use
532
 *
533
 * Sends a notification response on this fd. This function is thread safe
534
 * (synchronization is performed in the kernel). Returns zero on success,
535
 * negative values on error.
536
 *
537
 */
538
int sys_notify_respond(int fd, struct seccomp_notif_resp *resp)
1✔
539
{
540
        if (state.sup_user_notif <= 0)
1✔
541
                return -EOPNOTSUPP;
542

543
        if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0)
×
544
                return -ECANCELED;
×
545
        return 0;
546
}
547

548
/**
549
 * Check if a notification id is still valid
550
 * @param fd the notification fd
551
 * @param id the id to test
552
 *
553
 * Checks to see if a notification id is still valid. Returns 0 on success, and
554
 * negative values on failure.
555
 *
556
 */
557
int sys_notify_id_valid(int fd, uint64_t id)
1✔
558
{
559
        int rc;
1✔
560
        if (state.sup_user_notif <= 0)
1✔
561
                return -EOPNOTSUPP;
562

563
        rc = ioctl(fd, SECCOMP_IOCTL_NOTIF_ID_VALID, &id);
×
564
        if (rc < 0 && errno == EINVAL)
×
565
                /* It is possible that libseccomp was built against newer kernel
566
                 * headers than the kernel it is running on. If so, the older
567
                 * runtime kernel may not support the "fixed"
568
                 * SECCOMP_IOCTL_NOTIF_ID_VALID ioctl number which was introduced in
569
                 * kernel commit 47e33c05f9f0 ("seccomp: Fix ioctl number for
570
                 * SECCOMP_IOCTL_NOTIF_ID_VALID"). Try the old value. */
571
                rc = ioctl(fd, SECCOMP_IOCTL_NOTIF_ID_VALID_WRONG_DIR, &id);
×
572
        if (rc < 0)
×
573
                return -ENOENT;
574
        return 0;
575
}
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