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

drakenclimber / libseccomp / 13339131135

14 Feb 2025 11:17PM UTC coverage: 87.606% (-2.6%) from 90.252%
13339131135

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>

2778 of 3171 relevant lines covered (87.61%)

1457826.27 hits per line

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

89.55
/src/api.c
1
/**
2
 * Seccomp Library API
3
 *
4
 * Copyright (c) 2012,2013 Red Hat <pmoore@redhat.com>
5
 * Copyright (c) 2022 Microsoft Corporation <paulmoore@microsoft.com>
6
 * Author: Paul Moore <paul@paul-moore.com>
7
 */
8

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

23
#include <endian.h>
24
#include <errno.h>
25
#include <inttypes.h>
26
#include <unistd.h>
27
#include <stdarg.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include <stdbool.h>
31
#include <sys/ioctl.h>
32

33
#include <seccomp.h>
34

35
#include "arch.h"
36
#include "db.h"
37
#include "gen_pfc.h"
38
#include "gen_bpf.h"
39
#include "helper.h"
40
#include "system.h"
41

42
#define API        __attribute__((visibility("default")))
43

44
const struct scmp_version library_version = {
45
        .major = SCMP_VER_MAJOR,
46
        .minor = SCMP_VER_MINOR,
47
        .micro = SCMP_VER_MICRO,
48
};
49

50
unsigned int seccomp_api_level = 0;
51

52
/**
53
 * Filter the error codes we send back to callers
54
 * @param err the error code
55
 *
56
 * We consider error codes part of our API so we want to make sure we don't
57
 * accidentally send an undocumented error code to our callers.  This function
58
 * helps with that.
59
 *
60
 */
61
static int _rc_filter(int err)
141,151✔
62
{
63
        /* pass through success values */
64
        if (err >= 0)
137,935✔
65
                return err;
66

67
        /* filter the error codes */
68
        switch (err) {
1,907✔
69
        case -EACCES:
70
        /* NOTE: operation is not permitted by libseccomp */
71
        case -ECANCELED:
72
        /* NOTE: kernel level error that is beyond the control of
73
         *       libseccomp */
74
        case -EDOM:
75
        /* NOTE: failure due to arch/ABI */
76
        case -EEXIST:
77
        /* NOTE: operation failed due to existing rule or filter */
78
        case -EINVAL:
79
        /* NOTE: invalid input to the libseccomp API */
80
        case -ENOENT:
81
        /* NOTE: no matching entry found */
82
        case -ENOMEM:
83
        /* NOTE: unable to allocate enough memory to perform the
84
         *       requested operation */
85
        case -EOPNOTSUPP:
86
        /* NOTE: operation is not supported */
87
        case -ERANGE:
88
        /* NOTE: provided buffer is too small */
89
        case -ESRCH:
90
                /* NOTE: operation failed due to multi-threading */
91
                return err;
92
        default:
26✔
93
                /* NOTE: this is the default "internal libseccomp error"
94
                 *       error code, it is our catch-all */
95
                return -EFAULT;
26✔
96
        }
97
}
98

99
/**
100
 * Filter the system error codes we send back to callers
101
 * @param col the filter collection
102
 * @param err the error code
103
 *
104
 * This is similar to _rc_filter(), but it first checks the filter attribute
105
 * to determine if we should be filtering the return codes.
106
 *
107
 */
108
static int _rc_filter_sys(struct db_filter_col *col, int err)
5✔
109
{
110
        /* pass through success values */
111
        if (err >= 0)
5✔
112
                return err;
113

114
        /* pass the return code if the SCMP_FLTATR_API_SYSRAWRC is true */
115
        if (db_col_attr_read(col, SCMP_FLTATR_API_SYSRAWRC))
3✔
116
                return err;
1✔
117
        return -ECANCELED;
118
}
119

120
/**
121
 * Validate a filter context
122
 * @param ctx the filter context
123
 *
124
 * Attempt to validate the provided filter context.  Returns zero if the
125
 * context is valid, negative values on failure.
126
 *
127
 */
128
static int _ctx_valid(const scmp_filter_ctx *ctx)
18,560✔
129
{
130
        return db_col_valid((struct db_filter_col *)ctx);
18,560✔
131
}
132

