]> git.proxmox.com Git - mirror_libseccomp.git/commitdiff
api: implement user notification in libseccomp
authorPaul Moore <paul@paul-moore.com>
Thu, 2 May 2019 23:29:59 +0000 (19:29 -0400)
committerPaul Moore <paul@paul-moore.com>
Thu, 2 May 2019 23:29:59 +0000 (19:29 -0400)
This patch is heavily based on an earlier patchset by Tycho
Andersen.  I took Tycho's patch and incorporated the requested changes
from the review, fixed some corner case bugs, and simplified the API
a bit.

Kernel 5.0 includes the new user notification return code. Here's all the
infrastructure to handle that.

The idea behind the user notification return code is that the filter stops
the syscall, and forwards it to a "listener fd" that is created when
installing a filter. Then then some userspace task can listen and process
events accordingly by taking some (or no) action in userspace, and then
returning a value from the command.

Signed-off-by: Tycho Andersen <tycho@tycho.ws>
Signed-off-by: Paul Moore <paul@paul-moore.com>
13 files changed:
doc/man/man3/seccomp_api_get.3
doc/man/man3/seccomp_notify_alloc.3 [new file with mode: 0644]
doc/man/man3/seccomp_notify_fd.3 [new file with mode: 0644]
doc/man/man3/seccomp_notify_free.3 [new file with mode: 0644]
doc/man/man3/seccomp_notify_id_valid.3 [new file with mode: 0644]
doc/man/man3/seccomp_notify_receive.3 [new file with mode: 0644]
doc/man/man3/seccomp_notify_respond.3 [new file with mode: 0644]
include/seccomp.h.in
src/api.c
src/db.c
src/db.h
src/system.c
src/system.h

index d358c6d750b65faaaa713406488169408ba05ee7..6fa83a85322b2558c91663b528eefca541ab03d0 100644 (file)
@@ -53,6 +53,9 @@ The SCMP_FLTATR_CTL_LOG filter attribute and the SCMP_ACT_LOG action are support
 .TP
 .B 4
 The SCMP_FLTATR_CTL_SSB filter attribute is supported.
+.TP
+.B 5
+The SCMP_ACT_NOTIFY action is supported.
 .\" //////////////////////////////////////////////////////////////////////////
 .SH RETURN VALUE
 .\" //////////////////////////////////////////////////////////////////////////
