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

drakenclimber / libseccomp / 12185452021

09 Sep 2024 11:08PM UTC coverage: 90.252% (+0.7%) from 89.523%
12185452021

push

github

pcmoore
tests: add test 62-sim-arch_transactions

Add a test to verify the logic at the end of db_col_transaction_commit()
properly copies and releases the snapshots from the filter when the
filter length doesn't match the snapshot length.

Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
[PM: subj tweak]
Signed-off-by: Paul Moore <paul@paul-moore.com>

2722 of 3016 relevant lines covered (90.25%)

301149.74 hits per line

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

99.25
/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)
131,223✔
62
{
63
        /* pass through success values */
64
        if (err >= 0)
128,007✔
65
                return err;
66

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

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

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

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

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

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

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

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

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

328
        return db_col_init(def_action);
7,851✔
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,825✔
353
{
354
        db_col_release((struct db_filter_col *)ctx);
7,825✔
355
}
7,825✔
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, and TSYNC settings must match */
367
        if ((col_dst->attr.act_default != col_src->attr.act_default) ||
26✔
368
            (col_dst->attr.nnp_enable != col_src->attr.nnp_enable) ||
26✔
369
            (col_dst->attr.tsync_enable != col_src->attr.tsync_enable))
26✔
370
                return _rc_filter(-EINVAL);
27✔
371

372
        return _rc_filter(db_col_merge(col_dst, col_src));
26✔
373
}
374

375
/* NOTE - function header comment in include/seccomp.h */
376
API uint32_t seccomp_arch_resolve_name(const char *arch_name)
7,728✔
377
{
378
        const struct arch_def *arch;
7,728✔
379

380
        if (arch_name == NULL)
7,728✔
381
                return 0;
382

383
        arch = arch_def_lookup_name(arch_name);
7,728✔
384
        if (arch == NULL)
7,728✔
385
                return 0;
386

387
        return arch->token;
7,728✔
388
}
389

390
/* NOTE - function header comment in include/seccomp.h */
391
API uint32_t seccomp_arch_native(void)
1,639✔
392
{
393
        return arch_def_native->token;
1,639✔
394
}
395

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

401
        if (arch_token == 0)
564✔
402
                arch_token = arch_def_native->token;
282✔
403

404
        if (arch_valid(arch_token))
564✔
405
                return _rc_filter(-EINVAL);
564✔
406

407
        return _rc_filter((db_col_arch_exist(col, arch_token) ? 0 : -EEXIST));
846✔
408
}
409

410
/* NOTE - function header comment in include/seccomp.h */
411
API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
12,114✔
412
{
413
        const struct arch_def *arch;
12,114✔
414
        struct db_filter_col *col = (struct db_filter_col *)ctx;
12,114✔
415

416
        if (arch_token == 0)
12,114✔
417
                arch_token = arch_def_native->token;
282✔
418

419
        arch = arch_def_lookup(arch_token);
12,114✔
420
        if (arch == NULL)
12,114✔
421
                return _rc_filter(-EINVAL);
12,114✔
422
        if (db_col_arch_exist(col, arch_token))
12,114✔
423
                return _rc_filter(-EEXIST);
12,114✔
424

425
        return _rc_filter(db_col_db_new(col, arch));
12,114✔
426
}
427

428
/* NOTE - function header comment in include/seccomp.h */
429
API int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
5,303✔
430
{
431
        struct db_filter_col *col = (struct db_filter_col *)ctx;
5,303✔
432

433
        if (arch_token == 0)
5,303✔
434
                arch_token = arch_def_native->token;
1,915✔
435

436
        if (arch_valid(arch_token))
5,303✔
437
                return _rc_filter(-EINVAL);
5,303✔
438
        if (db_col_arch_exist(col, arch_token) != -EEXIST)
5,303✔
439
                return _rc_filter(-EEXIST);
5,303✔
440

441
        return _rc_filter(db_col_db_remove(col, arch_token));
5,303✔
442
}
443

