From 2f610f344d2b40b364bdb43862f005bf42750834 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 04 2021 04:35:57 +0000 Subject: import libseccomp-2.5.0-6.el9 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad8ec8e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/libseccomp-2.5.0.tar.gz diff --git a/.libseccomp.metadata b/.libseccomp.metadata new file mode 100644 index 0000000..3544cd5 --- /dev/null +++ b/.libseccomp.metadata @@ -0,0 +1 @@ +81e29853770269ec42f5d52fe0dc795022a6ffd7 SOURCES/libseccomp-2.5.0.tar.gz diff --git a/SOURCES/0101-all-only-request-the-userspace-notification-fd-once.patch b/SOURCES/0101-all-only-request-the-userspace-notification-fd-once.patch new file mode 100644 index 0000000..59f412e --- /dev/null +++ b/SOURCES/0101-all-only-request-the-userspace-notification-fd-once.patch @@ -0,0 +1,631 @@ +From bbf4ae95742662e641e0a456951b912024433435 Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Sun, 26 Jul 2020 11:01:49 -0400 +Subject: [PATCH 101/102] all: only request the userspace notification fd once + +It turns out that requesting the seccomp userspace notifcation fd +more than once is a bad thing which causes the kernel to complain +(rightfully so for a variety of reasons). Unfortunately as we were +always requesting the notification fd whenever possible this results +in problems at filter load time. + +Our solution is to move the notification fd out of the filter context +and into the global task context, using a newly created task_state +structure. This allows us to store, and retrieve the notification +outside the scope of an individual filter context. It also provides +some implementation improvements by giving us a convenient place to +stash all of the API level related support variables. We also extend +the seccomp_reset() API call to reset this internal global state when +passed a NULL filter context. + +There is one potential case which we don't currently handle well: +threads. At the moment libseccomp is thread ignorant, and that works +well as the only global state up to this point was the currently +supported API level information which was common to all threads in a +process. Unfortunately, it appears that the notification fd need not +be common to all threads in a process, yet this patch treats it as if +it is common. I suspect this is a very unusual use case so I decided +to keep this patch simple and ignore this case, but in the future if +we need to support this properly we should be able to do so without +API changes by keeping an internal list of notification fds indexed +by gettid(2). + +This fixes the GitHub issue below: +* https://github.com/seccomp/libseccomp/issues/273 + +Reported-by: Tobias Stoeckmann +Acked-by: Tom Hromatka +Signed-off-by: Paul Moore +--- + doc/man/man3/seccomp_init.3 | 10 +- + doc/man/man3/seccomp_notify_alloc.3 | 3 +- + src/api.c | 19 ++- + src/db.c | 1 - + src/db.h | 3 +- + src/system.c | 204 ++++++++++++++++++---------- + src/system.h | 3 + + tests/11-basic-basic_errors.c | 9 +- + tests/51-live-user_notification.c | 21 +++ + tests/51-live-user_notification.py | 4 + + 10 files changed, 187 insertions(+), 90 deletions(-) + +diff --git a/doc/man/man3/seccomp_init.3 b/doc/man/man3/seccomp_init.3 +index 3ab68fe..87520cd 100644 +--- a/doc/man/man3/seccomp_init.3 ++++ b/doc/man/man3/seccomp_init.3 +@@ -36,7 +36,15 @@ The + function releases the existing filter context state before reinitializing it + and can only be called after a call to + .BR seccomp_init () +-has succeeded. ++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 ++library after a ++.BR fork () ++or ++.BR clone () ++call to ensure the API level and user notification state is properly reset. + .P + When the caller is finished configuring the seccomp filter and has loaded it + into the kernel, the caller should call +diff --git a/doc/man/man3/seccomp_notify_alloc.3 b/doc/man/man3/seccomp_notify_alloc.3 +index 50c8970..cb1c048 100644 +--- a/doc/man/man3/seccomp_notify_alloc.3 ++++ b/doc/man/man3/seccomp_notify_alloc.3 +@@ -59,7 +59,8 @@ returns the notification fd of a filter after it has been loaded. + .\" ////////////////////////////////////////////////////////////////////////// + The + .BR seccomp_notify_fd () +-returns the notification fd of the loaded filter. ++returns the notification fd of the loaded filter, -1 if a notification fd has ++not yet been created, and -EINVAL if the filter context is invalid. + .P + The + .BR seccomp_notify_id_valid () +diff --git a/src/api.c b/src/api.c +index 00975ad..5cec088 100644 +--- a/src/api.c ++++ b/src/api.c +@@ -301,10 +301,18 @@ API int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action) + { + struct db_filter_col *col = (struct db_filter_col *)ctx; + +- /* use a NULL filter collection here since we are resetting it */ +- if (ctx == NULL || db_col_action_valid(NULL, def_action) < 0) ++ /* a NULL filter context indicates we are resetting the global state */ ++ if (ctx == NULL) { ++ /* reset the global state and redetermine the api level */ ++ sys_reset_state(); ++ _seccomp_api_update(); ++ return _rc_filter(0); ++ } ++ /* ensure the default action is valid */ ++ if (db_col_action_valid(NULL, def_action) < 0) + return _rc_filter(-EINVAL); + ++ /* reset the filter */ + return _rc_filter(db_col_reset(col, def_action)); + } + +@@ -675,16 +683,17 @@ API int seccomp_notify_id_valid(int fd, uint64_t id) + /* NOTE - function header comment in include/seccomp.h */ + API int seccomp_notify_fd(const scmp_filter_ctx ctx) + { +- struct db_filter_col *col; ++ /* NOTE: for historical reasons, and possibly future use, we require a ++ * valid filter context even though we don't actual use it here; the ++ * api update is also not strictly necessary, but keep it for now */ + + /* force a runtime api level detection */ + _seccomp_api_update(); + + if (_ctx_valid(ctx)) + return _rc_filter(-EINVAL); +- col = (struct db_filter_col *)ctx; + +- return _rc_filter(col->notify_fd); ++ return _rc_filter(sys_notify_fd()); + } + + /* NOTE - function header comment in include/seccomp.h */ +diff --git a/src/db.c b/src/db.c +index 4a87ea3..836171a 100644 +--- a/src/db.c ++++ b/src/db.c +@@ -1057,7 +1057,6 @@ 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; +diff --git a/src/db.h b/src/db.h +index b96b104..765c607 100644 +--- a/src/db.h ++++ b/src/db.h +@@ -160,8 +160,7 @@ struct db_filter_col { + /* transaction snapshots */ + struct db_filter_snap *snapshots; + +- /* notification fd that was returned from seccomp() */ +- int notify_fd; ++ /* userspace notification */ + bool notify_used; + }; + +diff --git a/src/system.c b/src/system.c +index 6cdfc16..3b43b2a 100644 +--- a/src/system.c ++++ b/src/system.c +@@ -40,16 +40,61 @@ + * our next release we may have to enable the allowlist */ + #define SYSCALL_ALLOWLIST_ENABLE 0 + +-static int _nr_seccomp = -1; +-static int _support_seccomp_syscall = -1; +-static int _support_seccomp_flag_tsync = -1; +-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; +-static int _support_seccomp_flag_tsync_esrch = -1; ++/* task global state */ ++struct task_state { ++ /* seccomp(2) syscall */ ++ int nr_seccomp; ++ ++ /* userspace notification fd */ ++ int notify_fd; ++ ++ /* runtime support flags */ ++ int sup_syscall; ++ int sup_flag_tsync; ++ int sup_flag_log; ++ int sup_action_log; ++ int sup_kill_process; ++ int sup_flag_spec_allow; ++ int sup_flag_new_listener; ++ int sup_user_notif; ++ int sup_flag_tsync_esrch; ++}; ++static struct task_state state = { ++ .nr_seccomp = -1, ++ ++ .notify_fd = -1, ++ ++ .sup_syscall = -1, ++ .sup_flag_tsync = -1, ++ .sup_flag_log = -1, ++ .sup_action_log = -1, ++ .sup_kill_process = -1, ++ .sup_flag_spec_allow = -1, ++ .sup_flag_new_listener = -1, ++ .sup_user_notif = -1, ++ .sup_flag_tsync_esrch = -1, ++}; ++ ++/** ++ * Reset the task state ++ * ++ * This function fully resets the library's global "system task state". ++ * ++ */ ++void sys_reset_state(void) ++{ ++ state.nr_seccomp = -1; ++ state.notify_fd = -1; ++ state.sup_syscall = -1; ++ state.sup_flag_tsync = -1; ++ state.sup_flag_log = -1; ++ state.sup_action_log = -1; ++ state.sup_kill_process = -1; ++ state.sup_flag_spec_allow = -1; ++ state.sup_flag_new_listener = -1; ++ state.sup_user_notif = -1; ++ state.sup_flag_tsync_esrch = -1; ++} + + /** + * Check to see if the seccomp() syscall is supported +@@ -68,8 +113,8 @@ int sys_chk_seccomp_syscall(void) + /* NOTE: it is reasonably safe to assume that we should be able to call + * seccomp() when the caller first starts, but we can't rely on + * it later so we need to cache our findings for use later */ +- if (_support_seccomp_syscall >= 0) +- return _support_seccomp_syscall; ++ if (state.sup_syscall >= 0) ++ return state.sup_syscall; + + #if SYSCALL_ALLOWLIST_ENABLE + /* architecture allowlist */ +@@ -100,11 +145,11 @@ int sys_chk_seccomp_syscall(void) + goto supported; + + unsupported: +- _support_seccomp_syscall = 0; ++ state.sup_syscall = 0; + return 0; + supported: +- _nr_seccomp = nr_seccomp; +- _support_seccomp_syscall = 1; ++ state.nr_seccomp = nr_seccomp; ++ state.sup_syscall = 1; + return 1; + } + +@@ -118,7 +163,7 @@ supported: + */ + void sys_set_seccomp_syscall(bool enable) + { +- _support_seccomp_syscall = (enable ? 1 : 0); ++ state.sup_syscall = (enable ? 1 : 0); + } + + /** +@@ -132,16 +177,16 @@ void sys_set_seccomp_syscall(bool enable) + int sys_chk_seccomp_action(uint32_t action) + { + if (action == SCMP_ACT_KILL_PROCESS) { +- if (_support_seccomp_kill_process < 0) { ++ if (state.sup_kill_process < 0) { + if (sys_chk_seccomp_syscall() == 1 && +- syscall(_nr_seccomp, SECCOMP_GET_ACTION_AVAIL, 0, +- &action) == 0) +- _support_seccomp_kill_process = 1; ++ syscall(state.nr_seccomp, ++ SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) ++ state.sup_kill_process = 1; + else +- _support_seccomp_kill_process = 0; ++ state.sup_kill_process = 0; + } + +- return _support_seccomp_kill_process; ++ return state.sup_kill_process; + } else if (action == SCMP_ACT_KILL_THREAD) { + return 1; + } else if (action == SCMP_ACT_TRAP) { +@@ -152,30 +197,30 @@ int sys_chk_seccomp_action(uint32_t action) + } else if (action == SCMP_ACT_TRACE(action & 0x0000ffff)) { + return 1; + } else if (action == SCMP_ACT_LOG) { +- if (_support_seccomp_action_log < 0) { ++ if (state.sup_action_log < 0) { + if (sys_chk_seccomp_syscall() == 1 && +- syscall(_nr_seccomp, SECCOMP_GET_ACTION_AVAIL, 0, +- &action) == 0) +- _support_seccomp_action_log = 1; ++ syscall(state.nr_seccomp, ++ SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) ++ state.sup_action_log = 1; + else +- _support_seccomp_action_log = 0; ++ state.sup_action_log = 0; + } + +- return _support_seccomp_action_log; ++ return state.sup_action_log; + } else if (action == SCMP_ACT_ALLOW) { + return 1; + } else if (action == SCMP_ACT_NOTIFY) { +- if (_support_seccomp_user_notif < 0) { ++ if (state.sup_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; ++ syscall(state.nr_seccomp, ++ SECCOMP_GET_NOTIF_SIZES, 0, &sizes) == 0) ++ state.sup_user_notif = 1; + else +- _support_seccomp_user_notif = 0; ++ state.sup_user_notif = 0; + } + +- return _support_seccomp_user_notif; ++ return state.sup_user_notif; + } + + return 0; +@@ -193,13 +238,13 @@ void sys_set_seccomp_action(uint32_t action, bool enable) + { + switch (action) { + case SCMP_ACT_LOG: +- _support_seccomp_action_log = (enable ? 1 : 0); ++ state.sup_action_log = (enable ? 1 : 0); + break; + case SCMP_ACT_KILL_PROCESS: +- _support_seccomp_kill_process = (enable ? 1 : 0); ++ state.sup_kill_process = (enable ? 1 : 0); + break; + case SCMP_ACT_NOTIFY: +- _support_seccomp_user_notif = (enable ? 1 : 0); ++ state.sup_user_notif = (enable ? 1 : 0); + break; + } + } +@@ -212,13 +257,14 @@ void sys_set_seccomp_action(uint32_t action, bool enable) + * Return one if the flag is supported, zero otherwise. + * + */ +-static int _sys_chk_seccomp_flag_kernel(int flag) ++static int _sys_chk_flag_kernel(int flag) + { + /* this is an invalid seccomp(2) call because the last argument + * is NULL, but depending on the errno value of EFAULT we can + * guess if the filter flag is supported or not */ + if (sys_chk_seccomp_syscall() == 1 && +- syscall(_nr_seccomp, SECCOMP_SET_MODE_FILTER, flag, NULL) == -1 && ++ syscall(state.nr_seccomp, ++ SECCOMP_SET_MODE_FILTER, flag, NULL) == -1 && + errno == EFAULT) + return 1; + +@@ -238,29 +284,25 @@ int sys_chk_seccomp_flag(int flag) + { + switch (flag) { + case SECCOMP_FILTER_FLAG_TSYNC: +- if (_support_seccomp_flag_tsync < 0) +- _support_seccomp_flag_tsync = _sys_chk_seccomp_flag_kernel(flag); +- +- return _support_seccomp_flag_tsync; ++ if (state.sup_flag_tsync < 0) ++ state.sup_flag_tsync = _sys_chk_flag_kernel(flag); ++ return state.sup_flag_tsync; + case SECCOMP_FILTER_FLAG_LOG: +- if (_support_seccomp_flag_log < 0) +- _support_seccomp_flag_log = _sys_chk_seccomp_flag_kernel(flag); +- +- return _support_seccomp_flag_log; ++ if (state.sup_flag_log < 0) ++ state.sup_flag_log = _sys_chk_flag_kernel(flag); ++ return state.sup_flag_log; + case SECCOMP_FILTER_FLAG_SPEC_ALLOW: +- if (_support_seccomp_flag_spec_allow < 0) +- _support_seccomp_flag_spec_allow = _sys_chk_seccomp_flag_kernel(flag); +- +- return _support_seccomp_flag_spec_allow; ++ if (state.sup_flag_spec_allow < 0) ++ state.sup_flag_spec_allow = _sys_chk_flag_kernel(flag); ++ return state.sup_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; ++ if (state.sup_flag_new_listener < 0) ++ state.sup_flag_new_listener = _sys_chk_flag_kernel(flag); ++ return state.sup_flag_new_listener; + case SECCOMP_FILTER_FLAG_TSYNC_ESRCH: +- if (_support_seccomp_flag_tsync_esrch < 0) +- _support_seccomp_flag_tsync_esrch = _sys_chk_seccomp_flag_kernel(flag); +- return _support_seccomp_flag_tsync_esrch; ++ if (state.sup_flag_tsync_esrch < 0) ++ state.sup_flag_tsync_esrch = _sys_chk_flag_kernel(flag); ++ return state.sup_flag_tsync_esrch; + } + + return -EOPNOTSUPP; +@@ -279,19 +321,19 @@ void sys_set_seccomp_flag(int flag, bool enable) + { + switch (flag) { + case SECCOMP_FILTER_FLAG_TSYNC: +- _support_seccomp_flag_tsync = (enable ? 1 : 0); ++ state.sup_flag_tsync = (enable ? 1 : 0); + break; + case SECCOMP_FILTER_FLAG_LOG: +- _support_seccomp_flag_log = (enable ? 1 : 0); ++ state.sup_flag_log = (enable ? 1 : 0); + break; + case SECCOMP_FILTER_FLAG_SPEC_ALLOW: +- _support_seccomp_flag_spec_allow = (enable ? 1 : 0); ++ state.sup_flag_spec_allow = (enable ? 1 : 0); + break; + case SECCOMP_FILTER_FLAG_NEW_LISTENER: +- _support_seccomp_flag_new_listener = (enable ? 1 : 0); ++ state.sup_flag_new_listener = (enable ? 1 : 0); + break; + case SECCOMP_FILTER_FLAG_TSYNC_ESRCH: +- _support_seccomp_flag_tsync_esrch = (enable ? 1 : 0); ++ state.sup_flag_tsync_esrch = (enable ? 1 : 0); + break; + } + } +@@ -324,7 +366,7 @@ int sys_filter_load(struct db_filter_col *col, bool rawrc) + goto filter_load_out; + } + +- tsync_notify = (_support_seccomp_flag_tsync_esrch > 0); ++ tsync_notify = state.sup_flag_tsync_esrch > 0 && state.notify_fd == -1; + + /* load the filter into the kernel */ + if (sys_chk_seccomp_syscall() == 1) { +@@ -333,28 +375,29 @@ 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 (_support_seccomp_user_notif > 0) ++ if (state.sup_user_notif > 0) + flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER; + } else if (col->attr.tsync_enable) + flgs |= SECCOMP_FILTER_FLAG_TSYNC; +- else if (_support_seccomp_user_notif > 0) ++ else if (state.sup_user_notif > 0 && state.notify_fd == -1) + flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER; + if (col->attr.log_enable) + flgs |= SECCOMP_FILTER_FLAG_LOG; + if (col->attr.spec_allow) + flgs |= SECCOMP_FILTER_FLAG_SPEC_ALLOW; +- rc = syscall(_nr_seccomp, SECCOMP_SET_MODE_FILTER, flgs, prgm); ++ rc = syscall(state.nr_seccomp, ++ SECCOMP_SET_MODE_FILTER, flgs, prgm); + if (tsync_notify && rc > 0) { + /* return 0 on NEW_LISTENER success, but save the fd */ +- col->notify_fd = rc; ++ state.notify_fd = rc; + rc = 0; + } else if (rc > 0 && col->attr.tsync_enable) { + /* always return -ESRCH if we fail to sync threads */ + errno = ESRCH; + rc = -errno; +- } else if (rc > 0 && _support_seccomp_user_notif > 0) { ++ } else if (rc > 0 && state.sup_user_notif > 0) { + /* return 0 on NEW_LISTENER success, but save the fd */ +- col->notify_fd = rc; ++ state.notify_fd = rc; + rc = 0; + } + } else +@@ -370,6 +413,19 @@ filter_load_out: + return rc; + } + ++/** ++ * Return the userspace notification fd ++ * ++ * This function returns the userspace notification fd from ++ * SECCOMP_FILTER_FLAG_NEW_LISTENER. If the notification fd has not yet been ++ * set, or an error has occurred, -1 is returned. ++ * ++ */ ++int sys_notify_fd(void) ++{ ++ return state.notify_fd; ++} ++ + /** + * Allocate a pair of notification request/response structures + * @param req the request location +@@ -386,7 +442,7 @@ int sys_notify_alloc(struct seccomp_notif **req, + int rc; + static struct seccomp_notif_sizes sizes = { 0, 0, 0 }; + +- if (_support_seccomp_syscall <= 0) ++ if (state.sup_syscall <= 0) + return -EOPNOTSUPP; + + if (sizes.seccomp_notif == 0 && sizes.seccomp_notif_resp == 0) { +@@ -427,7 +483,7 @@ int sys_notify_alloc(struct seccomp_notif **req, + */ + int sys_notify_receive(int fd, struct seccomp_notif *req) + { +- if (_support_seccomp_user_notif <= 0) ++ if (state.sup_user_notif <= 0) + return -EOPNOTSUPP; + + if (ioctl(fd, SECCOMP_IOCTL_NOTIF_RECV, req) < 0) +@@ -448,7 +504,7 @@ int sys_notify_receive(int fd, struct seccomp_notif *req) + */ + int sys_notify_respond(int fd, struct seccomp_notif_resp *resp) + { +- if (_support_seccomp_user_notif <= 0) ++ if (state.sup_user_notif <= 0) + return -EOPNOTSUPP; + + if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0) +@@ -467,7 +523,7 @@ int sys_notify_respond(int fd, struct seccomp_notif_resp *resp) + */ + int sys_notify_id_valid(int fd, uint64_t id) + { +- if (_support_seccomp_user_notif <= 0) ++ if (state.sup_user_notif <= 0) + return -EOPNOTSUPP; + + if (ioctl(fd, SECCOMP_IOCTL_NOTIF_ID_VALID, &id) < 0) +diff --git a/src/system.h b/src/system.h +index 133f9b1..096f3ca 100644 +--- a/src/system.h ++++ b/src/system.h +@@ -182,6 +182,8 @@ struct seccomp_notif_resp { + #define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOR(2, __u64) + #endif /* SECCOMP_RET_USER_NOTIF */ + ++void sys_reset_state(void); ++ + int sys_chk_seccomp_syscall(void); + void sys_set_seccomp_syscall(bool enable); + +@@ -193,6 +195,7 @@ void sys_set_seccomp_flag(int flag, bool enable); + + int sys_filter_load(struct db_filter_col *col, bool rawrc); + ++int sys_notify_fd(void); + int sys_notify_alloc(struct seccomp_notif **req, + struct seccomp_notif_resp **resp); + int sys_notify_receive(int fd, struct seccomp_notif *req); +diff --git a/tests/11-basic-basic_errors.c b/tests/11-basic-basic_errors.c +index d3b2256..da059df 100644 +--- a/tests/11-basic-basic_errors.c ++++ b/tests/11-basic-basic_errors.c +@@ -41,12 +41,9 @@ int main(int argc, char *argv[]) + seccomp_release(ctx); + ctx = NULL; + +- /* seccomp_reset error */ +- rc = seccomp_reset(ctx, SCMP_ACT_KILL + 1); +- if (rc != -EINVAL) +- return -1; +- rc = seccomp_reset(ctx, SCMP_ACT_KILL); +- if (rc != -EINVAL) ++ /* ensure that seccomp_reset(NULL, ...) is accepted */ ++ rc = seccomp_reset(NULL, SCMP_ACT_ALLOW); ++ if (rc != 0) + return -1; + + /* seccomp_load error */ +diff --git a/tests/51-live-user_notification.c b/tests/51-live-user_notification.c +index de31d2f..a00627b 100644 +--- a/tests/51-live-user_notification.c ++++ b/tests/51-live-user_notification.c +@@ -98,6 +98,27 @@ int main(int argc, char *argv[]) + goto out; + } + ++ rc = seccomp_reset(ctx, SCMP_ACT_ALLOW); ++ if (rc < 0) ++ goto out; ++ ++ rc = seccomp_rule_add(ctx, SCMP_ACT_NOTIFY, SCMP_SYS(getppid), 0, NULL); ++ if (rc) ++ goto out; ++ ++ rc = seccomp_load(ctx); ++ if (rc < 0) ++ goto out; ++ ++ rc = seccomp_notify_fd(ctx); ++ if (rc < 0) ++ goto out; ++ if (rc != fd) { ++ rc = -EFAULT; ++ goto out; ++ } else ++ rc = 0; ++ + out: + if (fd >= 0) + close(fd); +diff --git a/tests/51-live-user_notification.py b/tests/51-live-user_notification.py +index 0d81f5e..3449c44 100755 +--- a/tests/51-live-user_notification.py ++++ b/tests/51-live-user_notification.py +@@ -52,6 +52,10 @@ def test(): + raise RuntimeError("Child process error") + if os.WEXITSTATUS(rc) != 0: + raise RuntimeError("Child process error") ++ f.reset(ALLOW) ++ f.add_rule(NOTIFY, "getppid") ++ f.load() ++ # no easy way to check the notification fd here + quit(160) + + test() +-- +2.26.2 + diff --git a/SOURCES/0102-system-change-our-notification-fd-handling.patch b/SOURCES/0102-system-change-our-notification-fd-handling.patch new file mode 100644 index 0000000..3ffe19e --- /dev/null +++ b/SOURCES/0102-system-change-our-notification-fd-handling.patch @@ -0,0 +1,93 @@ +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 + diff --git a/SPECS/libseccomp.spec b/SPECS/libseccomp.spec new file mode 100644 index 0000000..69a33e8 --- /dev/null +++ b/SPECS/libseccomp.spec @@ -0,0 +1,249 @@ +Name: libseccomp +Version: 2.5.0 +Release: 6%{?dist} +Summary: Enhanced seccomp library +License: LGPLv2 +URL: https://github.com/seccomp/libseccomp +Source0: %{url}/releases/download/v%{version}/%{name}-%{version}.tar.gz + +# Backports from upstream + +# Patches pending merge +## From: https://github.com/seccomp/libseccomp/pull/280 +## Reference: https://bugzilla.redhat.com/show_bug.cgi?id=1865802 +Patch0101: 0101-all-only-request-the-userspace-notification-fd-once.patch +Patch0102: 0102-system-change-our-notification-fd-handling.patch + +BuildRequires: gcc +BuildRequires: gperf +BuildRequires: make + +%ifnarch riscv64 s390 +# Versions prior to 3.13.0-4 do not work on ARM with newer glibc 2.25.0-6 +# See https://bugzilla.redhat.com/show_bug.cgi?id=1466017 +BuildRequires: valgrind >= 1:3.13.0-4 +%endif + +%description +The libseccomp library provides an easy to use interface to the Linux Kernel's +syscall filtering mechanism, seccomp. The libseccomp API allows an application +to specify which syscalls, and optionally which syscall arguments, the +application is allowed to execute, all of which are enforced by the Linux +Kernel. + +%package devel +Summary: Development files used to build applications with libseccomp support +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The libseccomp library provides an easy to use interface to the Linux Kernel's +syscall filtering mechanism, seccomp. The libseccomp API allows an application +to specify which syscalls, and optionally which syscall arguments, the +application is allowed to execute, all of which are enforced by the Linux +Kernel. + +%package static +Summary: Enhanced seccomp static library +Requires: %{name}-devel%{?_isa} = %{version}-%{release} + +%description static +The libseccomp library provides an easy to use interface to the Linux Kernel's +syscall filtering mechanism, seccomp. The libseccomp API allows an application +to specify which syscalls, and optionally which syscall arguments, the +application is allowed to execute, all of which are enforced by the Linux +Kernel. + +%prep +%autosetup -p1 + +%build +%configure +%make_build + +%install +mkdir -p %{buildroot}/%{_libdir} +mkdir -p %{buildroot}/%{_includedir} +mkdir -p %{buildroot}/%{_mandir} + +%make_install + +rm -f %{buildroot}/%{_libdir}/libseccomp.la + +%check +# Tests 36 and 37 fail on the build systems for the arches below and I'm not +# able to reproduce the failure so just skip the tests for now +%ifarch i686 ppc64le s390x +rm -f tests/36-sim-ipc_syscalls.tests tests/37-sim-ipc_syscalls_be.tests +%endif +%make_build check + + +%files +%license LICENSE +%doc CREDITS README.md CHANGELOG CONTRIBUTING.md +%{_libdir}/libseccomp.so.* + +%files devel +%{_includedir}/seccomp.h +%{_includedir}/seccomp-syscalls.h +%{_libdir}/libseccomp.so +%{_libdir}/pkgconfig/libseccomp.pc +%{_bindir}/scmp_sys_resolver +%{_mandir}/man1/* +%{_mandir}/man3/* + +%files static +%{_libdir}/libseccomp.a + +%changelog +* Mon Aug 09 2021 Mohan Boddu - 2.5.0-6 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Fri Apr 16 2021 Mohan Boddu - 2.5.0-5 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Tue Jan 26 2021 Fedora Release Engineering - 2.5.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Aug 05 2020 Neal Gompa - 2.5.0-3 +- Apply fixes to change internal handling of the notification fd (#1865802) + +* Tue Jul 28 2020 Fedora Release Engineering - 2.5.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Fri Jul 24 2020 Neal Gompa - 2.5.0-1 +- New upstream version (#1858965) + +* Wed Jan 29 2020 Fedora Release Engineering - 2.4.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Mon Dec 16 2019 Neal Gompa - 2.4.2-2 +- Modernize spec +- Backport fix for missing __SNR_ppoll symbol (#1777889) +- Refresh patch to build on aarch64 with upstream version + +* Wed Nov 20 2019 Zbigniew Jędrzejewski-Szmek - 2.4.2-1 +- New upstream version (#1765314) + +* Thu Jul 25 2019 Fedora Release Engineering - 2.4.1-1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Wed Apr 17 2019 Paul Moore - 2.4.1-0 +- New upstream version + +* Thu Mar 14 2019 Paul Moore - 2.4.0-0 +- New upstream version +- Added a hack to workaround test failures (see %check above) + +* Fri Feb 01 2019 Fedora Release Engineering - 2.3.3-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Nov 07 2018 Paul Moore - 2.3.3-4 +- Remove ldconfig scriptlet, thanks to James Antill (RHBZ #1644074) + +* Fri Jul 13 2018 Fedora Release Engineering - 2.3.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Feb 07 2018 Fedora Release Engineering - 2.3.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Wed Jan 10 2018 Paul Moore - 2.3.3-1 +- New upstream version + +* Thu Aug 03 2017 Fedora Release Engineering - 2.3.2-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 2.3.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Jun 29 2017 Stephen Gallagher - 2.3.2-3 +- Re-enable valgrind-based tests on ARMv7 + +* Thu Jun 29 2017 Stephen Gallagher - 2.3.2-2 +- Disable running valgrind-based tests on ARMv7 due to glibc/valgrind bug (RHBZ #1466017) + +* Wed Mar 01 2017 Paul Moore -2.3.2-1 +- New upstream version + +* Fri Feb 10 2017 Fedora Release Engineering - 2.3.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Wed Apr 20 2016 Paul Moore - 2.3.1-1 +- Cleanup the changelog whitespace and escape the macros to make rpmlint happy + +* Wed Apr 20 2016 Paul Moore - 2.3.1-0 +- New upstream version + +* Tue Mar 1 2016 Peter Robinson 2.3.0-1 +- No valgrind on s390 + +* Mon Feb 29 2016 Paul Moore - 2.3.0-0 +- New upstream version + +* Thu Feb 04 2016 Fedora Release Engineering - 2.2.3-1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Jul 08 2015 Paul Moore - 2.2.3-0 +- New upstream version + +* Wed Jun 17 2015 Fedora Release Engineering - 2.2.1-1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed May 13 2015 Paul Moore - 2.2.1-0 +- New upstream version + +* Thu Feb 12 2015 Paul Moore - 2.2.0-0 +- New upstream version +- Added aarch64 support +- Added a static build + +* Thu Sep 18 2014 Paul Moore - 2.1.1-6 +- Fully builds on i686, x86_64, and armv7hl (RHBZ #1106071) + +* Sun Aug 17 2014 Fedora Release Engineering - 2.1.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Fri Jul 18 2014 Tom Callaway - 2.1.1-4 +- fix license handling + +* Sat Jun 07 2014 Fedora Release Engineering - 2.1.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Thu Feb 27 2014 Paul Moore - 2.1.1-2 +- Build with CFLAGS="${optflags}" + +* Mon Feb 17 2014 Paul Moore - 2.1.1-1 +- Removed the kernel dependency (RHBZ #1065572) + +* Thu Oct 31 2013 Paul Moore - 2.1.1-0 +- New upstream version +- Added a %%check procedure for self-test during build + +* Sat Aug 03 2013 Fedora Release Engineering - 2.1.0-1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Tue Jun 11 2013 Paul Moore - 2.1.0-0 +- New upstream version +- Added support for the ARM architecture +- Added the scmp_sys_resolver tool + +* Mon Jan 28 2013 Paul Moore - 2.0.0-0 +- New upstream version + +* Tue Nov 13 2012 Paul Moore - 1.0.1-0 +- New upstream version with several important fixes + +* Tue Jul 31 2012 Paul Moore - 1.0.0-0 +- New upstream version +- Remove verbose build patch as it is no longer needed +- Enable _smp_mflags during build stage + +* Thu Jul 19 2012 Fedora Release Engineering - 0.1.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 10 2012 Paul Moore - 0.1.0-1 +- Limit package to x86/x86_64 platforms (RHBZ #837888) + +* Tue Jun 12 2012 Paul Moore - 0.1.0-0 +- Initial version