133
/**
134
 * Validate a syscall number
135
 * @param syscall the syscall number
136
 *
137
 * Attempt to perform basic syscall number validation.  Returns zero of the
138
 * syscall appears valid, negative values on failure.
139
 *
140
 */
141
static int _syscall_valid(const struct db_filter_col *col, int syscall)
56,853✔
142
{
143
        /* syscall -1 is used by tracers to skip the syscall */
144
        if (col->attr.api_tskip && syscall == -1)
6✔
145
                return 0;
146
        if (syscall <= -1 && syscall >= -99)
56,847✔
147
                return -EINVAL;
148
        return 0;
149
}
150

151
/**
152
 * Update the API level
153
 *
154
 * This function performs a series of tests to determine what functionality is
155
 * supported given the current running environment (kernel, etc.).  It is
156
 * important to note that this function only does meaningful checks the first
157
 * time it is run, the resulting API level is cached after this first run and
158
 * used for all subsequent calls.  The API level value is returned.
159
 *
160
 */
161
static unsigned int _seccomp_api_update(void)
8,268✔
162
{
163
        unsigned int level = 1;
8,268✔
164

165
        /* if seccomp_api_level > 0 then it's already been set, we're done */
166
        if (seccomp_api_level >= 1)
8,268✔
167
                return seccomp_api_level;
168

169
        /* NOTE: level 1 is the base level, start checking at 2 */
170

171
        if (sys_chk_seccomp_syscall() &&
15,010✔
172
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC) == 1)
7,505✔
173
                level = 2;
×
174

175
        if (level == 2 &&
×
176
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_LOG) == 1 &&
×
177
            sys_chk_seccomp_action(SCMP_ACT_LOG) == 1 &&
×
178
            sys_chk_seccomp_action(SCMP_ACT_KILL_PROCESS) == 1)
×
179
                level = 3;
×
180

181
        if (level == 3 &&
×
182
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW) == 1)
×
183
                level = 4;
×
184

185
        if (level == 4 &&
×
186
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER) == 1 &&
×
187
            sys_chk_seccomp_action(SCMP_ACT_NOTIFY) == 1)
×
188
                level = 5;
×
189

190
        if (level == 5 &&
×
191
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH) == 1)
×
192
                level = 6;
×
193

194
        if (level == 6 &&
×
195
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) == 1)
×
196
                level = 7;
×
197

198
        /* update the stored api level and return */
199
        seccomp_api_level = level;
7,505✔
200
        return seccomp_api_level;
7,505✔
201
}
202

203
/* NOTE - function header comment in include/seccomp.h */
204
API const struct scmp_version *seccomp_version(void)
1✔
205
{
206
        return &library_version;
1✔
207
}
208

209
/* NOTE - function header comment in include/seccomp.h */
210
API unsigned int seccomp_api_get(void)
11✔
211
{
212
        /* update the api level, if needed */
213
        return _seccomp_api_update();
11✔
214
}
215

216
/* NOTE - function header comment in include/seccomp.h */
217
API int seccomp_api_set(unsigned int level)
724✔
218
{
219
        switch (level) {
724✔
220
        case 1:
9✔
221
                sys_set_seccomp_syscall(false);
9✔
222
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, false);
9✔
223
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, false);
9✔
224
                sys_set_seccomp_action(SCMP_ACT_LOG, false);
9✔
225
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, false);
9✔
226
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, false);
9✔
227
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, false);
9✔
228
                sys_set_seccomp_action(SCMP_ACT_NOTIFY, false);
9✔
229
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false);
9✔
230
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV,
9✔
231
                                     false);
232
                break;
9✔
233
        case 2:
1✔
234
                sys_set_seccomp_syscall(true);
1✔
235
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true);
1✔
236
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, false);
1✔
237
                sys_set_seccomp_action(SCMP_ACT_LOG, false);
1✔
238
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, false);
1✔
239
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, false);
1✔
240
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, false);
1✔
241
                sys_set_seccomp_action(SCMP_ACT_NOTIFY, false);
1✔
242
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false);
1✔
243
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV,
1✔
244
                                     false);
245
                break;
1✔
246
        case 3:
