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

drakenclimber / libseccomp / 6279355589

21 Sep 2023 04:53PM UTC coverage: 89.542% (-0.3%) from 89.89%
6279355589

push

github

pcmoore
api: add transaction support to the libseccomp API

While libseccomp has internally has transaction support for some time
now, it hasn't been accessible to callers through the libseccomp API.
This patch adds a transaction API as well as supporting documentation
and a new unit regression test.

  int seccomp_transaction_start(const scmp_filter_ctx ctx)
  int seccomp_transaction_commit(const scmp_filter_ctx ctx)
  void seccomp_transaction_reject(const scmp_filter_ctx ctx)

Signed-off-by: Paul Moore <paul@paul-moore.com>

30 of 30 new or added lines in 2 files covered. (100.0%)

2697 of 3012 relevant lines covered (89.54%)

299730.21 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)
125,902✔
62
{
63
        /* pass through success values */
64
        if (err >= 0)
124,463✔
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)
10,294✔
129
{
130
        return db_col_valid((struct db_filter_col *)ctx);
10,294✔
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,385✔
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,379✔
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,855✔
162
{
163
        unsigned int level = 1;
7,855✔
164

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

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

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

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

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

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

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

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

328
        return db_col_init(def_action);
7,836✔
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,810✔
353
{
354
        db_col_release((struct db_filter_col *)ctx);
7,810✔
355
}
7,810✔
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,708✔
377
{
378
        const struct arch_def *arch;
7,708✔
379

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

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

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

390
/* NOTE - function header comment in include/seccomp.h */
391
API uint32_t seccomp_arch_native(void)
1,631✔
392
{
393
        return arch_def_native->token;
1,631✔
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,106✔
412
{
413
        const struct arch_def *arch;
12,106✔
414
        struct db_filter_col *col = (struct db_filter_col *)ctx;
12,106✔
415

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

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

425
        return _rc_filter(db_col_db_new(col, arch));
12,106✔
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,013✔
430
{
431
        struct db_filter_col *col = (struct db_filter_col *)ctx;
5,013✔
432

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

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

441
        return _rc_filter(db_col_db_remove(col, arch_token));
5,013✔
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,395✔
522
                                             const char *name)
523
{
524
        int rc;
1,395✔
525
        int syscall;
1,395✔
526
        const struct arch_def *arch;
1,395✔
527

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

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

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

549
        return syscall;
1,339✔
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,842✔
572
                               uint32_t action, int syscall,
573
                               unsigned int arg_cnt,
574
                               const struct scmp_arg_cmp *arg_array)
575
{
576
        int rc;
21,842✔
577
        struct db_filter_col *col = (struct db_filter_col *)ctx;
21,842✔
578

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

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

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

593
        return _rc_filter(db_col_rule_add(col, 0, action,
21,838✔
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,844✔
599
                         uint32_t action, int syscall,
600
                         unsigned int arg_cnt, ...)
601
{
602
        int rc;
21,844✔
603
        int iter;
21,844✔
604
        struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
21,844✔
605
        va_list arg_list;
21,844✔
606

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

611
        va_start(arg_list, arg_cnt);
21,842✔
612
        for (iter = 0; iter < arg_cnt; ++iter)
36,329✔
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,842✔
615
        va_end(arg_list);
21,842✔
616

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

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

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

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

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

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

646
        return _rc_filter(db_col_rule_add(col, 1, action,
31,474✔
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,
29,625✔
652
                               uint32_t action, int syscall,
653
                               unsigned int arg_cnt, ...)
654
{
655
        int rc;
29,625✔
656
        int iter;
29,625✔
657
        struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
29,625✔
658
        va_list arg_list;
29,625✔
659

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

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

671
        return _rc_filter(rc);
29,625✔
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,796✔
747
{
748
        int rc;
7,796✔
749
        struct db_filter_col *col;
7,796✔
750
        struct bpf_program *program;
7,796✔
751

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

756
        rc = db_col_precompute(col);
7,795✔
757
        if (rc < 0)
7,795✔
758
                return _rc_filter(rc);
×
759
        program = col->prgm_bpf;
7,795✔
760
        rc = write(fd, program->blks, BPF_PGM_SIZE(program));
7,795✔
761
        if (rc < 0)
7,795✔
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)
952✔
798
{
799
        int rc;
952✔
800
        struct db_filter_col *col;
952✔
801

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

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

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

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

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

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

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

831
        db_col_transaction_commit(col, true);
714✔
832
        return _rc_filter(0);
714✔
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

© 2025 Coveralls, Inc