diff --git a/doc/man/man3/seccomp_notify_alloc.3 b/doc/man/man3/seccomp_notify_alloc.3
new file mode 100644 (file)
index 0000000..c265ba2
--- /dev/null
@@ -0,0 +1,100 @@
+.TH "seccomp_notify_alloc" 3 "24 April 2019" "tycho@tycho.ws" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_notify_alloc, seccomp_notify_free, seccomp_notify_receive,
+seccomp_notify_respond, seccomp_notify_id_valid, seccomp_notify_fd \- Manage seccomp notifications
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.BI "int seccomp_notify_alloc(struct seccomp_notif **" req ", struct seccomp_notif_resp **" resp ")"
+.BI "void seccomp_notify_free(struct seccomp_notif *" req ", struct seccomp_notif_resp *" resp ")"
+.BI "int seccomp_notify_receive(int " fd ", struct seccomp_notif *" req ")"
+.BI "int seccomp_notify_respond(int " fd ", struct seccomp_notif_resp *" resp ")"
+.BI "int seccomp_notify_id_valid(int " fd ", uint64_t " id ")"
+.BI "int seccomp_notify_fd(const scmp_filter_ctx " ctx ")"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_notify_alloc ()
+function dynamically allocates enough memory for a seccomp notification and
+response. Note that one should always use these functions and not depend on the
+structure sizes in headers, since the size can vary depending on the kernel
+version. This function takes care to ask the kernel how big each structure
+should be, and allocates the right amount of memory. The
+.BR seccomp_notify_free ()
+function frees memory allocated by
+.BR seccomp_notify_alloc ().
+.P
+The
+.BR seccomp_notify_receive ()
+function receives a notification from a seccomp notify fd (obtained from
+.BR seccomp_notify_fd ()).
+.P
+The
+.BR seccomp_notify_respond ()
+function sends a response to a particular notification. The id field should be
+the same as the id from the request, so that the kernel knows which request
+this response corresponds to.
+.P
+The
+.BR seccomp_notify_id_valid ()
+function checks to see if the syscall from a particualr notification request is
+still valid, i.e. if the task is still alive. See NOTES below for details on
+race conditions.
+.P
+The
+.BR seccomp_notify_fd ()
+returns the notification fd of a filter after it has been loaded.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_notify_alloc (),
+.BR seccomp_notify_receive (),
+and
+.BR seccomp_notify_respond ()
+functions all return 0 on success, -1 on failure.
+.P
+The
+.BR seccomp_notify_id_valid ()
+returns 0 if the id is valid, and -ENOENT if it is not.
+.P
+The
+.BR seccomp_notify_fd ()
+returns the notification fd of the loaded filter.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+Care should be taken to avoid two different time of check/time of use errors.
+First, after opening any resources relevant to the pid for a notification (e.g.
+/proc/pid/mem for reading tracee memory to make policy decisions), applications
+should call
+.BR seccomp_notify_id_valid ()
+to make sure that the resources the application has opened correspond to the
+right pid, i.e. that the pid didn't die and a different task take its place.
+.P
+Second, the classic time of check/time of use issue with seccomp memory should
+also be avoided: applications should copy any memory they wish to use to make
+decisions from the tracee into its own address space before applying any policy
+decisions, since a multi-threaded tracee may edit the memory at any time,
+including after it's used to make a policy decision.
+.P
+A complete example of how to avoid these two races is available in the Linux
+Kernel source tree at
+.BR /samples/seccomp/user-trap.c.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Tycho Andersen <tycho@tycho.ws>
+.\" //////////////////////////////////////////////////////////////////////////
diff --git a/doc/man/man3/seccomp_notify_fd.3 b/doc/man/man3/seccomp_notify_fd.3
new file mode 100644 (file)
index 0000000..0c168c8
--- /dev/null
@@ -0,0 +1 @@
+.so man3/seccomp_notify_alloc.3
diff --git a/doc/man/man3/seccomp_notify_free.3 b/doc/man/man3/seccomp_notify_free.3
new file mode 100644 (file)
index 0000000..0c168c8
--- /dev/null
@@ -0,0 +1 @@
+.so man3/seccomp_notify_alloc.3
diff --git a/doc/man/man3/seccomp_notify_id_valid.3 b/doc/man/man3/seccomp_notify_id_valid.3
new file mode 100644 (file)
index 0000000..0c168c8
--- /dev/null
@@ -0,0 +1 @@
+.so man3/seccomp_notify_alloc.3
diff --git a/doc/man/man3/seccomp_notify_receive.3 b/doc/man/man3/seccomp_notify_receive.3
new file mode 100644 (file)
index 0000000..0c168c8
--- /dev/null
@@ -0,0 +1 @@
+.so man3/seccomp_notify_alloc.3
diff --git a/doc/man/man3/seccomp_notify_respond.3 b/doc/man/man3/seccomp_notify_respond.3
new file mode 100644 (file)
index 0000000..0c168c8
--- /dev/null
@@ -0,0 +1 @@
+.so man3/seccomp_notify_alloc.3
index e698e687e629c84981a08c7c9d5263e578ad79e7..d2fde3af83f24c63dd29526d41fe3aff53a469fa 100644 (file)
@@ -26,6 +26,8 @@
 #include <inttypes.h>
 #include <asm/unistd.h>
 #include <linux/audit.h>
+#include <linux/types.h>
+#include <linux/seccomp.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -319,6 +321,10 @@ struct scmp_arg_cmp {
  * Throw a SIGSYS signal
  */
 #define SCMP_ACT_TRAP          0x00030000U
+/**
+ * Notifies userspace
+ */
+#define SCMP_ACT_NOTIFY                0x7fc00000U
 /**
  * Return the specified error code
  */
