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

drakenclimber / libseccomp / 12716868856

10 Jan 2025 08:37PM UTC coverage: 87.592% (-0.08%) from 87.676%
12716868856

push

github

drakenclimber
bpf: pfc: Add maximum supported kernel version logic

Add support for an application to specify the maximum kernel version it
currently supports.  Any syscalls that have been added to a kernel
version newer than this specified version will return the unknown
action.  The unknown action defaults to returning ENOSYS, but it can be
overridden via the filter attribute SCMP_FLTATR_ACT_UNKNOWN.

When the maximum supported kernel version is enabled, libseccomp will
create a filter as follows:
	* Users explicitly declare rules for syscalls.  No changes here
	  from previous behavior
	* The default action provided via seccomp_init() will still be
	  used for all syscalls that existed as of the user-specified
	  supported kernel
	* Any syscalls that did not exist at the time of the
	  user-specified supported kernel will return the unknown
	  action.  By default libseccomp sets this to return ENOSYS, but
	  it can be overridden via the filter attribute
	  SCMP_FLTATR_ACT_UNKNOWN.

Below is a rough pseudo-code outline of a typical usage of this feature:
	seccomp_init()
	seccomp_add_rules()

	(optional but recommended) seccomp_attr_set( binary tree )
	seccomp_attr_set( max supported kernel version, e.g. SCMP_KV_6_5 )
	(optional) seccomp_attr_set( default unknown action )

	seccomp_load()
	seccomp_release()

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

8 of 65 new or added lines in 5 files covered. (12.31%)

96 existing lines in 4 files now uncovered.

2739 of 3127 relevant lines covered (87.59%)

288204.54 hits per line

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

99.21
/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)
124,070✔
62
{
63
        /* pass through success values */
64
        if (err >= 0)
123,345✔
65
                return err;
66

67
        /* filter the error codes */
68
        switch (err) {
1,099✔
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:
25✔
93
                /* NOTE: this is the default "internal libseccomp error"
94
                 *       error code, it is our catch-all */
95
                return -EFAULT;
25✔
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)
8,375✔
129
{
130
        return db_col_valid((struct db_filter_col *)ctx);
8,375✔
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)
53,162✔
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)
53,156✔
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)
7,840✔
162
{
163
        unsigned int level = 1;
7,840✔
164

165
        /* if seccomp_api_level > 0 then it's already been set, we're done */
166
        if (seccomp_api_level >= 1)
7,840✔
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() &&
14,140✔
172
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC) == 1)
7,070✔
173
                level = 2;
7,070✔
174

175
        if (level == 2 &&
7,070✔
176
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_LOG) == 1 &&
14,140✔
177
            sys_chk_seccomp_action(SCMP_ACT_LOG) == 1 &&
14,140✔
178
            sys_chk_seccomp_action(SCMP_ACT_KILL_PROCESS) == 1)
7,070✔
179
                level = 3;
7,070✔
180

181
        if (level == 3 &&
7,070✔
182
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW) == 1)
7,070✔
183
                level = 4;
7,070✔
184

185
        if (level == 4 &&
7,070✔
186
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER) == 1 &&
14,140✔
187
            sys_chk_seccomp_action(SCMP_ACT_NOTIFY) == 1)
7,070✔
188
                level = 5;
7,070✔
189

190
        if (level == 5 &&
7,070✔
191
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH) == 1)
7,070✔
192
                level = 6;
7,070✔
193

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

198
        /* update the stored api level and return */
199
        seccomp_api_level = level;
7,070✔
200
        return seccomp_api_level;