708✔
247
                sys_set_seccomp_syscall(true);
708✔
248
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true);
708✔
249
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, true);
708✔
250
                sys_set_seccomp_action(SCMP_ACT_LOG, true);
708✔
251
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, true);
708✔
252
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, false);
708✔
253
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, false);
708✔
254
                sys_set_seccomp_action(SCMP_ACT_NOTIFY, false);
708✔
255
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false);
708✔
256
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV,
708✔
257
                                     false);
258
                break;
708✔
259
        case 4:
1✔
260
                sys_set_seccomp_syscall(true);
1✔
261
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true);
1✔
262
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, true);
1✔
263
                sys_set_seccomp_action(SCMP_ACT_LOG, true);
1✔
264
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, true);
1✔
265
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, true);
1✔
266
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, false);
1✔
267
                sys_set_seccomp_action(SCMP_ACT_NOTIFY, false);
1✔
268
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false);
1✔
269
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV,
1✔
270
                                     false);
271
                break;
1✔
272
        case 5:
2✔
273
                sys_set_seccomp_syscall(true);
2✔
274
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true);
2✔
275
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, true);
2✔
276
                sys_set_seccomp_action(SCMP_ACT_LOG, true);
2✔
277
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, true);
2✔
278
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, true);
2✔
279
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, true);
2✔
280
                sys_set_seccomp_action(SCMP_ACT_NOTIFY, true);
2✔
281
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false);
2✔
282
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV,
2✔
283
                                     false);
284
                break;
2✔
285
        case 6:
1✔
286
                sys_set_seccomp_syscall(true);
1✔
287
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true);
1✔
288
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, true);
1✔
289
                sys_set_seccomp_action(SCMP_ACT_LOG, true);
1✔
290
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, true);
1✔
291
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, true);
1✔
292
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, true);
1✔
293
                sys_set_seccomp_action(SCMP_ACT_NOTIFY, true);
1✔
294
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, true);
1✔
295
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV,
1✔
296
                                     false);
297
                break;
1✔
298
        case 7:
1✔
299
                sys_set_seccomp_syscall(true);
1✔
300
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true);
1✔
301
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, true);
1✔
302
                sys_set_seccomp_action(SCMP_ACT_LOG, true);
1✔
303
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, true);
1✔
304
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, true);
1✔
305
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, true);
1✔
306
                sys_set_seccomp_action(SCMP_ACT_NOTIFY, true);
1✔
307
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, true);
1✔
308
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV,
1✔
309
                                     true);
310
                break;
1✔
311
        default:
312
                return _rc_filter(-EINVAL);
724✔
313
        }
314

315
        seccomp_api_level = level;
723✔
316
        return _rc_filter(0);
723✔
317
}
318

319
/* NOTE - function header comment in include/seccomp.h */
320
API scmp_filter_ctx seccomp_init(uint32_t def_action)
8,256✔
321
{
322
        /* force a runtime api level detection */
323
        _seccomp_api_update();
8,256✔
324

325
        if (db_col_action_valid(NULL, def_action) < 0)
8,256✔
326
                return NULL;
327

328
        return db_col_init(def_action);
8,255✔
329
}
330

331
/* NOTE - function header comment in include/seccomp.h */
332
API int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action)
366✔
333
{
334
        struct db_filter_col *col = (struct db_filter_col *)ctx;
366✔
335

336
        /* a NULL filter context indicates we are resetting the global state */
337
        if (ctx == NULL) {
366✔
338
                /* reset the global state and redetermine the api level */
339
                sys_reset_state();
1✔
340
                _seccomp_api_update();
1✔
341
                return _rc_filter(0);
1✔
342
        }
343
        /* ensure the default action is valid */
344
        if (db_col_action_valid(NULL, def_action) < 0)
365✔
345
                return _rc_filter(-EINVAL);
366✔
346

347
        /* reset the filter */
348
        return _rc_filter(db_col_reset(col, def_action));
365✔
349
}
350

351
/* NOTE - function header comment in include/seccomp.h */
352
API void seccomp_release(scmp_filter_ctx ctx)
8,229✔
353
{
354
        db_col_release((struct db_filter_col *)ctx);
8,229✔
355
}
8,229✔
356