@@ -336,6 +342,25 @@ struct scmp_arg_cmp {
  */
 #define SCMP_ACT_ALLOW         0x7fff0000U
 
+/* SECCOMP_RET_USER_NOTIF was added in kernel v5.0. */
+#ifndef SECCOMP_RET_USER_NOTIF
+#define SECCOMP_RET_USER_NOTIF 0x7fc00000U
+
+struct seccomp_notif {
+       __u64 id;
+       __u32 pid;
+       __u32 flags;
+       struct seccomp_data data;
+};
+
+struct seccomp_notif_resp {
+       __u64 id;
+       __s64 val;
+       __s32 error;
+       __u32 flags;
+};
+#endif
+
 /*
  * functions
  */
@@ -369,6 +394,7 @@ const struct scmp_version *seccomp_version(void);
  *      support for the SCMP_ACT_LOG action
  *      support for the SCMP_ACT_KILL_PROCESS action
  *  4 : support for the SCMP_FLTATR_CTL_SSB filter attrbute
+ *  5 : support for the SCMP_ACT_NOTIFY action
  *
  */
 unsigned int seccomp_api_get(void);
@@ -673,6 +699,72 @@ int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
                                 unsigned int arg_cnt,
                                 const struct scmp_arg_cmp *arg_array);
 
+/**
+ * Allocate a pair of notification request/response structures.
+ * @param req the request location
+ * @param resp the response location
+ *
+ * This function allocates a pair of request/response structure by computing
+ * the correct sized based on the currently running kernel. It returns zero on
+ * success, and negative values on failure.
+ *
+ */
+int seccomp_notify_alloc(struct seccomp_notif **req,
+                        struct seccomp_notif_resp **resp);
+
+/**
+ * Free a pair of notification request/response structures.
+ * @param req the request location
+ * @param resp the response location
+ */
+void seccomp_notify_free(struct seccomp_notif *req,
+                        struct seccomp_notif_resp *resp);
+/**
+ * Receive a notification from a seccomp notification fd.
+ * @param fd the notification fd
+ * @param req the request buffer to save into
+ *
+ * Blocks waiting for a notification on this fd. This function is thread safe
+ * (synchronization is performed in the kernel). Returns zero on success,
+ * negative values on error.
+ *
+ */
+int seccomp_notify_receive(int fd, struct seccomp_notif *req);
+
+/**
+ * Send a notification response to a seccomp notification fd.
+ * @param fd the notification fd
+ * @param resp the response buffer to use
+ *
+ * Sends a notification response on this fd. This function is thread safe
+ * (synchronization is performed in the kernel). Returns zero on success,
+ * negative values on error.
+ *
+ */
+int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp);
+
+/**
+ * Check if a notification id is still valid.
+ * @param fd the notification fd
+ * @param id the id to test
+ *
+ * Checks to see if a notification id is still valid. Returns 0 on success, and
+ * negative values on failure.
+ *
+ */
+int seccomp_notify_id_valid(int fd, uint64_t id);
+
+/**
+ * Return the notification fd from a filter that has already been loaded.
+ * @param ctx the filter context
+ *
+ * This returns the listener fd that was generated when the seccomp policy was
+ * loaded. This is only valid after seccomp_load() with a filter that makes
+ * use of SCMP_ACT_NOTIFY.
+ *
+ */
+int seccomp_notify_fd(const scmp_filter_ctx ctx);
+
 /**
  * Generate seccomp Pseudo Filter Code (PFC) and export it to a file
  * @param ctx the filter context
index 34fd9c712771fd0c985762316e53c80f0cef66fa..e2b6c00bf66e9babdc87c5933c34e2e913caafbf 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
+#include <sys/ioctl.h>
 
 #include <seccomp.h>
 
@@ -34,6 +35,7 @@
 #include "db.h"
 #include "gen_pfc.h"
 #include "gen_bpf.h"
+#include "helper.h"
 #include "system.h"
 
 #define API    __attribute__((visibility("default")))
@@ -112,6 +114,10 @@ static unsigned int _seccomp_api_update(void)
            sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW) == 1)
                level = 4;
 
+       if (level == 4 &&
+           sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER) == 1)
+               level = 5;
+
        /* update the stored api level and return */
        seccomp_api_level = level;
        return seccomp_api_level;