444
/* NOTE - function header comment in include/seccomp.h */
445
API int seccomp_load(const scmp_filter_ctx ctx)
2✔
446
{
447
        struct db_filter_col *col;
2✔
448
        bool rawrc;
2✔
449

450
        if (_ctx_valid(ctx))
2✔
451
                return _rc_filter(-EINVAL);
2✔
452
        col = (struct db_filter_col *)ctx;
1✔
453

454
        rawrc = db_col_attr_read(col, SCMP_FLTATR_API_SYSRAWRC);
1✔
455
        return _rc_filter(sys_filter_load(col, rawrc));
1✔
456
}
457

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

465
        return _rc_filter(db_col_attr_get((const struct db_filter_col *)ctx,
11✔
466
                                          attr, value));
467
}
468

469
/* NOTE - function header comment in include/seccomp.h */
470
API int seccomp_attr_set(scmp_filter_ctx ctx,
529✔
471
                         enum scmp_filter_attr attr, uint32_t value)
472
{
473
        if (_ctx_valid(ctx))
529✔
474
                return _rc_filter(-EINVAL);
529✔
475

476
        return _rc_filter(db_col_attr_set((struct db_filter_col *)ctx,
529✔
477
                                          attr, value));
478
}
479

480
/* NOTE - function header comment in include/seccomp.h */
481
API char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num)
15,499✔
482
{
483
        const struct arch_def *arch;
15,499✔
484
        const char *name;
15,499✔
485

486
        if (arch_token == 0)
15,499✔
487
                arch_token = arch_def_native->token;
2,505✔
488
        if (arch_valid(arch_token))
15,499✔
489
                return NULL;
490
        arch = arch_def_lookup(arch_token);
15,499✔
491
        if (arch == NULL)
15,499✔
492
                return NULL;
493

494
        name = arch_syscall_resolve_num(arch, num);
15,499✔
495
        if (name == NULL)
15,499✔
496
                return NULL;
497

498
        return strdup(name);
8,211✔
499
}
500

501
/* NOTE - function header comment in include/seccomp.h */
502
API int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name)
6,417✔
503
{
504
        const struct arch_def *arch;
6,417✔
505

506
        if (name == NULL)
6,417✔
507
                return __NR_SCMP_ERROR;
508

509
        if (arch_token == 0)
6,417✔
510
                arch_token = arch_def_native->token;
370✔
511
        if (arch_valid(arch_token))
6,417✔
512
                return __NR_SCMP_ERROR;
513
        arch = arch_def_lookup(arch_token);
6,417✔
514
        if (arch == NULL)
6,417✔
515
                return __NR_SCMP_ERROR;
516

517
        return arch_syscall_resolve_name(arch, name);
6,417✔
518
}
519

520
/* NOTE - function header comment in include/seccomp.h */
521
API int seccomp_syscall_resolve_name_rewrite(uint32_t arch_token,
1,403✔
522
                                             const char *name)
523
{
524
        int rc;
1,403✔
525
        int syscall;
1,403✔
526
        const struct arch_def *arch;
1,403✔
527

528
        if (name == NULL)
1,403✔
529
                return __NR_SCMP_ERROR;
530

531
        if (arch_token == 0)
1,403✔
532
                arch_token = arch_def_native->token;
3✔
533
        if (arch_valid(arch_token))
1,403✔
534
                return __NR_SCMP_ERROR;
535
        arch = arch_def_lookup(arch_token);
1,403✔
536
        if (arch == NULL)
1,403✔
537
                return __NR_SCMP_ERROR;
538

539
        syscall = arch_syscall_resolve_name(arch, name);
1,403✔
540
        if (syscall == __NR_SCMP_ERROR)
1,403✔
541
                return __NR_SCMP_ERROR;
542
        rc = arch_syscall_rewrite(arch, &syscall);
1,403✔
543
        if (rc == -EDOM)
1,403✔
544
                /* if we can't rewrite the syscall, just pass it through */
545
                return syscall;
56✔
546
        else if (rc < 0)
1,347✔
547
                return __NR_SCMP_ERROR;
548

549
        return syscall;
1,347✔
550
}
551

552
/* NOTE - function header comment in include/seccomp.h */
553
API int seccomp_syscall_resolve_name(const char *name)
3✔
554
{
555
        return seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, name);
3✔
556
}
557

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

564
        if (db_col_valid(col) || _syscall_valid(col, syscall))