357
/* NOTE - function header comment in include/seccomp.h */
358
API int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src)
27✔
359
{
360
        struct db_filter_col *col_dst = (struct db_filter_col *)ctx_dst;
27✔
361
        struct db_filter_col *col_src = (struct db_filter_col *)ctx_src;
27✔
362

363
        if (db_col_valid(col_dst) || db_col_valid(col_src))
27✔
364
                return _rc_filter(-EINVAL);
1✔
365

366
        /* NOTE: only the default action, NNP, TSYNC, and kernel version
367
         * settings must match */
368
        if ((col_dst->attr.act_default != col_src->attr.act_default) ||
26✔
369
            (col_dst->attr.nnp_enable != col_src->attr.nnp_enable) ||
26✔
370
            (col_dst->attr.tsync_enable != col_src->attr.tsync_enable) ||
26✔
371
            (col_dst->attr.act_enosys != col_src->attr.act_enosys) ||
26✔
372
            (col_dst->attr.kvermax != col_src->attr.kvermax))
26✔
373

374
                return _rc_filter(-EINVAL);
27✔
375

376
        return _rc_filter(db_col_merge(col_dst, col_src));
26✔
377
}
378

379
/* NOTE - function header comment in include/seccomp.h */
380
API uint32_t seccomp_arch_resolve_name(const char *arch_name)
7,744✔
381
{
382
        const struct arch_def *arch;
7,744✔
383

384
        if (arch_name == NULL)
7,744✔
385
                return 0;
386

387
        arch = arch_def_lookup_name(arch_name);
7,744✔
388
        if (arch == NULL)
7,744✔
389
                return 0;
390

391
        return arch->token;
7,744✔
392
}
393

394
/* NOTE - function header comment in include/seccomp.h */
395
API uint32_t seccomp_arch_native(void)
1,655✔
396
{
397
        return arch_def_native->token;
1,655✔
398
}
399

400
/* NOTE - function header comment in include/seccomp.h */
401
API int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token)
564✔
402
{
403
        struct db_filter_col *col = (struct db_filter_col *)ctx;
564✔
404

405
        if (arch_token == 0)
564✔
406
                arch_token = arch_def_native->token;
282✔
407

408
        if (arch_valid(arch_token))
564✔
409
                return _rc_filter(-EINVAL);
564✔
410

411
        return _rc_filter((db_col_arch_exist(col, arch_token) ? 0 : -EEXIST));
846✔
412
}
413

414
/* NOTE - function header comment in include/seccomp.h */
415
API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
13,275✔
416
{
417
        const struct arch_def *arch;
13,275✔
418
        struct db_filter_col *col = (struct db_filter_col *)ctx;
13,275✔
419

420
        if (arch_token == 0)
13,275✔
421
                arch_token = arch_def_native->token;
282✔
422

423
        arch = arch_def_lookup(arch_token);
13,275✔
424
        if (arch == NULL)
13,275✔
425
                return _rc_filter(-EINVAL);
13,275✔
426
        if (db_col_arch_exist(col, arch_token))
13,275✔
427
                return _rc_filter(-EEXIST);
13,275✔
428

429
        return _rc_filter(db_col_db_new(col, arch));
13,275✔
430
}
431

432
/* NOTE - function header comment in include/seccomp.h */
433
API int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
5,708✔
434
{
435
        struct db_filter_col *col = (struct db_filter_col *)ctx;
5,708✔
436

437
        if (arch_token == 0)
5,708✔
438
                arch_token = arch_def_native->token;
2,320✔
439

440
        if (arch_valid(arch_token))
5,708✔
441
                return _rc_filter(-EINVAL);
5,708✔
442
        if (db_col_arch_exist(col, arch_token) != -EEXIST)
5,708✔
443
                return _rc_filter(-EEXIST);
5,708✔
444

445
        return _rc_filter(db_col_db_remove(col, arch_token));
5,708✔
446
}
447

