• 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

87.01
/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,
79,801✔
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)
79,801✔
50
        _ABI_SYSCALL_RES_NAME_CHK(bind)
76,852✔
51
        _ABI_SYSCALL_RES_NAME_CHK(connect)
76,404✔
52
        _ABI_SYSCALL_RES_NAME_CHK(listen)
73,482✔
53
        _ABI_SYSCALL_RES_NAME_CHK(accept)
73,034✔
54
        _ABI_SYSCALL_RES_NAME_CHK(getsockname)
72,341✔
55
        _ABI_SYSCALL_RES_NAME_CHK(getpeername)
71,893✔
56
        _ABI_SYSCALL_RES_NAME_CHK(socketpair)
71,445✔
57
        _ABI_SYSCALL_RES_NAME_CHK(send)
70,997✔
58
        _ABI_SYSCALL_RES_NAME_CHK(recv)
70,549✔
59
        _ABI_SYSCALL_RES_NAME_CHK(sendto)
70,101✔
60
        _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
69,653✔
61
        _ABI_SYSCALL_RES_NAME_CHK(shutdown)
69,205✔
62
        _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
66,283✔
63
        _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
65,835✔
64
        _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
65,387✔
65
        _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
64,939✔
66
        _ABI_SYSCALL_RES_NAME_CHK(accept4)
64,491✔
67
        _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
63,799✔
68
        _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
63,348✔
69
        _ABI_SYSCALL_RES_NAME_CHK(semop)
62,900✔
70
        _ABI_SYSCALL_RES_NAME_CHK(semget)
62,204✔
71
        _ABI_SYSCALL_RES_NAME_CHK(semctl)
61,508✔
72
        _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
60,812✔
73
        _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
60,116✔
74
        _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
59,420✔
75
        _ABI_SYSCALL_RES_NAME_CHK(msgget)
58,724✔
76
        _ABI_SYSCALL_RES_NAME_CHK(msgctl)
58,028✔
77
        _ABI_SYSCALL_RES_NAME_CHK(shmat)
57,332✔
78
        _ABI_SYSCALL_RES_NAME_CHK(shmdt)
56,636✔
79
        _ABI_SYSCALL_RES_NAME_CHK(shmget)
55,940✔
80
        _ABI_SYSCALL_RES_NAME_CHK(shmctl)
55,244✔
81

82
        return arch->syscall_resolve_name_raw(name);
54,538✔
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,960✔
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,960✔
102
        _ABI_SYSCALL_RES_NUM_CHK(bind)
2,950✔
103
        _ABI_SYSCALL_RES_NUM_CHK(connect)
2,940✔
104
        _ABI_SYSCALL_RES_NUM_CHK(listen)
2,930✔
105
        _ABI_SYSCALL_RES_NUM_CHK(accept)
2,920✔
106
        _ABI_SYSCALL_RES_NUM_CHK(getsockname)
2,910✔
107
        _ABI_SYSCALL_RES_NUM_CHK(getpeername)
2,900✔
108
        _ABI_SYSCALL_RES_NUM_CHK(socketpair)
2,890✔
109
        _ABI_SYSCALL_RES_NUM_CHK(send)
2,880✔
110
        _ABI_SYSCALL_RES_NUM_CHK(recv)
2,870✔
111
        _ABI_SYSCALL_RES_NUM_CHK(sendto)
2,860✔
112
        _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
2,850✔
113
        _ABI_SYSCALL_RES_NUM_CHK(shutdown)
2,840✔
114
        _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
2,830✔
115
        _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
2,820✔
116
        _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
2,810✔
117
        _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
2,800✔
118
        _ABI_SYSCALL_RES_NUM_CHK(accept4)
2,790✔
119
        _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
2,780✔
120
        _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
2,770✔
121
        _ABI_SYSCALL_RES_NUM_CHK(semop)
2,760✔
122
        _ABI_SYSCALL_RES_NUM_CHK(semget)
2,750✔
123
        _ABI_SYSCALL_RES_NUM_CHK(semctl)
2,740✔
124
        _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
2,730✔
125
        _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
2,720✔
126
        _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
2,710✔
127
        _ABI_SYSCALL_RES_NUM_CHK(msgget)
2,700✔
128
        _ABI_SYSCALL_RES_NUM_CHK(msgctl)
2,690✔
129
        _ABI_SYSCALL_RES_NUM_CHK(shmat)
2,680✔
130
        _ABI_SYSCALL_RES_NUM_CHK(shmdt)
2,670✔
131
        _ABI_SYSCALL_RES_NUM_CHK(shmget)
2,660✔
132
        _ABI_SYSCALL_RES_NUM_CHK(shmctl)
2,650✔
133

134
        return arch->syscall_resolve_num_raw(num);
2,640✔
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)
86✔
354
{
355
        int sys = *syscall;
86✔
356

357
        if (sys <= -100 && sys >= -120)
86✔
358
                *syscall = arch->sys_socketcall;
76✔
359
        else if (sys <= -200 && sys >= -224)
10✔
360
                *syscall = arch->sys_ipc;
10✔
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)
76,708✔
382
{
383
        int rc = 0;
76,708✔
384
        unsigned int iter;
76,708✔
385
        int sys = rule->syscall;
76,708✔
386
        int sys_a, sys_b;
76,708✔
387
        struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
76,708✔
388

389
        if (_abi_syscall_socket_test(db->arch, sys)) {
76,708✔
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)) {
59,891✔
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) {
51,539✔
538
                /* normal syscall processing */
539
                rc = db_rule_add(db, rule);
50,434✔
540
                if (rc < 0)
50,434✔
541
                        goto add_return;
×
542
        } else if (rule->strict) {
1,105✔
543
                rc = -EDOM;
364✔
544
                goto add_return;
364✔
545
        }
546

547
add_return:
741✔
548
        if (rule_dup != NULL)
25,533✔
549
                free(rule_dup);
25,168✔
550
        return rc;
76,708✔
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

© 2025 Coveralls, Inc