70✔
565
                return _rc_filter(-EINVAL);
70✔
566

567
        return _rc_filter(db_col_syscall_priority(col, syscall, priority));
68✔
568
}
569

570
/* NOTE - function header comment in include/seccomp.h */
571
API int seccomp_rule_add_array(scmp_filter_ctx ctx,
21,854✔
572
                               uint32_t action, int syscall,
573
                               unsigned int arg_cnt,
574
                               const struct scmp_arg_cmp *arg_array)
575
{
576
        int rc;
21,854✔
577
        struct db_filter_col *col = (struct db_filter_col *)ctx;
21,854✔
578

579
        if (arg_cnt > ARG_COUNT_MAX)
21,854✔
580
                return _rc_filter(-EINVAL);
21,854✔
581
        if (arg_cnt > 0 && arg_array == NULL)
21,854✔
582
                return _rc_filter(-EINVAL);
21,854✔
583

584
        if (db_col_valid(col) || _syscall_valid(col, syscall))
21,854✔
585
                return _rc_filter(-EINVAL);
21,854✔
586

587
        rc = db_col_action_valid(col, action);
21,853✔
588
        if (rc < 0)
21,853✔
589
                return _rc_filter(rc);
2✔
590
        if (action == col->attr.act_default)
21,851✔
591
                return _rc_filter(-EACCES);
21,854✔
592

593
        return _rc_filter(db_col_rule_add(col, 0, action,
21,850✔
594
                                          syscall, arg_cnt, arg_array));
595
}
596

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

607
        /* arg_cnt is unsigned, so no need to check the lower bound */
608
        if (arg_cnt > ARG_COUNT_MAX)
21,856✔
609
                return _rc_filter(-EINVAL);
21,856✔
610

611
        va_start(arg_list, arg_cnt);
21,854✔
612
        for (iter = 0; iter < arg_cnt; ++iter)
36,341✔
613
                arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
14,487✔
614
        rc = seccomp_rule_add_array(ctx, action, syscall, arg_cnt, arg_array);
21,854✔
615
        va_end(arg_list);
21,854✔
616

617
        return _rc_filter(rc);
21,854✔
618
}
619

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

629
        if (arg_cnt > ARG_COUNT_MAX)
31,879✔
630
                return _rc_filter(-EINVAL);
31,879✔
631
        if (arg_cnt > 0 && arg_array == NULL)
31,879✔
632
                return _rc_filter(-EINVAL);
31,879✔
633

634
        if (db_col_valid(col) || _syscall_valid(col, syscall))
31,879✔
635
                return _rc_filter(-EINVAL);
31,879✔
636

637
        rc = db_col_action_valid(col, action);
31,879✔
638
        if (rc < 0)
31,879✔
639
                return _rc_filter(rc);
1✔
640
        if (action == col->attr.act_default)
31,878✔
641
                return _rc_filter(-EACCES);
31,879✔
642

643
        if (col->filter_cnt > 1)
31,878✔
644
                return _rc_filter(-EOPNOTSUPP);
31,879✔
645

646
        return _rc_filter(db_col_rule_add(col, 1, action,
31,878✔
647
                                          syscall, arg_cnt, arg_array));
648
}
649

650
/* NOTE - function header comment in include/seccomp.h */
651
API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
30,029✔
652
                               uint32_t action, int syscall,
653
                               unsigned int arg_cnt, ...)
654
{
655
        int rc;
30,029✔
656
        int iter;
30,029✔
657
        struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
30,029✔
658
        va_list arg_list;
30,029✔
659

660
        /* arg_cnt is unsigned, so no need to check the lower bound */
661
        if (arg_cnt > ARG_COUNT_MAX)
30,029✔
662
                return _rc_filter(-EINVAL);
30,029✔
663

664
        va_start(arg_list, arg_cnt);
30,029✔
665
        for (iter = 0; iter < arg_cnt; ++iter)
86,497✔
666
                arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
56,468✔
667
        rc = seccomp_rule_add_exact_array(ctx,
30,029✔
668
                                          action, syscall, arg_cnt, arg_array);
669
        va_end(arg_list);
30,029✔
670

671
        return _rc_filter(rc);
30,029✔
672
}
673

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