448
/* NOTE - function header comment in include/seccomp.h */
449
API int seccomp_load(const scmp_filter_ctx ctx)
2✔
450
{
451
        struct db_filter_col *col;
2✔
452
        bool rawrc;
2✔
453

454
        if (_ctx_valid(ctx))
2✔
455
                return _rc_filter(-EINVAL);
2✔
456
        col = (struct db_filter_col *)ctx;
1✔
457

458
        rawrc = db_col_attr_read(col, SCMP_FLTATR_API_SYSRAWRC);
1✔
459
        return _rc_filter(sys_filter_load(col, rawrc));
1✔
460
}
461

462
/* NOTE - function header comment in include/seccomp.h */
463
API int seccomp_attr_get(const scmp_filter_ctx ctx,
11✔
464
                         enum scmp_filter_attr attr, uint32_t *value)
465
{
466
        if (_ctx_valid(ctx))
11✔
467
                return _rc_filter(-EINVAL);
11✔
468

469
        return _rc_filter(db_col_attr_get((const struct db_filter_col *)ctx,
11✔
470
                                          attr, value));
471
}
472

473
/* NOTE - function header comment in include/seccomp.h */
474
API int seccomp_attr_set(scmp_filter_ctx ctx,
3,550✔
475
                         enum scmp_filter_attr attr, uint32_t value)
476
{
477
        if (_ctx_valid(ctx))
3,550✔
478
                return _rc_filter(-EINVAL);
3,550✔
479

480
        return _rc_filter(db_col_attr_set((struct db_filter_col *)ctx,
3,550✔
481
                                          attr, value));
482
}
483

484
/* NOTE - function header comment in include/seccomp.h */
485
API char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num)
18,794✔
486
{
487
        const struct arch_def *arch;
18,794✔
488
        const char *name;
18,794✔
489

490
        if (arch_token == 0)
18,794✔
491
                arch_token = arch_def_native->token;
2,505✔
492
        if (arch_valid(arch_token))
18,794✔
493
                return NULL;
494
        arch = arch_def_lookup(arch_token);
18,794✔
495
        if (arch == NULL)
18,794✔
496
                return NULL;
497

498
        name = arch_syscall_resolve_num(arch, num);
18,794✔
499
        if (name == NULL)
18,794✔
500
                return NULL;
501

502
        return strdup(name);
6,841✔
503
}
504

505
/* NOTE - function header comment in include/seccomp.h */
506
API int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name)
5,315✔
507
{
508
        const struct arch_def *arch;
5,315✔
509

510
        if (name == NULL)
5,315✔
511
                return __NR_SCMP_ERROR;
512

513
        if (arch_token == 0)
5,315✔
514
                arch_token = arch_def_native->token;
369✔
515
        if (arch_valid(arch_token))
5,315✔
516
                return __NR_SCMP_ERROR;
517
        arch = arch_def_lookup(arch_token);
5,315✔
518
        if (arch == NULL)
5,315✔
519
                return __NR_SCMP_ERROR;
520

521
        return arch_syscall_resolve_name(arch, name);
5,315✔
522
}
523

524
/* NOTE - function header comment in include/seccomp.h */
525
API int seccomp_syscall_resolve_name_rewrite(uint32_t arch_token,
1,381✔
526
                                             const char *name)
527
{
528
        int rc;
1,381✔
529
        int syscall;
1,381✔
530
        const struct arch_def *arch;
1,381✔
531

532
        if (name == NULL)
1,381✔
533
                return __NR_SCMP_ERROR;
534

535
        if (arch_token == 0)
1,381✔
536
                arch_token = arch_def_native->token;
3✔
537
        if (arch_valid(arch_token))
1,381✔
538
                return __NR_SCMP_ERROR;
539
        arch = arch_def_lookup(arch_token);
1,381✔
540
        if (arch == NULL)
1,381✔
541
                return __NR_SCMP_ERROR;
542

543
        syscall = arch_syscall_resolve_name(arch, name);
1,381✔
544
        if (syscall == __NR_SCMP_ERROR)
1,381✔
545
                return __NR_SCMP_ERROR;
546
        rc = arch_syscall_rewrite(arch, &syscall);
1,381✔
547
        if (rc == -EDOM)
1,381✔
548
                /* if we can't rewrite the syscall, just pass it through */
549
                return syscall;
56✔
550
        else if (rc < 0)
1,325✔
551
                return __NR_SCMP_ERROR;
552

553
        return syscall;
1,325✔
554
}
555

