Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/gen_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1583,7 +1583,7 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
unsigned int *blks_added, uint32_t optimize,
unsigned int *bintree_levels)
{
struct db_sys_list *s_head = NULL, *s_tail = NULL, *s_iter;
struct db_sys_list *s_head = NULL, *s_tail = NULL, *s_iter, *s_first = NULL;
unsigned int syscall_cnt, empty_cnt = 0;
uint64_t *bintree_hashes = NULL, nxt_hsh;
unsigned int *bintree_syscalls = NULL;
Expand Down Expand Up @@ -1623,6 +1623,18 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
*/
acc_reset = false;

/* the first syscall in the filter loads the syscall number for the
* ones that follow, so it must be the first syscall that is not
* omitted below; the head of the sorted list may be a pseudo-syscall
* or an entry that only carries a priority, and if we used it, no
* syscall would load the number */
for (s_iter = s_head; s_iter != NULL; s_iter = s_iter->pri_nxt) {
if (!_skip_syscall(state, s_iter)) {
s_first = s_iter;
break;
}
}

syscall_cnt = 0;

/* create the syscall filters and add them to block list group */
Expand All @@ -1641,7 +1653,7 @@ static int _gen_bpf_syscalls(struct bpf_state *state,

/* build the syscall filter */
state->b_new = _gen_bpf_syscall(state, s_iter, nxt_hsh,
(s_iter == s_head ?
(s_iter == s_first ?
acc_reset : false));
if (state->b_new == NULL)
goto out;
Expand Down
85 changes: 85 additions & 0 deletions tests/65-sim-pseudo_syscall_first.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Seccomp Library test program
*
* Copyright (c) 2026 Sascha Grunert <sgrunert@redhat.com>
* Author: Sascha Grunert <sgrunert@redhat.com>
*/

/*
* This library is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License as
* published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see <http://www.gnu.org/licenses>.
*/

#include <errno.h>
#include <unistd.h>

#include <seccomp.h>

#include "util.h"

int main(int argc, char *argv[])
{
int rc;
struct util_options opts;
scmp_filter_ctx ctx = NULL;

rc = util_getopt(argc, argv, &opts);
if (rc < 0)
goto out;

ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL)
return ENOMEM;

rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE);
if (rc < 0)
goto out;
rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
if (rc < 0)
goto out;
rc = seccomp_arch_add(ctx, SCMP_ARCH_X86_64);
if (rc < 0)
goto out;
rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
if (rc < 0)
goto out;
rc = seccomp_arch_add(ctx, SCMP_ARCH_AARCH64);
if (rc < 0)
goto out;

/* a pseudo-syscall on every arch above, without conditions so that it
* sorts before the conditional rules and becomes the head of the
* syscall list, where it is omitted from the filter; x86 drops the
* rule when it is added, the others keep it */
rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(arm_fadvise64_64), 0);
if (rc < 0)
goto out;

/* the real rules must still be applied, which they are only if the
* filter loads the syscall number before testing them */
rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 1,
SCMP_A0(SCMP_CMP_EQ, 1));
if (rc < 0)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 1,
SCMP_A0(SCMP_CMP_EQ, 1));
if (rc < 0)
goto out;

rc = util_filter_output(&opts, ctx);
if (rc)
goto out;

out:
seccomp_release(ctx);
return (rc < 0 ? -rc : rc);
}
54 changes: 54 additions & 0 deletions tests/65-sim-pseudo_syscall_first.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python

#
# Seccomp Library test program
#
# Copyright (c) 2026 Sascha Grunert <sgrunert@redhat.com>
# Author: Sascha Grunert <sgrunert@redhat.com>
#

#
# This library is free software; you can redistribute it and/or modify it
# under the terms of version 2.1 of the GNU Lesser General Public License as
# published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, see <http://www.gnu.org/licenses>.
#

import argparse
import sys

import util

from seccomp import *

def test(args):
f = SyscallFilter(ALLOW)
f.remove_arch(Arch())
f.add_arch(Arch("x86"))
f.add_arch(Arch("x86_64"))
f.add_arch(Arch("x32"))
f.add_arch(Arch("aarch64"))
# a pseudo-syscall on every arch above, without conditions so that it
# sorts before the conditional rules and becomes the head of the syscall
# list, where it is omitted from the filter; x86 drops the rule when it
# is added, the others keep it
f.add_rule(KILL, "arm_fadvise64_64")
# the real rules must still be applied, which they are only if the
# filter loads the syscall number before testing them
f.add_rule(KILL, "read", Arg(0, EQ, 1))
f.add_rule(KILL, "write", Arg(0, EQ, 1))
return f

args = util.get_opt()
ctx = test(args)
util.filter_output(args, ctx)

# kate: syntax python;
# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
39 changes: 39 additions & 0 deletions tests/65-sim-pseudo_syscall_first.tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# libseccomp regression test automation data
#
# Copyright (c) 2026 Sascha Grunert <sgrunert@redhat.com>
# Author: Sascha Grunert <sgrunert@redhat.com>
#

test type: bpf-sim

# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
65-sim-pseudo_syscall_first +x86 read 1 N N N N N KILL
65-sim-pseudo_syscall_first +x86 read 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +x86 read 2-10 N N N N N ALLOW
65-sim-pseudo_syscall_first +x86 write 1 N N N N N KILL
65-sim-pseudo_syscall_first +x86 write 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +x86 open 1 N N N N N ALLOW
65-sim-pseudo_syscall_first +x86_64 read 1 N N N N N KILL
65-sim-pseudo_syscall_first +x86_64 read 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +x86_64 read 2-10 N N N N N ALLOW
65-sim-pseudo_syscall_first +x86_64 write 1 N N N N N KILL
65-sim-pseudo_syscall_first +x86_64 write 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +x86_64 open 1 N N N N N ALLOW
65-sim-pseudo_syscall_first +x32 read 1 N N N N N KILL
65-sim-pseudo_syscall_first +x32 read 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +x32 read 2-10 N N N N N ALLOW
65-sim-pseudo_syscall_first +x32 write 1 N N N N N KILL
65-sim-pseudo_syscall_first +x32 write 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +x32 open 1 N N N N N ALLOW
65-sim-pseudo_syscall_first +aarch64 read 1 N N N N N KILL
65-sim-pseudo_syscall_first +aarch64 read 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +aarch64 read 2-10 N N N N N ALLOW
65-sim-pseudo_syscall_first +aarch64 write 1 N N N N N KILL
65-sim-pseudo_syscall_first +aarch64 write 0 N N N N N ALLOW
65-sim-pseudo_syscall_first +aarch64 openat 1 N N N N N ALLOW

test type: bpf-valgrind

# Testname
65-sim-pseudo_syscall_first
77 changes: 77 additions & 0 deletions tests/66-sim-priority_only_first.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Seccomp Library test program
*
* Copyright (c) 2026 Sascha Grunert <sgrunert@redhat.com>
* Author: Sascha Grunert <sgrunert@redhat.com>
*/

/*
* This library is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License as
* published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see <http://www.gnu.org/licenses>.
*/

#include <errno.h>
#include <unistd.h>

#include <seccomp.h>

#include "util.h"

int main(int argc, char *argv[])
{
int rc;
struct util_options opts;
scmp_filter_ctx ctx = NULL;

rc = util_getopt(argc, argv, &opts);
if (rc < 0)
goto out;

ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL)
return ENOMEM;

rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE);
if (rc < 0)
goto out;
rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
if (rc < 0)
goto out;
rc = seccomp_arch_add(ctx, SCMP_ARCH_AARCH64);
if (rc < 0)
goto out;

/* a priority without a rule leaves an entry that sorts first and is
* omitted from the filter, on every arch */
rc = seccomp_syscall_priority(ctx, SCMP_SYS(getpid), 255);
if (rc < 0)
goto out;

/* the real rules must still be applied, which they are only if the
* filter loads the syscall number before testing them */
rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 1,
SCMP_A0(SCMP_CMP_EQ, 1));
if (rc < 0)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 1,
SCMP_A0(SCMP_CMP_EQ, 1));
if (rc < 0)
goto out;

rc = util_filter_output(&opts, ctx);
if (rc)
goto out;

out:
seccomp_release(ctx);
return (rc < 0 ? -rc : rc);
}
50 changes: 50 additions & 0 deletions tests/66-sim-priority_only_first.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env python

#
# Seccomp Library test program
#
# Copyright (c) 2026 Sascha Grunert <sgrunert@redhat.com>
# Author: Sascha Grunert <sgrunert@redhat.com>
#

#
# This library is free software; you can redistribute it and/or modify it
# under the terms of version 2.1 of the GNU Lesser General Public License as
# published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, see <http://www.gnu.org/licenses>.
#

import argparse
import sys

import util

from seccomp import *

def test(args):
f = SyscallFilter(ALLOW)
f.remove_arch(Arch())
f.add_arch(Arch("x86"))
f.add_arch(Arch("aarch64"))
# a priority without a rule leaves an entry that sorts first and is
# omitted from the filter, on every arch
f.syscall_priority("getpid", 255)
# the real rules must still be applied, which they are only if the
# filter loads the syscall number before testing them
f.add_rule(KILL, "read", Arg(0, EQ, 1))
f.add_rule(KILL, "write", Arg(0, EQ, 1))
return f

args = util.get_opt()
ctx = test(args)
util.filter_output(args, ctx)

# kate: syntax python;
# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
29 changes: 29 additions & 0 deletions tests/66-sim-priority_only_first.tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# libseccomp regression test automation data
#
# Copyright (c) 2026 Sascha Grunert <sgrunert@redhat.com>
# Author: Sascha Grunert <sgrunert@redhat.com>
#

test type: bpf-sim

# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
66-sim-priority_only_first +x86 read 1 N N N N N KILL
66-sim-priority_only_first +x86 read 0 N N N N N ALLOW
66-sim-priority_only_first +x86 read 2-10 N N N N N ALLOW
66-sim-priority_only_first +x86 write 1 N N N N N KILL
66-sim-priority_only_first +x86 write 0 N N N N N ALLOW
66-sim-priority_only_first +x86 getpid N N N N N N ALLOW
66-sim-priority_only_first +x86 open 1 N N N N N ALLOW
66-sim-priority_only_first +aarch64 read 1 N N N N N KILL
66-sim-priority_only_first +aarch64 read 0 N N N N N ALLOW
66-sim-priority_only_first +aarch64 read 2-10 N N N N N ALLOW
66-sim-priority_only_first +aarch64 write 1 N N N N N KILL
66-sim-priority_only_first +aarch64 write 0 N N N N N ALLOW
66-sim-priority_only_first +aarch64 getpid N N N N N N ALLOW
66-sim-priority_only_first +aarch64 openat 1 N N N N N ALLOW

test type: bpf-valgrind

# Testname
66-sim-priority_only_first
Loading
Loading