7,070✔
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)
7,822✔
321
{
322
        /* force a runtime api level detection */
323
        _seccomp_api_update();
7,822✔
324

325
        if (db_col_action_valid(NULL, def_action) < 0)
7,822✔
326
                return NULL;
327

328
        return db_col_init(def_action);
7,821✔
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)
7,795✔
353
{
354
        db_col_release((struct db_filter_col *)ctx);
7,795✔
355
}
7,795✔
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_unknown != col_src->attr.act_unknown) ||
26✔
372
            (col_dst->attr.kver != col_src->attr.kver))
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,708✔
381
{
382
        const struct arch_def *arch;
7,708✔
383

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

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

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

394
/* NOTE - function header comment in include/seccomp.h */
395
API uint32_t seccomp_arch_native(void)
1,631✔
396
{
397
        return arch_def_native->token;
1,631✔
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)
12,105✔
416
{
417
        const struct arch_def *arch;
12,105✔
418
        struct db_filter_col *col = (struct db_filter_col *)ctx;
12,105✔
419

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

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

429
        return _rc_filter(db_col_db_new(col, arch));
12,105✔
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,294✔
434
{
435
        struct db_filter_col *col = (struct db_filter_col *)ctx;
5,294✔
436

437
        if (arch_token == 0)
5,294✔
438
                arch_token = arch_def_native->token;
1,910✔
439

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

445
        return _rc_filter(db_col_db_remove(col, arch_token));
5,294✔
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,
529✔
475
                         enum scmp_filter_attr attr, uint32_t value)
476
{
477
        if (_ctx_valid(ctx))
529✔
478
                return _rc_filter(-EINVAL);
529✔
479

480
        return _rc_filter(db_col_attr_set((struct db_filter_col *)ctx,
529✔
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)
15,499✔
486
{
487
        const struct arch_def *arch;
15,499✔
488
        const char *name;
15,499✔
489

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

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

502
        return strdup(name);
8,351✔
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)
6,557✔
507
{
508
        const struct arch_def *arch;
6,557✔
509

510
        if (name == NULL)
6,557✔
511
                return __NR_SCMP_ERROR;
512

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

521
        return arch_syscall_resolve_name(arch, name);
6,557✔
522
}
523

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

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

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

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

553
        return syscall;
1,339✔
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,
21,829✔
576
                               uint32_t action, int syscall,
577
                               unsigned int arg_cnt,
578
                               const struct scmp_arg_cmp *arg_array)
579
{
580
        int rc;
21,829✔
581
        struct db_filter_col *col = (struct db_filter_col *)ctx;
21,829✔
582

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

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

591
        rc = db_col_action_valid(col, action);
21,828✔
592
        if (rc < 0)
21,828✔
593
                return _rc_filter(rc);
2✔
594
        if (action == col->attr.act_default)
21,826✔
595
                return _rc_filter(-EACCES);
21,829✔
596

597
        return _rc_filter(db_col_rule_add(col, 0, action,
21,825✔
598
                                          syscall, arg_cnt, arg_array));
599
}
600

601
/* NOTE - function header comment in include/seccomp.h */
602
API int seccomp_rule_add(scmp_filter_ctx ctx,
21,831✔
603
                         uint32_t action, int syscall,
604
                         unsigned int arg_cnt, ...)
605
{
606
        int rc;
21,831✔
607
        int iter;
21,831✔
608
        struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
21,831✔
609
        va_list arg_list;
21,831✔
610

611
        /* arg_cnt is unsigned, so no need to check the lower bound */
612
        if (arg_cnt > ARG_COUNT_MAX)
21,831✔
613
                return _rc_filter(-EINVAL);
21,831✔
614

615
        va_start(arg_list, arg_cnt);
21,829✔
616
        for (iter = 0; iter < arg_cnt; ++iter)
36,316✔
617
                arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
14,487✔
618
        rc = seccomp_rule_add_array(ctx, action, syscall, arg_cnt, arg_array);
21,829✔
619
        va_end(arg_list);
21,829✔
620

621
        return _rc_filter(rc);
21,829✔
622
}
623

624
/* NOTE - function header comment in include/seccomp.h */
625
API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
31,265✔
626
                                     uint32_t action, int syscall,
627
                                     unsigned int arg_cnt,
628
                                     const struct scmp_arg_cmp *arg_array)
629
{
630
        int rc;
31,265✔
631
        struct db_filter_col *col = (struct db_filter_col *)ctx;
31,265✔
632

633
        if (arg_cnt > ARG_COUNT_MAX)
31,265✔
634
                return _rc_filter(-EINVAL);
31,265✔
635
        if (arg_cnt > 0 && arg_array == NULL)
31,265✔
636
                return _rc_filter(-EINVAL);
31,265✔
637

638
        if (db_col_valid(col) || _syscall_valid(col, syscall))
31,265✔
639
                return _rc_filter(-EINVAL);
31,265✔
640

641
        rc = db_col_action_valid(col, action);
31,265✔
642
        if (rc < 0)
31,265✔
643
                return _rc_filter(rc);
1✔
644
        if (action == col->attr.act_default)
31,264✔
645
                return _rc_filter(-EACCES);
31,265✔
646

647
        if (col->filter_cnt > 1)
31,264✔
648
                return _rc_filter(-EOPNOTSUPP);
31,265✔
649

650
        return _rc_filter(db_col_rule_add(col, 1, action,
31,264✔
651
                                          syscall, arg_cnt, arg_array));
652
}
653

654
/* NOTE - function header comment in include/seccomp.h */
655
API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
29,415✔
656
                               uint32_t action, int syscall,
657
                               unsigned int arg_cnt, ...)
658
{
659
        int rc;
29,415✔
660
        int iter;
29,415✔
661
        struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
29,415✔
662
        va_list arg_list;
29,415✔
663

664
        /* arg_cnt is unsigned, so no need to check the lower bound */
665
        if (arg_cnt > ARG_COUNT_MAX)
29,415✔
666
                return _rc_filter(-EINVAL);
29,415✔
667

668
        va_start(arg_list, arg_cnt);
29,415✔
669
        for (iter = 0; iter < arg_cnt; ++iter)
85,883✔
670
                arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
56,468✔
671
        rc = seccomp_rule_add_exact_array(ctx,
29,415✔
672
                                          action, syscall, arg_cnt, arg_array);
673
        va_end(arg_list);
29,415✔
674

675
        return _rc_filter(rc);
29,415✔
676
}
677

678
/* NOTE - function header comment in include/seccomp.h */
679
API int seccomp_notify_alloc(struct seccomp_notif **req,
3✔
680
                             struct seccomp_notif_resp **resp)
681
{
682
        /* force a runtime api level detection */
683
        _seccomp_api_update();
3✔
684

685
        return _rc_filter(sys_notify_alloc(req, resp));
3✔
686
}
687

688
/* NOTE - function header comment in include/seccomp.h */
689
API void seccomp_notify_free(struct seccomp_notif *req,
2✔
690
                             struct seccomp_notif_resp *resp)
691
{
692
        if (req)
2✔
693
                free(req);
1✔
694
        if (resp)
2✔
695
                free(resp);
1✔
696
}
2✔
697

698
/* NOTE - function header comment in include/seccomp.h */
699
API int seccomp_notify_receive(int fd, struct seccomp_notif *req)
1✔
700
{
701
        return _rc_filter(sys_notify_receive(fd, req));
1✔
702
}
703

704
/* NOTE - function header comment in include/seccomp.h */
705
API int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp)
1✔
706
{
707
        return _rc_filter(sys_notify_respond(fd, resp));
1✔
708
}
709

