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

drakenclimber / libseccomp / 13399061959

18 Feb 2025 07:52PM UTC coverage: 90.639% (-0.1%) from 90.78%
13399061959

push

github

drakenclimber
doc: Add documentation for max kernel version attributes

Add documentation for SCMP_FLTATR_ACT_UNKNOWN and SCMP_FLTATR_CTL_KVER.

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

2866 of 3162 relevant lines covered (90.64%)

1389731.65 hits per line

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

84.75
/src/syscalls.c
1
/**
2
 * Enhanced Seccomp Syscall Table Functions
3
 *
4
 * Copyright (c) 2012, 2020 Red Hat <pmoore@redhat.com>
5
 * Author: Paul Moore <paul@paul-moore.com>
6
 * gperf support: Giuseppe Scrivano <gscrivan@redhat.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 <stdlib.h>
24
#include <errno.h>
25
#include <string.h>
26
#include <seccomp.h>
27

28
#include "db.h"
29
#include "arch.h"
30
#include "syscalls.h"
31

32
/**
33
 * Resolve a syscall name to a number
34
 * @param arch the arch definition
35
 * @param name the syscall name
36
 *
37
 * Resolve the given syscall name to the syscall number using the syscall table.
38
 * Returns the syscall number on success, including negative pseudo syscall
39
 * numbers; returns __NR_SCMP_ERROR on failure.
40
 *
41
 */
42
int abi_syscall_resolve_name_munge(const struct arch_def *arch,
78,374✔
43
                                   const char *name)