556
/* NOTE - function header comment in include/seccomp.h */
557
API int seccomp_syscall_resolve_name(const char *name)
3✔
558
{
559
        return seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, name);
3✔
560
}
561

562
/* NOTE - function header comment in include/seccomp.h */
563
API int seccomp_syscall_priority(scmp_filter_ctx ctx,
70✔
564
                                 int syscall, uint8_t priority)
565
{
566
        struct db_filter_col *col = (struct db_filter_col *)ctx;
70✔
567

568
        if (db_col_valid(col) || _syscall_valid(col, syscall))
70✔
569
                return _rc_filter(-EINVAL);
70✔
570

571
        return _rc_filter(db_col_syscall_priority(col, syscall, priority));
68✔
572
}
573

574
/* NOTE - function header comment in include/seccomp.h */
575
API int seccomp_rule_add_array(scmp_filter_ctx ctx,
25,271✔
576
                               uint32_t action, int syscall,
577
                               unsigned int arg_cnt,
578
                               const struct scmp_arg_cmp *arg_array)
579
{
580
        int rc;
25,271✔
581
        struct db_filter_col *col = (struct db_filter_col *)ctx;
25,271✔
582

583
        if (arg_cnt > ARG_COUNT_MAX)
25,271✔
584
                return _rc_filter(-EINVAL);
25,271✔
585
        if (arg_cnt > 0 && arg_array == NULL)
25,271✔
586
                return _rc_filter(-EINVAL);
25,271✔
587

588
        if (db_col_valid(col) || _syscall_valid(col, syscall))
25,271✔
589
                return _rc_filter(-EINVAL);
25,271✔
590

591
        rc = db_col_action_valid(col, action);
25,270✔
592
        if (rc < 0)
25,270✔
593
                return _rc_filter(rc);
2✔
594
        if (action == col->attr.act_default)
25,268✔
595
                return _rc_filter(-EACCES);
25,271✔
596

597
        if (col->attr.kvermax != SCMP_KV_UNDEF)
25,267✔
598
                /* Currently libseccomp does not support overwriting rules
599
                 * that have already been added to the filter.  The maximum
600
                 * supported kernel version feature adds a rule for each
601
                 * syscall.  Thus we can't support adding any more syscalls
602
                 * after that value is set */
603
                return _rc_filter(-EINVAL);
25,271✔
604

605
        return _rc_filter(db_col_rule_add(col, 0, action,
24,511✔
606
                                          syscall, arg_cnt, arg_array));
607
}
608

609
/* NOTE - function header comment in include/seccomp.h */
610
API int seccomp_rule_add(scmp_filter_ctx ctx,
25,273✔
611
                         uint32_t action, int syscall,
612
                         unsigned int arg_cnt, ...)
613
{
614
        int rc;
25,273✔
615
        int iter;
25,273✔
616
        struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
25,273✔
617
        va_list arg_list;
25,273✔
618

619
        /* arg_cnt is unsigned, so no need to check the lower bound */
620
        if (arg_cnt > ARG_COUNT_MAX)
25,273✔
621
                return _rc_filter(-EINVAL);
25,273✔
622

623
        va_start(arg_list, arg_cnt);
25,271✔
624
        for (iter = 0; iter < arg_cnt; ++iter)
39,758✔
625
                arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
14,487✔
626
        rc = seccomp_rule_add_array(ctx, action, syscall, arg_cnt, arg_array);
25,271✔
627
        va_end(arg_list);
25,271✔
628

629
        return _rc_filter(rc);
25,271✔
630
}
631

632
/* NOTE - function header comment in include/seccomp.h */
633
API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
31,514✔
634
                                     uint32_t action, int syscall,
635
                                     unsigned int arg_cnt,
636
                                     const struct scmp_arg_cmp *arg_array)