710
/* NOTE - function header comment in include/seccomp.h */
711
API int seccomp_notify_id_valid(int fd, uint64_t id)
1✔
712
{
713
        /* force a runtime api level detection */
714
        _seccomp_api_update();
1✔
715

716
        return _rc_filter(sys_notify_id_valid(fd, id));
1✔
717
}
718

719
/* NOTE - function header comment in include/seccomp.h */
720
API int seccomp_notify_fd(const scmp_filter_ctx ctx)
2✔
721
{
722
        /* NOTE: for historical reasons, and possibly future use, we require a
723
         * valid filter context even though we don't actual use it here; the
724
         * api update is also not strictly necessary, but keep it for now */
725

726
        /* force a runtime api level detection */
727
        _seccomp_api_update();
2✔
728

729
        if (_ctx_valid(ctx))
2✔
730
                return _rc_filter(-EINVAL);
2✔
731

732
        return _rc_filter(sys_notify_fd());
1✔
733
}
734

735
/* NOTE - function header comment in include/seccomp.h */
736
API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
5✔
737
{
738
        int rc;
5✔
739
        struct db_filter_col *col;
5✔
740

741
        if (_ctx_valid(ctx))
5✔
742
                return _rc_filter(-EINVAL);
5✔
743
        col = (struct db_filter_col *)ctx;
4✔
744

745
        rc = gen_pfc_generate(col, fd);
4✔
746
        return _rc_filter_sys(col, rc);
4✔
747
}
748

749
/* NOTE - function header comment in include/seccomp.h */
750
API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
7,781✔
751
{
752
        int rc;
7,781✔
753
        struct db_filter_col *col;
7,781✔
754
        struct bpf_program *program;
7,781✔
755

756
        if (_ctx_valid(ctx))
7,781✔
757
                return _rc_filter(-EINVAL);
7,781✔
758
        col = (struct db_filter_col *)ctx;
7,780✔
759

760
        rc = db_col_precompute(col);
7,780✔
761
        if (rc < 0)
7,780✔
UNCOV
762
                return _rc_filter(rc);
×
763
        program = col->prgm_bpf;
7,780✔
764
        rc = write(fd, program->blks, BPF_PGM_SIZE(program));
7,780✔
765
        if (rc < 0)
7,780✔
766
                return _rc_filter_sys(col, -errno);
2✔
767

768
        return 0;
769
}
770

771
/* NOTE - function header comment in include/seccomp.h */
772
API int seccomp_export_bpf_mem(const scmp_filter_ctx ctx, void *buf,
6✔
773
                               size_t *len)
774
{
775
        int rc;
6✔
776
        struct db_filter_col *col;
6✔
777
        struct bpf_program *program;
6✔
778

779
        if (_ctx_valid(ctx) || !len)
6✔
780
                return _rc_filter(-EINVAL);
6✔
781
        col = (struct db_filter_col *)ctx;
3✔
782

783
        rc = db_col_precompute(col);
3✔
784
        if (rc < 0)
3✔
UNCOV
785
                return _rc_filter(rc);
×
786
        program = col->prgm_bpf;
3✔
787

788
        if (buf) {
3✔
789
                /* If we have a big enough buffer, write the program. */
790
                if (BPF_PGM_SIZE(program) > *len)
2✔
791
                        rc = _rc_filter(-ERANGE);
3✔
792
                else
793
                        memcpy(buf, program->blks, *len);
1✔
794
        }
795
        *len = BPF_PGM_SIZE(program);
3✔
796

797
        return rc;
3✔
798
}
799

800
/* NOTE - function header comment in include/seccomp.h */
801
API int seccomp_precompute(const scmp_filter_ctx ctx)
39✔
802
{
803
        struct db_filter_col *col;
39✔
804

805
        if (_ctx_valid(ctx))
39✔
806
                return _rc_filter(-EINVAL);
39✔
807
        col = (struct db_filter_col *)ctx;
39✔
808

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