681
        return _rc_filter(sys_notify_alloc(req, resp));
3✔
682
}
683

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

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

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

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

712
        return _rc_filter(sys_notify_id_valid(fd, id));
1✔
713
}
714

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

722
        /* force a runtime api level detection */
723
        _seccomp_api_update();
2✔
724

725
        if (_ctx_valid(ctx))
2✔
726
                return _rc_filter(-EINVAL);
2✔
727

728
        return _rc_filter(sys_notify_fd());
1✔
729
}
730

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

737
        if (_ctx_valid(ctx))
5✔
738
                return _rc_filter(-EINVAL);
5✔
739
        col = (struct db_filter_col *)ctx;
4✔
740

741
        rc = gen_pfc_generate(col, fd);
4✔
742
        return _rc_filter_sys(col, rc);
4✔
743
}
744

745
/* NOTE - function header comment in include/seccomp.h */
746
API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
7,811✔
747
{
748
        int rc;
7,811✔
749
        struct db_filter_col *col;
7,811✔
750
        struct bpf_program *program;
7,811✔
751

752
        if (_ctx_valid(ctx))
7,811✔
753
                return _rc_filter(-EINVAL);
7,811✔
754
        col = (struct db_filter_col *)ctx;
7,810✔
755

756
        rc = db_col_precompute(col);
7,810✔
757
        if (rc < 0)
7,810✔
758
                return _rc_filter(rc);
×
759
        program = col->prgm_bpf;
7,810✔
760
        rc = write(fd, program->blks, BPF_PGM_SIZE(program));
7,810✔
761
        if (rc < 0)
7,810✔
762
                return _rc_filter_sys(col, -errno);
2✔
763

764
        return 0;
765
}
766

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

775
        if (_ctx_valid(ctx) || !len)
6✔
776
                return _rc_filter(-EINVAL);
6✔
777
        col = (struct db_filter_col *)ctx;
3✔
778

779
        rc = db_col_precompute(col);
3✔
780
        if (rc < 0)
3✔
781
                return _rc_filter(rc);
×
782
        program = col->prgm_bpf;
3✔
783

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

793
        return rc;
3✔
794
}
795

796
/* NOTE - function header comment in include/seccomp.h */
797
API int seccomp_transaction_start(const scmp_filter_ctx ctx)
3,366✔
798
{
799
        int rc;
3,366✔
800
        struct db_filter_col *col;
3,366✔
801

802
        if (_ctx_valid(ctx))
3,366✔
803
                return _rc_filter(-EINVAL);
3,366✔
804
        col = (struct db_filter_col *)ctx;
3,366✔
805

806
        rc = db_col_transaction_start(col, true);
3,366✔
807
        return _rc_filter(rc);
3,366✔
808
}
809

810
/* NOTE - function header comment in include/seccomp.h */
811
API void seccomp_transaction_reject(const scmp_filter_ctx ctx)
875✔
812
{
813
        struct db_filter_col *col;
875✔
814

815
        if (_ctx_valid(ctx))
875✔
816
                return;
817
        col = (struct db_filter_col *)ctx;
875✔
818

819
        db_col_transaction_abort(col, true);
875✔
820
}
821

822
/* NOTE - function header comment in include/seccomp.h */
823
API int seccomp_transaction_commit(const scmp_filter_ctx ctx)
2,491✔
824
{
825
        struct db_filter_col *col;
2,491✔
826

827
        if (_ctx_valid(ctx))
2,491✔
828
                return _rc_filter(-EINVAL);
2,491✔
829
        col = (struct db_filter_col *)ctx;
2,491✔
830

831
        db_col_transaction_commit(col, true);
2,491✔
832
        return _rc_filter(0);
2,491✔
833
}
834

835
/* NOTE - function header comment in include/seccomp.h */
836
API int seccomp_precompute(const scmp_filter_ctx ctx)
39✔
837
{
838
        struct db_filter_col *col;
39✔
839

840
        if (_ctx_valid(ctx))
39✔
841
                return _rc_filter(-EINVAL);
39✔
842
        col = (struct db_filter_col *)ctx;
39✔
843

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