44
{
45

46
#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
47
        if (!strcmp(name, #NAME)) return __PNR_##NAME;
48

49
        _ABI_SYSCALL_RES_NAME_CHK(socket)
78,374✔
50
        _ABI_SYSCALL_RES_NAME_CHK(bind)
75,434✔
51
        _ABI_SYSCALL_RES_NAME_CHK(connect)
74,986✔
52
        _ABI_SYSCALL_RES_NAME_CHK(listen)
72,064✔
53
        _ABI_SYSCALL_RES_NAME_CHK(accept)
71,616✔
54
        _ABI_SYSCALL_RES_NAME_CHK(getsockname)
70,923✔
55
        _ABI_SYSCALL_RES_NAME_CHK(getpeername)
70,475✔
56
        _ABI_SYSCALL_RES_NAME_CHK(socketpair)
70,027✔
57
        _ABI_SYSCALL_RES_NAME_CHK(send)
69,579✔
58
        _ABI_SYSCALL_RES_NAME_CHK(recv)
69,131✔
59
        _ABI_SYSCALL_RES_NAME_CHK(sendto)
68,683✔
60
        _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
68,235✔
61
        _ABI_SYSCALL_RES_NAME_CHK(shutdown)
67,787✔
62
        _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
64,865✔
63
        _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
64,417✔
64
        _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
63,969✔
65
        _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
63,521✔
66
        _ABI_SYSCALL_RES_NAME_CHK(accept4)
63,073✔
67
        _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
62,381✔
68
        _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
61,931✔
69
        _ABI_SYSCALL_RES_NAME_CHK(semop)
61,483✔
70
        _ABI_SYSCALL_RES_NAME_CHK(semget)
60,787✔
71
        _ABI_SYSCALL_RES_NAME_CHK(semctl)
60,091✔
72
        _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
59,395✔
73
        _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
58,698✔
74
        _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
58,002✔
75
        _ABI_SYSCALL_RES_NAME_CHK(msgget)
57,306✔
76
        _ABI_SYSCALL_RES_NAME_CHK(msgctl)
56,610✔
77
        _ABI_SYSCALL_RES_NAME_CHK(shmat)
55,914✔
78
        _ABI_SYSCALL_RES_NAME_CHK(shmdt)
55,218✔
79
        _ABI_SYSCALL_RES_NAME_CHK(shmget)
54,522✔
80
        _ABI_SYSCALL_RES_NAME_CHK(shmctl)
53,826✔
81

82
        return arch->syscall_resolve_name_raw(name);
53,129✔
83
}
84

85
/**
86
 * Resolve a syscall number to a name
87
 * @param arch the arch definition
88
 * @param num the syscall number
89
 *
90
 * Resolve the given syscall number to the syscall name using the syscall table.
91
 * Returns a pointer to the syscall name string on success, including pseudo
92
 * syscall names; returns NULL on failure.
93
 *
94
 */
95
const char *abi_syscall_resolve_num_munge(const struct arch_def *arch, int num)
2,482✔
96
{
97

98
#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
99
        if (num == __PNR_##NAME) return #NAME;
100

101
        _ABI_SYSCALL_RES_NUM_CHK(socket)
2,482✔
102
        _ABI_SYSCALL_RES_NUM_CHK(bind)
2,481✔
103
        _ABI_SYSCALL_RES_NUM_CHK(connect)
2,480✔
104
        _ABI_SYSCALL_RES_NUM_CHK(listen)
2,479✔
105
        _ABI_SYSCALL_RES_NUM_CHK(accept)
2,478✔
106
        _ABI_SYSCALL_RES_NUM_CHK(getsockname)
2,477✔
107
        _ABI_SYSCALL_RES_NUM_CHK(getpeername)
2,476✔
108
        _ABI_SYSCALL_RES_NUM_CHK(socketpair)
2,475✔
109
        _ABI_SYSCALL_RES_NUM_CHK(send)
2,474✔
110
        _ABI_SYSCALL_RES_NUM_CHK(recv)
2,473✔
111
        _ABI_SYSCALL_RES_NUM_CHK(sendto)
2,472✔
112
        _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
2,471✔
113
        _ABI_SYSCALL_RES_NUM_CHK(shutdown)
2,470✔
114
        _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
2,469✔
115
        _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
2,468✔
116
        _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
2,467✔
117
        _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
2,466✔
118
        _ABI_SYSCALL_RES_NUM_CHK(accept4)
2,465✔
119
        _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
2,464✔
120
        _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
2,463✔
121
        _ABI_SYSCALL_RES_NUM_CHK(semop)
2,462✔
122
        _ABI_SYSCALL_RES_NUM_CHK(semget)
2,461✔
123
        _ABI_SYSCALL_RES_NUM_CHK(semctl)
2,460✔
124
        _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
2,459✔
125
        _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
2,458✔
126
        _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
2,457✔
127
        _ABI_SYSCALL_RES_NUM_CHK(msgget)
2,456✔
128
        _ABI_SYSCALL_RES_NUM_CHK(msgctl)
2,455✔
129
        _ABI_SYSCALL_RES_NUM_CHK(shmat)
2,454✔
130
        _ABI_SYSCALL_RES_NUM_CHK(shmdt)
2,453✔
131
        _ABI_SYSCALL_RES_NUM_CHK(shmget)
2,452✔
132
        _ABI_SYSCALL_RES_NUM_CHK(shmctl)
2,451✔
133

134
        return arch->syscall_resolve_num_raw(num);
2,450✔
135
}
136

137
/**
138
 * Check if a syscall is a socket syscall
139
 * @param arch the arch definition
140
 * @param sys the syscall number
141
 *
142
 * Returns true if the syscall is a socket related syscall, false otherwise.
143
 *
144
 */
145
static bool _abi_syscall_socket_test(const struct arch_def *arch, int sys)
146
{
147
        const char *name;
148

149
        /* multiplexed pseudo-syscalls */
150
        if (sys <= -100 && sys >= -120)
151
                return true;
152

153
        name = arch->syscall_resolve_num_raw(sys);
154
        if (!name)
155
                return false;
156

157
#define _ABI_SYSCALL_SOCK_CHK(NAME) \
158
        if (!strcmp(name, #NAME)) return true;
159

160
        _ABI_SYSCALL_SOCK_CHK(socket)
161
        _ABI_SYSCALL_SOCK_CHK(bind)
162
        _ABI_SYSCALL_SOCK_CHK(connect)
163
        _ABI_SYSCALL_SOCK_CHK(listen)
164
        _ABI_SYSCALL_SOCK_CHK(accept)
165
        _ABI_SYSCALL_SOCK_CHK(getsockname)
166
        _ABI_SYSCALL_SOCK_CHK(getpeername)
167
        _ABI_SYSCALL_SOCK_CHK(socketpair)
168
        _ABI_SYSCALL_SOCK_CHK(send)
169
        _ABI_SYSCALL_SOCK_CHK(recv)
170
        _ABI_SYSCALL_SOCK_CHK(sendto)
171
        _ABI_SYSCALL_SOCK_CHK(recvfrom)
172
        _ABI_SYSCALL_SOCK_CHK(shutdown)
173
        _ABI_SYSCALL_SOCK_CHK(setsockopt)
174
        _ABI_SYSCALL_SOCK_CHK(getsockopt)
175
        _ABI_SYSCALL_SOCK_CHK(sendmsg)
176
        _ABI_SYSCALL_SOCK_CHK(recvmsg)
177
        _ABI_SYSCALL_SOCK_CHK(accept4)
178
        _ABI_SYSCALL_SOCK_CHK(recvmmsg)
179
        _ABI_SYSCALL_SOCK_CHK(sendmmsg)
180

181
        return false;
182
}
183

184
/**
185
 * Check if a syscall is an ipc syscall
186
 * @param arch the arch definition
187
 * @param sys the syscall number
188
 *
189
 * Returns true if the syscall is an ipc related syscall, false otherwise.
190
 *
191
 */
192
static bool _abi_syscall_ipc_test(const struct arch_def *arch, int sys)
193
{
194
        const char *name;
195

196
        /* multiplexed pseudo-syscalls */
197
        if (sys <= -200 && sys >= -224)
198
                return true;
199

200
        name = arch->syscall_resolve_num_raw(sys);
201
        if (!name)
202
                return false;
203

204
#define _ABI_SYSCALL_IPC_CHK(NAME) \
205
        if (!strcmp(name, #NAME)) return true;
206

207
        _ABI_SYSCALL_IPC_CHK(semop)
208
        _ABI_SYSCALL_IPC_CHK(semget)
209
        _ABI_SYSCALL_IPC_CHK(semctl)
210
        _ABI_SYSCALL_IPC_CHK(semtimedop)
211
        _ABI_SYSCALL_IPC_CHK(msgsnd)
212
        _ABI_SYSCALL_IPC_CHK(msgrcv)
213
        _ABI_SYSCALL_IPC_CHK(msgget)
214
        _ABI_SYSCALL_IPC_CHK(msgctl)
215
        _ABI_SYSCALL_IPC_CHK(shmat)
216
        _ABI_SYSCALL_IPC_CHK(shmdt)
217
        _ABI_SYSCALL_IPC_CHK(shmget)
218
        _ABI_SYSCALL_IPC_CHK(shmctl)
219

220
        return false;
221
}
222

223
/**
224
 * Convert a multiplexed pseudo syscall into a direct syscall
225
 * @param arch the arch definition
226
 * @param syscall the multiplexed pseudo syscall number
227
 *
228
 * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
229
 * no related syscall, or __NR_SCMP_ERROR otherwise.
230
 *
231
 */
232
static int _abi_syscall_demux(const struct arch_def *arch, int syscall)
233
{
234
        int sys = __NR_SCMP_UNDEF;
235

236
#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
237
case __PNR_##NAME: \
238
        sys = arch->syscall_resolve_name_raw(#NAME); break;
239

240
        switch (syscall) {
241
                _ABI_SYSCALL_DEMUX_CHK(socket)
242
                _ABI_SYSCALL_DEMUX_CHK(bind)
243
                _ABI_SYSCALL_DEMUX_CHK(connect)
244
                _ABI_SYSCALL_DEMUX_CHK(listen)
245
                _ABI_SYSCALL_DEMUX_CHK(accept)
246
                _ABI_SYSCALL_DEMUX_CHK(getsockname)
247
                _ABI_SYSCALL_DEMUX_CHK(getpeername)
248
                _ABI_SYSCALL_DEMUX_CHK(socketpair)
249
                _ABI_SYSCALL_DEMUX_CHK(send)
250
                _ABI_SYSCALL_DEMUX_CHK(recv)
251
                _ABI_SYSCALL_DEMUX_CHK(sendto)
252
                _ABI_SYSCALL_DEMUX_CHK(recvfrom)
253
                _ABI_SYSCALL_DEMUX_CHK(shutdown)
254
                _ABI_SYSCALL_DEMUX_CHK(setsockopt)
255
                _ABI_SYSCALL_DEMUX_CHK(getsockopt)
256
                _ABI_SYSCALL_DEMUX_CHK(sendmsg)
257
                _ABI_SYSCALL_DEMUX_CHK(recvmsg)
258
                _ABI_SYSCALL_DEMUX_CHK(accept4)
259
                _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
260
                _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
261
                _ABI_SYSCALL_DEMUX_CHK(semop)
262
                _ABI_SYSCALL_DEMUX_CHK(semget)
263
                _ABI_SYSCALL_DEMUX_CHK(semctl)
264
                _ABI_SYSCALL_DEMUX_CHK(semtimedop)
265
                _ABI_SYSCALL_DEMUX_CHK(msgsnd)
266
                _ABI_SYSCALL_DEMUX_CHK(msgrcv)
267
                _ABI_SYSCALL_DEMUX_CHK(msgget)
268
                _ABI_SYSCALL_DEMUX_CHK(msgctl)
269
                _ABI_SYSCALL_DEMUX_CHK(shmat)
270
                _ABI_SYSCALL_DEMUX_CHK(shmdt)
271
                _ABI_SYSCALL_DEMUX_CHK(shmget)
272
                _ABI_SYSCALL_DEMUX_CHK(shmctl)
273
        }
274

275
        /* this looks odd because the arch resolver returns _ERROR if it can't
276
         * resolve the syscall, but we want to use _UNDEF for that, so we set
277
         * 'sys' to a sentinel value of _UNDEF and if it is error here we know
278
         * the resolve failed to find a match */
279
        if (sys == __NR_SCMP_UNDEF)
280
                sys = __NR_SCMP_ERROR;
281
        else if (sys == __NR_SCMP_ERROR)
282
                sys = __NR_SCMP_UNDEF;
283

284
        return sys;
285
}
286

287
/**
288
 * Convert a direct syscall into multiplexed pseudo socket syscall
289
 * @param arch the arch definition
290
 * @param syscall the direct syscall
291
 *
292
 * Return the related multiplexed pseudo syscall number, __NR_SCMP_UNDEF is
293
 * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
294
 *
295
 */
296
static int _abi_syscall_mux(const struct arch_def *arch, int syscall)
297
{
298
        const char *sys;
299

300
        sys = arch->syscall_resolve_num_raw(syscall);
301
        if (!sys)
302
                return __NR_SCMP_ERROR;
303

304
#define _ABI_SYSCALL_MUX_CHK(NAME) \
305
        if (!strcmp(sys, #NAME)) return __PNR_##NAME;
306

307
        _ABI_SYSCALL_MUX_CHK(socket)
308
        _ABI_SYSCALL_MUX_CHK(bind)
309
        _ABI_SYSCALL_MUX_CHK(connect)
310
        _ABI_SYSCALL_MUX_CHK(listen)
311
        _ABI_SYSCALL_MUX_CHK(accept)
312
        _ABI_SYSCALL_MUX_CHK(getsockname)
313
        _ABI_SYSCALL_MUX_CHK(getpeername)
314
        _ABI_SYSCALL_MUX_CHK(socketpair)
315
        _ABI_SYSCALL_MUX_CHK(send)
316
        _ABI_SYSCALL_MUX_CHK(recv)
317
        _ABI_SYSCALL_MUX_CHK(sendto)
318
        _ABI_SYSCALL_MUX_CHK(recvfrom)
319
        _ABI_SYSCALL_MUX_CHK(shutdown)
320
        _ABI_SYSCALL_MUX_CHK(setsockopt)
321
        _ABI_SYSCALL_MUX_CHK(getsockopt)
322
        _ABI_SYSCALL_MUX_CHK(sendmsg)
323
        _ABI_SYSCALL_MUX_CHK(recvmsg)
324
        _ABI_SYSCALL_MUX_CHK(accept4)
325
        _ABI_SYSCALL_MUX_CHK(recvmmsg)
326
        _ABI_SYSCALL_MUX_CHK(sendmmsg)
327
        _ABI_SYSCALL_MUX_CHK(semop)
328
        _ABI_SYSCALL_MUX_CHK(semget)
329
        _ABI_SYSCALL_MUX_CHK(semctl)
330
        _ABI_SYSCALL_MUX_CHK(semtimedop)
331
        _ABI_SYSCALL_MUX_CHK(msgsnd)
332
        _ABI_SYSCALL_MUX_CHK(msgrcv)
333
        _ABI_SYSCALL_MUX_CHK(msgget)
334
        _ABI_SYSCALL_MUX_CHK(msgctl)
335
        _ABI_SYSCALL_MUX_CHK(shmat)
336
        _ABI_SYSCALL_MUX_CHK(shmdt)
337
        _ABI_SYSCALL_MUX_CHK(shmget)
338
        _ABI_SYSCALL_MUX_CHK(shmctl)
339

340
        return __NR_SCMP_ERROR;
341
}
342

343
/**
344
 * Rewrite a syscall value to match the architecture
345
 * @param arch the arch definition
346
 * @param syscall the syscall number
347
 *
348
 * Syscalls can vary across different architectures so this function rewrites
349
 * the syscall into the correct value for the specified architecture.  Returns
350
 * zero on success, negative values on failure.
351
 *
352
 */
353
int abi_syscall_rewrite(const struct arch_def *arch, int *syscall)
68✔
354
{
355
        int sys = *syscall;
68✔
356

357
        if (sys <= -100 && sys >= -120)
68✔
358
                *syscall = arch->sys_socketcall;
67✔
359
        else if (sys <= -200 && sys >= -224)
1✔
360
                *syscall = arch->sys_ipc;
1✔
361
        else if (sys < 0)
×
362
                return -EDOM;
×
363

364
        return 0;
365
}
366

367
/**
368
 * add a new rule to the abi seccomp filter
369
 * @param db the seccomp filter db
370
 * @param rule the filter rule
371
 *
372
 * This function adds a new syscall filter to the seccomp filter db, making any
373
 * necessary adjustments for the abi ABI.  Returns zero on success, negative
374
 * values on failure.
375
 *
376
 * It is important to note that in the case of failure the db may be corrupted,
377
 * the caller must use the transaction mechanism if the db integrity is
378
 * important.
379
 *
380
 */
381
int abi_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
75,615✔
382
{
383
        int rc = 0;
75,615✔
384
        unsigned int iter;
75,615✔
385
        int sys = rule->syscall;
75,615✔
386
        int sys_a, sys_b;
75,615✔
387
        struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
75,615✔
388

389
        if (_abi_syscall_socket_test(db->arch, sys)) {
75,615✔
390
                /* socket syscalls */
391

392
                /* strict check for the multiplexed socket syscalls */
393
                for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
117,713✔
394
                        if ((rule->args[iter].valid != 0) && (rule->strict)) {
100,897✔
395
                                rc = -EINVAL;
1✔
396
                                goto add_return;
1✔
397
                        }
398
                }
399

400
                /* determine both the muxed and direct syscall numbers */
401
                if (sys > 0) {
16,816✔
402
                        sys_a = _abi_syscall_mux(db->arch, sys);
×
403
                        if (sys_a == __NR_SCMP_ERROR) {
×
404
                                rc = __NR_SCMP_ERROR;
×
405
                                goto add_return;
×
406
                        }
407
                        sys_b = sys;
408
                } else {
409
                        sys_a = sys;
16,816✔
410
                        sys_b = _abi_syscall_demux(db->arch, sys);
16,816✔
411
                        if (sys_b == __NR_SCMP_ERROR) {
16,816✔
412
                                rc = __NR_SCMP_ERROR;
×
413
                                goto add_return;
×
414
                        }
415
                }
416

417
                /* use rule_a for the multiplexed syscall and use rule_b for
418
                 * the direct wired syscall */
419

420
                if (sys_a == __NR_SCMP_UNDEF) {
16,816✔
421
                        rule_a = NULL;
422
                        rule_b = rule;
423
                } else if (sys_b == __NR_SCMP_UNDEF) {
16,816✔
424
                        rule_a = rule;
425
                        rule_b = NULL;
426
                } else {
427
                        /* need two rules, dup the first and link together */
428
                        rule_a = rule;
16,816✔
429
                        rule_dup = db_rule_dup(rule_a);
16,816✔
430
                        rule_b = rule_dup;
16,816✔
431
                        if (rule_b == NULL)
16,816✔
432
                                goto add_return;
×
433
                        rule_b->prev = rule_a;
16,816✔
434
                        rule_b->next = NULL;
16,816✔
435
                        rule_a->next = rule_b;
16,816✔
436
                }
437

438
                /* multiplexed socket syscalls */
439
                if (rule_a != NULL) {
16,816✔
440
                        rule_a->syscall = db->arch->sys_socketcall;
16,816✔
441
                        rule_a->args[0].arg = 0;
16,816✔
442
                        rule_a->args[0].op = SCMP_CMP_EQ;
16,816✔
443
                        rule_a->args[0].mask = DATUM_MAX;
16,816✔
444
                        rule_a->args[0].datum = (-sys_a) % 100;
16,816✔
445
                        rule_a->args[0].valid = 1;
16,816✔
446
                }
447

448
                /* direct wired socket syscalls */
449
                if (rule_b != NULL)
16,816✔
450
                        rule_b->syscall = sys_b;
16,816✔
451

452
                /* we should be protected by a transaction checkpoint */
453
                if (rule_a != NULL) {
16,816✔
454
                        rc = db_rule_add(db, rule_a);
16,816✔
455
                        if (rc < 0)
16,816✔
456
                                goto add_return;
×
457
                }
458
                if (rule_b != NULL) {
16,816✔
459
                        rc = db_rule_add(db, rule_b);
16,816✔
460
                        if (rc < 0)
16,816✔
461
                                goto add_return;
×
462
                }
463
        } else if (_abi_syscall_ipc_test(db->arch, sys)) {
58,798✔
464
                /* ipc syscalls */
465

466
                /* strict check for the multiplexed socket syscalls */
467
                for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
58,464✔
468
                        if ((rule->args[iter].valid != 0) && (rule->strict)) {
50,112✔
469
                                rc = -EINVAL;
×
470
                                goto add_return;
×
471
                        }
472
                }
473

474
                /* determine both the muxed and direct syscall numbers */
475
                if (sys > 0) {
8,352✔
476
                        sys_a = _abi_syscall_mux(db->arch, sys);
×
477
                        if (sys_a == __NR_SCMP_ERROR) {
×
478
                                rc = __NR_SCMP_ERROR;
×
479
                                goto add_return;
×
480
                        }
481
                        sys_b = sys;
482
                } else {
483
                        sys_a = sys;
8,352✔
484
                        sys_b = _abi_syscall_demux(db->arch, sys);
8,352✔
485
                        if (sys_b == __NR_SCMP_ERROR) {
8,352✔
486
                                rc = __NR_SCMP_ERROR;
×
487
                                goto add_return;
×
488
                        }
489
                }
490

491
                /* use rule_a for the multiplexed syscall and use rule_b for
492
                 * the direct wired syscall */
493

494
                if (sys_a == __NR_SCMP_UNDEF) {
8,352✔
495
                        rule_a = NULL;
496
                        rule_b = rule;
497
                } else if (sys_b == __NR_SCMP_UNDEF) {
8,352✔
498
                        rule_a = rule;
499
                        rule_b = NULL;
500
                } else {
501
                        /* need two rules, dup the first and link together */
502
                        rule_a = rule;
8,352✔
503
                        rule_dup = db_rule_dup(rule_a);
8,352✔
504
                        rule_b = rule_dup;
8,352✔
505
                        if (rule_b == NULL)
8,352✔
506
                                goto add_return;
×
507
                        rule_b->prev = rule_a;
8,352✔
508
                        rule_b->next = NULL;
8,352✔
509
                        rule_a->next = rule_b;
8,352✔
510
                }
511

512
                /* multiplexed socket syscalls */
513
                if (rule_a != NULL) {
8,352✔
514
                        rule_a->syscall = db->arch->sys_ipc;
8,352✔
515
                        rule_a->args[0].arg = 0;
8,352✔
516
                        rule_a->args[0].op = SCMP_CMP_EQ;
8,352✔
517
                        rule_a->args[0].mask = DATUM_MAX;
8,352✔
518
                        rule_a->args[0].datum = (-sys_a) % 200;
8,352✔
519
                        rule_a->args[0].valid = 1;
8,352✔
520
                }
521

522
                /* direct wired socket syscalls */
523
                if (rule_b != NULL)
8,352✔
524
                        rule_b->syscall = sys_b;
8,352✔
525

526
                /* we should be protected by a transaction checkpoint */
527
                if (rule_a != NULL) {
8,352✔
528
                        rc = db_rule_add(db, rule_a);
8,352✔
529
                        if (rc < 0)
8,352✔
530
                                goto add_return;
×
531
                }
532
                if (rule_b != NULL) {
8,352✔
533
                        rc = db_rule_add(db, rule_b);
8,352✔
534
                        if (rc < 0)
8,352✔
535
                                goto add_return;
×
536
                }
537
        } else if (sys >= 0) {
50,446✔
538
                /* normal syscall processing */
539
                rc = db_rule_add(db, rule);
50,446✔
540
                if (rc < 0)
50,446✔
541
                        goto add_return;
×
542
        } else if (rule->strict) {
×
543
                rc = -EDOM;
×
544
                goto add_return;
×
545
        }
546

547
add_return:
×
548
        if (rule_dup != NULL)
25,169✔
549
                free(rule_dup);
25,168✔
550
        return rc;
75,615✔
551
}
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