Blob Blame History Raw
From 5201e324d2025b1febbade9bb90d6e405b92a14c Mon Sep 17 00:00:00 2001
From: Paul Moore <paul@paul-moore.com>
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 <paul@paul-moore.com>
---
 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