diff options
author | Paul Moore <paul@paul-moore.com> | 2020-06-13 15:47:49 -0400 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2020-06-29 21:45:01 -0400 |
commit | 6b286c2e8e43de76746346b8eab855311915f5aa (patch) | |
tree | 0564aa8607a2674e2abee86cfe2386a631cfa386 /src | |
parent | 12cf0074be3fa87ef33eecde6848176f03cd1460 (diff) | |
download | libseccomp-6b286c2e8e43de76746346b8eab855311915f5aa.tar.gz |
api: add API level 6
API level 6 allows callers to use both the TSYNC and notify APIs at
the same time. This is due to the TSYNC_ESRCH flag which was added
in Linux v5.7.
This patch also fixes some omissions in seccomp_api_set().
Acked-by: Tom Hromatka <tom.hromatka@oracle.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/api.c | 33 | ||||
-rw-r--r-- | src/db.c | 12 | ||||
-rw-r--r-- | src/system.c | 30 | ||||
-rw-r--r-- | src/system.h | 9 |
4 files changed, 71 insertions, 13 deletions
@@ -165,12 +165,10 @@ static unsigned int _seccomp_api_update(void) /* NOTE: level 1 is the base level, start checking at 2 */ - /* level 2 */ if (sys_chk_seccomp_syscall() && sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC) == 1) level = 2; - /* level 3 */ if (level == 2 && sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_LOG) == 1 && sys_chk_seccomp_action(SCMP_ACT_LOG) == 1 && @@ -186,6 +184,10 @@ static unsigned int _seccomp_api_update(void) sys_chk_seccomp_action(SCMP_ACT_NOTIFY) == 1) level = 5; + if (level == 5 && + sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH) == 1) + level = 6; + /* update the stored api level and return */ seccomp_api_level = level; return seccomp_api_level; @@ -214,6 +216,10 @@ API int seccomp_api_set(unsigned int level) sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, false); sys_set_seccomp_action(SCMP_ACT_LOG, false); sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, false); + sys_set_seccomp_action(SCMP_ACT_NOTIFY, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false); break; case 2: sys_set_seccomp_syscall(true); @@ -221,6 +227,10 @@ API int seccomp_api_set(unsigned int level) sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, false); sys_set_seccomp_action(SCMP_ACT_LOG, false); sys_set_seccomp_action(SCMP_ACT_KILL_PROCESS, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_SPEC_ALLOW, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, false); + sys_set_seccomp_action(SCMP_ACT_NOTIFY, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false); break; case 3: sys_set_seccomp_syscall(true); @@ -228,6 +238,10 @@ API int seccomp_api_set(unsigned int level) 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, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_NEW_LISTENER, false); + sys_set_seccomp_action(SCMP_ACT_NOTIFY, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false); break; case 4: sys_set_seccomp_syscall(true); @@ -236,6 +250,9 @@ API int seccomp_api_set(unsigned int level) 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, false); + sys_set_seccomp_action(SCMP_ACT_NOTIFY, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false); break; case 5: sys_set_seccomp_syscall(true); @@ -246,6 +263,18 @@ API int seccomp_api_set(unsigned int level) 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); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, false); + break; + case 6: + 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); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH, true); break; default: return _rc_filter(-EINVAL); @@ -1196,8 +1196,10 @@ int db_col_action_valid(const struct db_filter_col *col, uint32_t action) /* NOTE: in some cases we don't have a filter collection yet, * but when we do we need to do the following checks */ - /* kernel disallows TSYNC and NOTIFY in one filter */ - if (col->attr.tsync_enable && action == SCMP_ACT_NOTIFY) + /* kernel disallows TSYNC and NOTIFY in one filter unless we + * have the TSYNC_ESRCH flag */ + if (sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH) < 1 && + col->attr.tsync_enable && action == SCMP_ACT_NOTIFY) return -EINVAL; } @@ -1381,8 +1383,10 @@ int db_col_attr_set(struct db_filter_col *col, if (rc == 1) { /* supported */ rc = 0; - /* kernel disallows TSYNC and NOTIFY in one filter */ - if (value && col->notify_used) + /* kernel disallows TSYNC and NOTIFY in one filter + * unless we have TSYNC_ESRCH */ + if (sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC_ESRCH) < 1 && + value && col->notify_used) return -EINVAL; col->attr.tsync_enable = (value ? 1 : 0); } else if (rc == 0) diff --git a/src/system.c b/src/system.c index 6522cb8..6cdfc16 100644 --- a/src/system.c +++ b/src/system.c @@ -49,6 +49,7 @@ 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; /** * Check to see if the seccomp() syscall is supported @@ -256,6 +257,10 @@ int sys_chk_seccomp_flag(int flag) _support_seccomp_flag_new_listener = _sys_chk_seccomp_flag_kernel(flag); return _support_seccomp_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; } return -EOPNOTSUPP; @@ -285,6 +290,9 @@ void sys_set_seccomp_flag(int flag, bool enable) case SECCOMP_FILTER_FLAG_NEW_LISTENER: _support_seccomp_flag_new_listener = (enable ? 1 : 0); break; + case SECCOMP_FILTER_FLAG_TSYNC_ESRCH: + _support_seccomp_flag_tsync_esrch = (enable ? 1 : 0); + break; } } @@ -302,6 +310,7 @@ void sys_set_seccomp_flag(int flag, bool enable) int sys_filter_load(struct db_filter_col *col, bool rawrc) { int rc; + bool tsync_notify; struct bpf_program *prgm = NULL; rc = gen_bpf_generate(col, &prgm); @@ -315,10 +324,18 @@ int sys_filter_load(struct db_filter_col *col, bool rawrc) goto filter_load_out; } + tsync_notify = (_support_seccomp_flag_tsync_esrch > 0); + /* load the filter into the kernel */ if (sys_chk_seccomp_syscall() == 1) { int flgs = 0; - if (col->attr.tsync_enable) + if (tsync_notify) { + if (col->attr.tsync_enable) + flgs |= SECCOMP_FILTER_FLAG_TSYNC | \ + SECCOMP_FILTER_FLAG_TSYNC_ESRCH; + if (_support_seccomp_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) flgs |= SECCOMP_FILTER_FLAG_NEW_LISTENER; @@ -327,10 +344,15 @@ int sys_filter_load(struct db_filter_col *col, bool rawrc) if (col->attr.spec_allow) flgs |= SECCOMP_FILTER_FLAG_SPEC_ALLOW; rc = syscall(_nr_seccomp, SECCOMP_SET_MODE_FILTER, flgs, prgm); - if (rc > 0 && col->attr.tsync_enable) + if (tsync_notify && rc > 0) { + /* return 0 on NEW_LISTENER success, but save the fd */ + col->notify_fd = rc; + rc = 0; + } else if (rc > 0 && col->attr.tsync_enable) { /* always return -ESRCH if we fail to sync threads */ - rc = -ESRCH; - if (rc > 0 && _support_seccomp_user_notif > 0) { + errno = ESRCH; + rc = -errno; + } else if (rc > 0 && _support_seccomp_user_notif > 0) { /* return 0 on NEW_LISTENER success, but save the fd */ col->notify_fd = rc; rc = 0; diff --git a/src/system.h b/src/system.h index 7517c71..133f9b1 100644 --- a/src/system.h +++ b/src/system.h @@ -116,17 +116,20 @@ typedef struct sock_filter bpf_instr_raw; /* flags for the seccomp() syscall */ #ifndef SECCOMP_FILTER_FLAG_TSYNC -#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0) +#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0) #endif #ifndef SECCOMP_FILTER_FLAG_LOG -#define SECCOMP_FILTER_FLAG_LOG (1UL << 1) +#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_FILTER_FLAG_TSYNC_ESRCH +#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4) +#endif #ifndef SECCOMP_RET_LOG #define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */ |