[PATCH] system: change our notification fd handling
authorPaul Moore <paul@paul-moore.com>
Tue, 4 Aug 2020 14:52:08 +0000 (10:52 -0400)
committerFelix Geyer <fgeyer@debian.org>
Sun, 8 Nov 2020 18:59:21 +0000 (18:59 +0000)
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.

Acked-by: Tom Hromatka <tom.hromatka@oracle.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
(imported from commit 02812f99e8d1df2e671dac675b4af663d0266303)

Gbp-Pq: Name system_change_our_notification_fd_handling.patch

doc/man/man3/seccomp_init.3
src/system.c

index 87520cd3ba5e243a9af031ea4a684314d6c58272..7881c35761f0e36a4c957a6a941a7982c205295a 100644 (file)
@@ -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
index 3b43b2a967106fc7903178b5402a22f0211ef672..c646c65eae160495b38a9b4b07736163fb4bcc84 100644 (file)
@@ -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;