diff options
author | Tom Hromatka <tom.hromatka@oracle.com> | 2020-06-30 08:30:29 -0600 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2020-07-13 21:14:15 -0400 |
commit | ad873bdec9817f53f380d3b20cf6ab6f70a7d2be (patch) | |
tree | 274af24b78b65240fe45633aac0af71cf6914e49 | |
parent | 858df15ea6354b6a75979720bce057b696545fd0 (diff) | |
download | libseccomp-ad873bdec9817f53f380d3b20cf6ab6f70a7d2be.tar.gz |
bpf: do not add pseudo-syscalls to the BPF filter
Unless explicitly instructed via the SCMP_FLTATR_API_TSKIP attribute,
pseudo-syscalls should not be added to the BPF filter. Note that
as of this commit, pseudo-syscalls are displayed in the PFC filter.
Reported-by: Vitaly Chikunov <vt@altlinux.org>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r-- | src/gen_bpf.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/src/gen_bpf.c b/src/gen_bpf.c index 2ed8abd..02ea3f6 100644 --- a/src/gen_bpf.c +++ b/src/gen_bpf.c @@ -1292,6 +1292,49 @@ static int _gen_bpf_insert(struct bpf_state *state, struct bpf_instr *instr, } /** + * Decide if we need to omit the syscall from the BPF filter + * @param state the BPF state + * @param syscall syscall being tested + * @return true if syscall is to be skipped, false otherwise + */ +static inline bool _skip_syscall(struct bpf_state *state, + struct db_sys_list *syscall) +{ + if (!syscall->valid) + return true; + + /* psuedo-syscalls should not be added to the filter unless explicity + * requested via SCMP_FLTATR_API_TSKIP + */ + if (((int)syscall->num < 0) && + (state->attr->api_tskip == 0 || syscall->num != -1)) + return true; + + return false; +} + +/** + * Calculate the number of syscalls that will be in the BPF filter + * @param state the BPF state + * @param s_tail the last syscall in the syscall linked list + */ +static unsigned int _get_syscall_cnt(struct bpf_state *state, + struct db_sys_list *s_tail) +{ + struct db_sys_list *s_iter; + unsigned int syscall_cnt = 0; + + for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) { + if (_skip_syscall(state, s_iter)) + continue; + + syscall_cnt++; + } + + return syscall_cnt; +} + +/** * Calculate the number of levels in the binary tree * @param syscall_cnt the number of syscalls in this seccomp filter */ @@ -1513,7 +1556,7 @@ static int _gen_bpf_syscalls(struct bpf_state *state, unsigned int *bintree_levels) { struct db_sys_list *s_head = NULL, *s_tail = NULL, *s_iter; - unsigned int syscall_cnt = 0, empty_cnt = 0; + unsigned int syscall_cnt, empty_cnt = 0; uint64_t *bintree_hashes = NULL, nxt_hsh; unsigned int *bintree_syscalls = NULL; bool acc_reset; @@ -1532,8 +1575,9 @@ static int _gen_bpf_syscalls(struct bpf_state *state, _sys_sort(db_secondary->syscalls, &s_head, &s_tail, optimize); if (optimize == 2) { + syscall_cnt = _get_syscall_cnt(state, s_tail); rc = _gen_bpf_init_bintree(&bintree_hashes, &bintree_syscalls, - bintree_levels, db->syscall_cnt, + bintree_levels, syscall_cnt, &empty_cnt); if (rc < 0) goto out; @@ -1551,9 +1595,11 @@ static int _gen_bpf_syscalls(struct bpf_state *state, */ acc_reset = false; + syscall_cnt = 0; + /* create the syscall filters and add them to block list group */ for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) { - if (!s_iter->valid) + if (_skip_syscall(state, s_iter)) continue; if (*bintree_levels > 0 && |