@@ -163,6 +169,16 @@ API int seccomp_api_set(unsigned int level)
                sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, true);
                sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, true);
                break;
+       case 5:
+               sys_set_seccomp_syscall(true);
+               sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true);
+               sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, true);
+               sys_set_seccomp_action(SCMP_ACT_LOG, true);
+               sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, true);
+               sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, true);
+               sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, true);
+               sys_set_seccomp_action(SCMP_ACT_NOTIFY, true);
+               break;
        default:
                return -EINVAL;
        }
@@ -510,6 +526,53 @@ API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
        return rc;
 }
 
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_notify_alloc(struct seccomp_notif **req,
+                            struct seccomp_notif_resp **resp)
+{
+       return sys_notify_alloc(req, resp);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API void seccomp_notify_free(struct seccomp_notif *req,
+                            struct seccomp_notif_resp *resp)
+{
+       if (req)
+               free(req);
+       if (resp)
+               free(resp);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_notify_receive(int fd, struct seccomp_notif *req)
+{
+       return sys_notify_receive(fd, req);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp)
+{
+       return sys_notify_respond(fd, resp);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_notify_id_valid(int fd, uint64_t id)
+{
+       return sys_notify_id_valid(fd, id);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_notify_fd(const scmp_filter_ctx ctx)
+{
+       struct db_filter_col *col;
+
+       if (_ctx_valid(ctx))
+               return -EINVAL;
+       col = (struct db_filter_col *)ctx;
+
+       return col->notify_fd;
+}
+
 /* NOTE - function header comment in include/seccomp.h */
 API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
 {
index 2f35d20e3947eea6061d3963b3195c7f2e2ffe7b..1b2c549a3785f3dd92da4cc9301d239881df886f 100644 (file)
--- a/src/db.c
+++ b/src/db.c
@@ -1053,6 +1053,7 @@ int db_col_reset(struct db_filter_col *col, uint32_t def_action)
        if (col->filters)
                free(col->filters);
        col->filters = NULL;
+       col->notify_fd = -1;
 
        /* set the endianess to undefined */
        col->endian = 0;
index fa9c08507e586e9568e49e45c466e3a758a5e63d..7967c479612cb274036e839dc4cd2a7e42d68f8c 100644 (file)
--- a/src/db.h
+++ b/src/db.h
@@ -153,6 +153,9 @@ struct db_filter_col {
 
        /* transaction snapshots */
        struct db_filter_snap *snapshots;
+
+       /* notification fd that was returned from seccomp() */
+       int notify_fd;
 };
 
 /**
index f45379c1c5f428d150895aed08328d6c769352f1..8e5aafce0cf6aa23613dd4c4aa8658fcc3163575 100644 (file)
 #define _GNU_SOURCE
 #include <unistd.h>
 
+#include "system.h"
+
 #include <seccomp.h>
 
 #include "arch.h"
 #include "db.h"
 #include "gen_bpf.h"
-#include "system.h"
+#include "helper.h"
 
 /* NOTE: the seccomp syscall whitelist is currently disabled for testing
  *       purposes, but unless we can verify all of the supported ABIs before
@@ -45,6 +47,8 @@ static int _support_seccomp_flag_log = -1;
 static int _support_seccomp_action_log = -1;
 static int _support_seccomp_kill_process = -1;
 static int _support_seccomp_flag_spec_allow = -1;
+static int _support_seccomp_flag_new_listener = -1;
+static int _support_seccomp_user_notif = -1;
 
 /**
  * Check to see if the seccomp() syscall is supported
@@ -158,6 +162,18 @@ int sys_chk_seccomp_action(uint32_t action)
                return _support_seccomp_action_log;
        } else if (action == SCMP_ACT_ALLOW) {
                return 1;
+       } else if (action == SCMP_ACT_NOTIFY) {
+               if (_support_seccomp_user_notif < 0) {
+                       struct seccomp_notif_sizes sizes;
+                       if (sys_chk_seccomp_syscall() == 1 &&
+                           syscall(_nr_seccomp, SECCOMP_GET_NOTIF_SIZES, 0,
+                                   &sizes) == 0)
+                               _support_seccomp_user_notif = 1;
+                       else
+                               _support_seccomp_user_notif = 0;
+               }
+
+               return _support_seccomp_user_notif;
        }
 
        return 0;
@@ -173,10 +189,17 @@ int sys_chk_seccomp_action(uint32_t action)
  */
 void sys_set_seccomp_action(uint32_t action, bool enable)
 {
-       if (action == SCMP_ACT_LOG)
+       switch (action) {
+       case SCMP_ACT_LOG:
                _support_seccomp_action_log = (enable ? 1 : 0);
-       else if (action == SCMP_ACT_KILL_PROCESS)
+               break;
+       case SCMP_ACT_KILL_PROCESS:
                _support_seccomp_kill_process = (enable ? 1 : 0);
+               break;
+       case SCMP_ACT_NOTIFY:
+               _support_seccomp_user_notif = (enable ? 1 : 0);
+               break;
+       }
 }
 
 /**
@@ -227,6 +250,11 @@ int sys_chk_seccomp_flag(int flag)
                        _support_seccomp_flag_spec_allow = _sys_chk_seccomp_flag_kernel(flag);
 
                return _support_seccomp_flag_spec_allow;
+       case SECCOMP_FILTER_FLAG_NEW_LISTENER:
+               if (_support_seccomp_flag_new_listener < 0)
+                       _support_seccomp_flag_new_listener = _sys_chk_seccomp_flag_kernel(flag);
+
+               return _support_seccomp_flag_new_listener;
        }
 
        return -EOPNOTSUPP;
@@ -253,6 +281,9 @@ void sys_set_seccomp_flag(int flag, bool enable)
        case SECCOMP_FILTER_FLAG_SPEC_ALLOW:
                _support_seccomp_flag_spec_allow = (enable ? 1 : 0);
                break;
+       case SECCOMP_FILTER_FLAG_NEW_LISTENER:
+               _support_seccomp_flag_new_listener = (enable ? 1 : 0);
+               break;
        }
 }
 
@@ -266,7 +297,7 @@ void sys_set_seccomp_flag(int flag, bool enable)
  * error.
  *
  */
-int sys_filter_load(const struct db_filter_col *col)
+int sys_filter_load(struct db_filter_col *col)
 {
        int rc;
        struct bpf_program *prgm = NULL;
@@ -291,10 +322,17 @@ int sys_filter_load(const struct db_filter_col *col)
                        flgs |= SECCOMP_FILTER_FLAG_LOG;
                if (col->attr.spec_allow)
                        flgs |= SECCOMP_FILTER_FLAG_SPEC_ALLOW;
+               if (_support_seccomp_user_notif > 0)
+                       flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER;
                rc = syscall(_nr_seccomp, SECCOMP_SET_MODE_FILTER, flgs, prgm);
                if (rc > 0 && col->attr.tsync_enable)
                        /* always return -ESRCH if we fail to sync threads */
                        errno = ESRCH;
+               if (rc > 0 && _support_seccomp_user_notif > 0) {
+                       /* return 0 on NEW_LISTENER success, but save the fd */
+                       col->notify_fd = rc;
+                       rc = 0;
+               }
        } else
                rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prgm);
 
@@ -303,5 +341,71 @@ filter_load_out:
        gen_bpf_release(prgm);
        if (rc < 0)
                return -errno;
+       return rc;
+}
+
+int sys_notify_alloc(struct seccomp_notif **req,
+                    struct seccomp_notif_resp **resp)
+{
+       int rc;
+       static struct seccomp_notif_sizes sizes = { 0, 0, 0 };
+
+       if (_support_seccomp_syscall <= 0)
+               return -EOPNOTSUPP;
+
+       if (sizes.seccomp_notif == 0 && sizes.seccomp_notif_resp == 0) {
+               rc = syscall(__NR_seccomp, SECCOMP_GET_NOTIF_SIZES, 0, &sizes);
+               if (rc < 0)
+                       return -errno;
+       }
+       if (sizes.seccomp_notif == 0 || sizes.seccomp_notif_resp == 0)
+               return -EFAULT;
+
+       if (req) {
+               *req = zmalloc(sizes.seccomp_notif);
+               if (!*req)
+                       return -ENOMEM;
+       }
+
+       if (resp) {
+               *resp = zmalloc(sizes.seccomp_notif_resp);
+               if (!*resp) {
+                       if (req)
+                               free(*req);
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
+int sys_notify_receive(int fd, struct seccomp_notif *req)
+{
+       if (_support_seccomp_user_notif <= 0)
+               return -EOPNOTSUPP;
+
+       if (ioctl(fd, SECCOMP_IOCTL_NOTIF_RECV, req) < 0)
+               return -errno;
+
+       return 0;
+}
+
+int sys_notify_respond(int fd, struct seccomp_notif_resp *resp)
+{
+       if (_support_seccomp_user_notif <= 0)
+               return -EOPNOTSUPP;
+
+       if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0)
+               return -errno;
+       return 0;
+}
+
+int sys_notify_id_valid(int fd, uint64_t id)
+{
+       if (_support_seccomp_user_notif <= 0)
+               return -EOPNOTSUPP;
+
+       if (ioctl(fd, SECCOMP_IOCTL_NOTIF_ID_VALID, &id) < 0)
+               return -errno;
        return 0;
 }
index 884d6ff6b3c40a75d26bde1e2f9717c046c0bc8c..d183b5e2a44c17f74d2de8c72e0a17f8497d3832 100644 (file)
 #ifndef _SYSTEM_H
 #define _SYSTEM_H
 
+#include <inttypes.h>
+#include <stdbool.h>
 #include <linux/filter.h>
+#include <linux/types.h>
 #include <sys/prctl.h>
-
+#include <sys/ioctl.h>
 #include "configure.h"
 
 /* NOTE: this was taken from the Linux Kernel sources */
@@ -40,7 +43,6 @@ struct db_filter_col;
 #else
 
 /* NOTE: the definitions below were taken from the Linux Kernel sources */
-#include <linux/types.h>
 
 /* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
 #define SECCOMP_MODE_DISABLED  0 /* seccomp is not in use. */
@@ -62,11 +64,9 @@ struct db_filter_col;
 #define SECCOMP_RET_ERRNO      0x00050000U /* returns an errno */
 #define SECCOMP_RET_USER_NOTIF 0x7fc00000U /* notifies userspace */
 #define SECCOMP_RET_TRACE      0x7ff00000U /* pass to a tracer or disallow */
-#define SECCOMP_RET_LOG                0x7ffc0000U /* allow after logging */
 #define SECCOMP_RET_ALLOW      0x7fff0000U /* allow */
 
 /* Masks for the return value sections. */
-#define SECCOMP_RET_ACTION_FULL 0xffff0000U
 #define SECCOMP_RET_ACTION     0x7fff0000U
 #define SECCOMP_RET_DATA       0x0000ffffU
 
@@ -86,38 +86,6 @@ struct seccomp_data {
        __u64 args[6];
 };
 
-struct seccomp_notif_sizes {
-       __u16 seccomp_notif;
-       __u16 seccomp_notif_resp;
-       __u16 seccomp_data;
-};
-
-struct seccomp_notif {
-       __u64 id;
-       __u32 pid;
-       __u32 flags;
-       struct seccomp_data data;
-};
-
-struct seccomp_notif_resp {
-       __u64 id;
-       __s64 val;
-       __s32 error;
-       __u32 flags;
-};
-
-#define SECCOMP_IOC_MAGIC               '!'
-#define SECCOMP_IO(nr)                  _IO(SECCOMP_IOC_MAGIC, nr)
-#define SECCOMP_IOR(nr, type)           _IOR(SECCOMP_IOC_MAGIC, nr, type)
-#define SECCOMP_IOW(nr, type)           _IOW(SECCOMP_IOC_MAGIC, nr, type)
-#define SECCOMP_IOWR(nr, type)          _IOWR(SECCOMP_IOC_MAGIC, nr, type)
-
-/* Flags for seccomp notification fd ioctl. */
-#define SECCOMP_IOCTL_NOTIF_RECV        SECCOMP_IOWR(0, struct seccomp_notif)
-#define SECCOMP_IOCTL_NOTIF_SEND        SECCOMP_IOWR(1, \
-                                                    struct seccomp_notif_resp)
-#define SECCOMP_IOCTL_NOTIF_ID_VALID    SECCOMP_IOR(2, __u64)
-
 #endif /* HAVE_LINUX_SECCOMP_H */
 
 /* rename some of the socket filter types to make more sense */
@@ -154,36 +122,29 @@ typedef struct sock_filter bpf_instr_raw;
 #define SECCOMP_FILTER_FLAG_LOG                (1UL << 1)
 #endif
 #ifndef SECCOMP_FILTER_FLAG_SPEC_ALLOW
-#define SECCOMP_FILTER_FLAG_SPEC_ALLOW         (1UL << 2)
+#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
 #endif
 #ifndef SECCOMP_FILTER_FLAG_NEW_LISTENER
 #define SECCOMP_FILTER_FLAG_NEW_LISTENER       (1UL << 3)
 #endif
 
 #ifndef SECCOMP_RET_LOG
-#define SECCOMP_RET_LOG                0x7ffc0000U /* allow after logging */
+#define SECCOMP_RET_LOG                        0x7ffc0000U /* allow after logging */
 #endif
 
-/* SECCOMP_RET_ACTION_FULL was added in kernel v4.14.  It may not be
- * defined on older kernels
- */
+/* SECCOMP_RET_ACTION_FULL was added in kernel v4.14. */
 #ifndef SECCOMP_RET_ACTION_FULL
 #define SECCOMP_RET_ACTION_FULL                0xffff0000U
 #endif
 
-/* SECCOMP_RET_LOG was added in kernel v4.14.  It may not be defined on
- * older kernels.
- */
+/* SECCOMP_RET_LOG was added in kernel v4.14. */
 #ifndef SECCOMP_RET_LOG
 #define SECCOMP_RET_LOG                        0x7fc00000U
 #endif
 
-/* SECCOMP_RET_USER_NOTIF was added in kernel 5.0.  It may not be defined on
- * older kernels. This version also added the structures below, so let's define
- * those if the header doesn't have this definiton.
- */
+/* SECCOMP_RET_USER_NOTIF was added in kernel v5.0. */
 #ifndef SECCOMP_RET_USER_NOTIF
-#define SECCOMP_RET_USER_NOTIF  0x7fc00000U
+#define SECCOMP_RET_USER_NOTIF         0x7fc00000U
 
 struct seccomp_notif_sizes {
        __u16 seccomp_notif;
@@ -211,12 +172,12 @@ struct seccomp_notif_resp {
 #define SECCOMP_IOW(nr, type)           _IOW(SECCOMP_IOC_MAGIC, nr, type)
 #define SECCOMP_IOWR(nr, type)          _IOWR(SECCOMP_IOC_MAGIC, nr, type)
 
-/* Flags for seccomp notification fd ioctl. */
+/* flags for seccomp notification fd ioctl */
 #define SECCOMP_IOCTL_NOTIF_RECV        SECCOMP_IOWR(0, struct seccomp_notif)
 #define SECCOMP_IOCTL_NOTIF_SEND        SECCOMP_IOWR(1, \
                                                     struct seccomp_notif_resp)
 #define SECCOMP_IOCTL_NOTIF_ID_VALID    SECCOMP_IOR(2, __u64)
-#endif
+#endif /* SECCOMP_RET_USER_NOTIF */
 
 int sys_chk_seccomp_syscall(void);
 void sys_set_seccomp_syscall(bool enable);
@@ -227,6 +188,11 @@ void sys_set_seccomp_action(uint32_t action, bool enable);
 int sys_chk_seccomp_flag(int flag);
 void sys_set_seccomp_flag(int flag, bool enable);
 
-int sys_filter_load(const struct db_filter_col *col);
+int sys_filter_load(struct db_filter_col *col);
 
+int sys_notify_alloc(struct seccomp_notif **req,
+                    struct seccomp_notif_resp **resp);
+int sys_notify_receive(int fd, struct seccomp_notif *req);
+int sys_notify_respond(int fd, struct seccomp_notif_resp *resp);
+int sys_notify_id_valid(int fd, uint64_t id);
 #endif