From 5201e324d2025b1febbade9bb90d6e405b92a14c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 4 Aug 2020 10:52:08 -0400 Subject: [PATCH 102/102] system: change our notification fd handling This commit changes how we handle the notification fd by only requesting it via _NEW_LISTENER if the filter has a _NOTIFY action in it. We also augment the seccomp_reset(NULL, ...) behavior so that it closes the notification fd before resetting the global state; applications that need to keep their notification fd open across a call to seccomp_reset(NULL, ...) can simply dup() it. Although one would have to wonder why the application would be calling seccomp_reset(NULL, ...) in that case. Signed-off-by: Paul Moore --- doc/man/man3/seccomp_init.3 | 6 ++++-- src/system.c | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/doc/man/man3/seccomp_init.3 b/doc/man/man3/seccomp_init.3 index 87520cd..7881c35 100644 --- a/doc/man/man3/seccomp_init.3 +++ b/doc/man/man3/seccomp_init.3 @@ -38,8 +38,10 @@ and can only be called after a call to .BR seccomp_init () has succeeded. If .BR seccomp_reset () -is called with a NULL filter, it resets the library's global task state; -normally this is not needed, but it may be required to continue using the +is called with a NULL filter, it resets the library's global task state, +including any notification file descriptors retrieved by +.BR seccomp_notify_fd(3) . +Normally this is not needed, but it may be required to continue using the library after a .BR fork () or diff --git a/src/system.c b/src/system.c index 3b43b2a..c646c65 100644 --- a/src/system.c +++ b/src/system.c @@ -84,7 +84,11 @@ static struct task_state state = { void sys_reset_state(void) { state.nr_seccomp = -1; + + if (state.notify_fd > 0) + close(state.notify_fd); state.notify_fd = -1; + state.sup_syscall = -1; state.sup_flag_tsync = -1; state.sup_flag_log = -1; @@ -353,6 +357,7 @@ int sys_filter_load(struct db_filter_col *col, bool rawrc) { int rc; bool tsync_notify; + bool listener_req; struct bpf_program *prgm = NULL; rc = gen_bpf_generate(col, &prgm); @@ -367,6 +372,8 @@ int sys_filter_load(struct db_filter_col *col, bool rawrc) } tsync_notify = state.sup_flag_tsync_esrch > 0 && state.notify_fd == -1; + listener_req = state.sup_user_notif > 0 && \ + col->notify_used && state.notify_fd == -1; /* load the filter into the kernel */ if (sys_chk_seccomp_syscall() == 1) { @@ -375,11 +382,16 @@ int sys_filter_load(struct db_filter_col *col, bool rawrc) if (col->attr.tsync_enable) flgs |= SECCOMP_FILTER_FLAG_TSYNC | \ SECCOMP_FILTER_FLAG_TSYNC_ESRCH; - if (state.sup_user_notif > 0) + if (listener_req) flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER; - } else if (col->attr.tsync_enable) + } else if (col->attr.tsync_enable) { + if (listener_req) { + /* NOTE: we _should_ catch this in db.c */ + rc = -EFAULT; + goto filter_load_out; + } flgs |= SECCOMP_FILTER_FLAG_TSYNC; - else if (state.sup_user_notif > 0 && state.notify_fd == -1) + } else if (listener_req) flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER; if (col->attr.log_enable) flgs |= SECCOMP_FILTER_FLAG_LOG; -- 2.26.2