637
{
638
        int rc;
31,514✔
639
        struct db_filter_col *col = (struct db_filter_col *)ctx;
31,514✔
640

641
        if (arg_cnt > ARG_COUNT_MAX)
31,514✔
642
                return _rc_filter(-EINVAL);
31,514✔
643
        if (arg_cnt > 0 && arg_array == NULL)
31,514✔
644
                return _rc_filter(-EINVAL);
31,514✔
645

646
        if (db_col_valid(col) || _syscall_valid(col, syscall))
31,514✔
647
                return _rc_filter(-EINVAL);
31,514✔
648

649
        rc = db_col_action_valid(col, action);
31,514✔
650
        if (rc < 0)
31,514✔
651
                return _rc_filter(rc);
1✔
652
        if (action == col->attr.act_default)
31,513✔
653
                return _rc_filter(-EACCES);
31,514✔
654

655
        if (col->filter_cnt > 1)
31,513✔
656
                return _rc_filter(-EOPNOTSUPP);
31,514✔
657

658
        return _rc_filter(db_col_rule_add(col, 1, action,
31,513✔
659
                                          syscall, arg_cnt, arg_array));
660
}
661

662
/* NOTE - function header comment in include/seccomp.h */
663
API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
29,664✔
664
                               uint32_t action, int syscall,
665
                               unsigned int arg_cnt, ...)
666
{
667
        int rc;
29,664✔
668
        int iter;
29,664✔
669
        struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
29,664✔
670
        va_list arg_list;
29,664✔
671

672
        /* arg_cnt is unsigned, so no need to check the lower bound */
673
        if (arg_cnt > ARG_COUNT_MAX)
29,664✔
674
                return _rc_filter(-EINVAL);
29,664✔
675

676
        va_start(arg_list, arg_cnt);
29,664✔
677
        for (iter = 0; iter < arg_cnt; ++iter)
86,132✔
678
                arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
56,468✔
679
        rc = seccomp_rule_add_exact_array(ctx,
29,664✔
680
                                          action, syscall, arg_cnt, arg_array);
681
        va_end(arg_list);
29,664✔
682

683
        return _rc_filter(rc);
29,664✔
684
}
685

686
/* NOTE - function header comment in include/seccomp.h */
687
API int seccomp_notify_alloc(struct seccomp_notif **req,
×
688
                             struct seccomp_notif_resp **resp)
689
{
690
        /* force a runtime api level detection */
691
        _seccomp_api_update();
×
692

693
        return _rc_filter(sys_notify_alloc(req, resp));
×
694
}
695

696
/* NOTE - function header comment in include/seccomp.h */
697
API void seccomp_notify_free(struct seccomp_notif *req,
×
698
                             struct seccomp_notif_resp *resp)
699
{
700
        if (req)
×
701
                free(req);
×
702
        if (resp)
×
703
                free(resp);
×
704
}
×
705

706
/* NOTE - function header comment in include/seccomp.h */
707
API int seccomp_notify_receive(int fd, struct seccomp_notif *req)
×
708
{
709
        return _rc_filter(sys_notify_receive(fd, req));
×
710
}
711

712
/* NOTE - function header comment in include/seccomp.h */
713
API int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp)
×
714
{
715
        return _rc_filter(sys_notify_respond(fd, resp));
×
716
}
717

718
/* NOTE - function header comment in include/seccomp.h */
719
API int seccomp_notify_id_valid(int fd, uint64_t id)
×
720
{
721
        /* force a runtime api level detection */
722
        _seccomp_api_update();
×
723

724
        return _rc_filter(sys_notify_id_valid(fd, id));
×
725
}
726

727
/* NOTE - function header comment in include/seccomp.h */
728
API int seccomp_notify_fd(const scmp_filter_ctx ctx)
×
729
{
730
        /* NOTE: for historical reasons, and possibly future use, we require a
731
         * valid filter context even though we don't actual use it here; the
732
         * api update is also not strictly necessary, but keep it for now */
733

734
        /* force a runtime api level detection */
735
        _seccomp_api_update();
×
736

737
        if (_ctx_valid(ctx))
×
738
                return _rc_filter(-EINVAL);
×
739

740
        return _rc_filter(sys_notify_fd());
×
741
}
742

743
/* NOTE - function header comment in include/seccomp.h */
744
API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
5✔
745
{
746
        int rc;
5✔
747
        struct db_filter_col *col;
5✔
748

749
        if (_ctx_valid(ctx))
5✔
750
                return _rc_filter(-EINVAL);
5✔
751
        col = (struct db_filter_col *)ctx;
4✔
752

753
        rc = gen_pfc_generate(col, fd);
4✔
754
        return _rc_filter_sys(col, rc);
4✔
755
}
756

757
/* NOTE - function header comment in include/seccomp.h */
758
API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
8,215✔
759
{
760
        int rc;
8,215✔
761
        struct db_filter_col *col;
8,215✔
762
        struct bpf_program *program;
8,215✔
763

764
        if (_ctx_valid(ctx))
8,215✔
765
                return _rc_filter(-EINVAL);
8,215✔
766
        col = (struct db_filter_col *)ctx;
8,214✔
767

768
        rc = db_col_precompute(col);
8,214✔
769
        if (rc < 0)
8,214✔
770
                return _rc_filter(rc);
×
771
        program = col->prgm_bpf;
8,214✔
772
        rc = write(fd, program->blks, BPF_PGM_SIZE(program));
8,214✔
773
        if (rc < 0)
8,214✔
774
                return _rc_filter_sys(col, -errno);
2✔
775

776
        return 0;
777
}
778

779
/* NOTE - function header comment in include/seccomp.h */
780
API int seccomp_export_bpf_mem(const scmp_filter_ctx ctx, void *buf,
6✔
781
                               size_t *len)
782
{
783
        int rc;
6✔
784
        struct db_filter_col *col;
6✔
785
        struct bpf_program *program;
6✔
786

787
        if (_ctx_valid(ctx) || !len)
6✔
788
                return _rc_filter(-EINVAL);
6✔
789
        col = (struct db_filter_col *)ctx;
3✔
790

791
        rc = db_col_precompute(col);
3✔
792
        if (rc < 0)
3✔
793
                return _rc_filter(rc);
×
794
        program = col->prgm_bpf;
3✔
795

796
        if (buf) {
3✔
797
                /* If we have a big enough buffer, write the program. */
798
                if (BPF_PGM_SIZE(program) > *len)
2✔
799
                        rc = _rc_filter(-ERANGE);
3✔
800
                else
801
                        memcpy(buf, program->blks, *len);
1✔
802
        }
803
        *len = BPF_PGM_SIZE(program);
3✔
804

805
        return rc;
3✔
806
}
807

808
/* NOTE - function header comment in include/seccomp.h */
809
API int seccomp_transaction_start(const scmp_filter_ctx ctx)
3,366✔
810
{
811
        int rc;
3,366✔
812
        struct db_filter_col *col;
3,366✔
813

814
        if (_ctx_valid(ctx))
3,366✔
815
                return _rc_filter(-EINVAL);
3,366✔
816
        col = (struct db_filter_col *)ctx;
3,366✔
817

818
        rc = db_col_transaction_start(col, true);
3,366✔
819
        return _rc_filter(rc);
3,366✔
820
}
821

822
/* NOTE - function header comment in include/seccomp.h */
823
API void seccomp_transaction_reject(const scmp_filter_ctx ctx)
875✔
824
{
825
        struct db_filter_col *col;
875✔
826

827
        if (_ctx_valid(ctx))
875✔
828
                return;
829
        col = (struct db_filter_col *)ctx;
875✔
830

831
        db_col_transaction_abort(col, true);
875✔
832
}
833

834
/* NOTE - function header comment in include/seccomp.h */
835
API int seccomp_transaction_commit(const scmp_filter_ctx ctx)
2,491✔
836
{
837
        struct db_filter_col *col;
2,491✔
838

839
        if (_ctx_valid(ctx))
2,491✔
840
                return _rc_filter(-EINVAL);
2,491✔
841
        col = (struct db_filter_col *)ctx;
2,491✔
842

843
        db_col_transaction_commit(col, true);
2,491✔
844
        return _rc_filter(0);
2,491✔
845
}
846

847
/* NOTE - function header comment in include/seccomp.h */
848
API int seccomp_precompute(const scmp_filter_ctx ctx)
39✔
849
{
850
        struct db_filter_col *col;
39✔
851

852
        if (_ctx_valid(ctx))
39✔
853
                return _rc_filter(-EINVAL);
39✔
854
        col = (struct db_filter_col *)ctx;
39✔
855

856
        return _rc_filter(db_col_precompute(col));
39✔
857
}
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