diff options
author | Tyler Hicks <tyhicks@canonical.com> | 2017-10-18 06:16:52 +0000 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2017-11-01 12:48:14 -0400 |
commit | d0e11951f6484db5d8e98591ddc0c0157b333d85 (patch) | |
tree | 0402519270e14ee916dfa31503505bc49037bdd7 | |
parent | 8a8576c9e0cf463d2d624686a4e57058ae30e91a (diff) | |
download | libseccomp-d0e11951f6484db5d8e98591ddc0c0157b333d85.tar.gz |
all: add support for new log filter flag
Extend libseccomp to support SECCOMP_FILTER_FLAG_LOG, which is intended
to cause log events for all actions taken by a filter except for
SCMP_ACT_ALLOW actions. This is done via a new filter attribute called
SCMP_FLTATR_CTL_LOG that is off by default.
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r-- | doc/man/man3/seccomp_api_get.3 | 3 | ||||
-rw-r--r-- | doc/man/man3/seccomp_attr_set.3 | 8 | ||||
-rw-r--r-- | include/seccomp.h.in | 2 | ||||
-rw-r--r-- | src/api.c | 12 | ||||
-rw-r--r-- | src/db.c | 14 | ||||
-rw-r--r-- | src/db.h | 2 | ||||
-rw-r--r-- | src/python/libseccomp.pxd | 1 | ||||
-rw-r--r-- | src/python/seccomp.pyx | 1 | ||||
-rw-r--r-- | src/system.c | 13 | ||||
-rw-r--r-- | src/system.h | 3 | ||||
-rw-r--r-- | tests/13-basic-attrs.c | 15 | ||||
-rwxr-xr-x | tests/13-basic-attrs.py | 5 | ||||
-rw-r--r-- | tests/39-basic-api_level.c | 13 | ||||
-rwxr-xr-x | tests/39-basic-api_level.py | 7 |
14 files changed, 94 insertions, 5 deletions
diff --git a/doc/man/man3/seccomp_api_get.3 b/doc/man/man3/seccomp_api_get.3 index a209dcc..b6c0453 100644 --- a/doc/man/man3/seccomp_api_get.3 +++ b/doc/man/man3/seccomp_api_get.3 @@ -47,6 +47,9 @@ The SCMP_FLTATR_CTL_TSYNC filter attribute is supported and libseccomp uses the .BR seccomp(2) syscall to load the seccomp filter into the kernel. +.TP +.B 3 +The SCMP_FLTATR_CTL_LOG filter attribute is supported. .\" ////////////////////////////////////////////////////////////////////////// .SH RETURN VALUE .\" ////////////////////////////////////////////////////////////////////////// diff --git a/doc/man/man3/seccomp_attr_set.3 b/doc/man/man3/seccomp_attr_set.3 index 091d6d1..7050d5f 100644 --- a/doc/man/man3/seccomp_attr_set.3 +++ b/doc/man/man3/seccomp_attr_set.3 @@ -86,6 +86,14 @@ specific syscall invocations, see for more information. Defaults to off ( .I value == 0). +.TP +.B SCMP_FLTATR_CTL_LOG +A flag to specify if the kernel should log all filter actions taken except for +the +.BR SCMP_ACT_ALLOW +action. Defaults to off ( +.I value +== 0). .\" ////////////////////////////////////////////////////////////////////////// .SH RETURN VALUE .\" ////////////////////////////////////////////////////////////////////////// diff --git a/include/seccomp.h.in b/include/seccomp.h.in index 350a840..014a2d7 100644 --- a/include/seccomp.h.in +++ b/include/seccomp.h.in @@ -64,6 +64,7 @@ enum scmp_filter_attr { SCMP_FLTATR_CTL_NNP = 3, /**< set NO_NEW_PRIVS on filter load */ SCMP_FLTATR_CTL_TSYNC = 4, /**< sync threads on filter load */ SCMP_FLTATR_API_TSKIP = 5, /**< allow rules with a -1 syscall */ + SCMP_FLTATR_CTL_LOG = 6, /**< log not-allowed actions */ _SCMP_FLTATR_MAX, }; @@ -290,6 +291,7 @@ const struct scmp_version *seccomp_version(void); * 1 : base level * 2 : support for the SCMP_FLTATR_CTL_TSYNC filter attribute * uses the seccomp(2) syscall instead of the prctl(2) syscall + * 3 : support for the SCMP_FLTATR_CTL_LOG filter attribute * */ const unsigned int seccomp_api_get(void); @@ -102,6 +102,11 @@ static unsigned int _seccomp_api_update(void) 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) + level = 3; + /* update the stored api level and return */ seccomp_api_level = level; return seccomp_api_level; @@ -127,10 +132,17 @@ API int seccomp_api_set(unsigned int level) case 1: sys_set_seccomp_syscall(false); sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, false); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, false); break; case 2: sys_set_seccomp_syscall(true); sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, false); + break; + case 3: + sys_set_seccomp_syscall(true); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_TSYNC, true); + sys_set_seccomp_flag(SECCOMP_FILTER_FLAG_LOG, true); break; default: return -EINVAL; @@ -792,6 +792,9 @@ int db_col_attr_get(const struct db_filter_col *col, case SCMP_FLTATR_API_TSKIP: *value = col->attr.api_tskip; break; + case SCMP_FLTATR_CTL_LOG: + *value = col->attr.log_enable; + break; default: rc = -EEXIST; break; @@ -842,6 +845,17 @@ int db_col_attr_set(struct db_filter_col *col, case SCMP_FLTATR_API_TSKIP: col->attr.api_tskip = (value ? 1 : 0); break; + case SCMP_FLTATR_CTL_LOG: + rc = sys_chk_seccomp_flag(SECCOMP_FILTER_FLAG_LOG); + if (rc == 1) { + /* supported */ + rc = 0; + col->attr.log_enable = (value ? 1 : 0); + } else if (rc == 0) { + /* unsupported */ + rc = -EOPNOTSUPP; + } + break; default: rc = -EEXIST; break; @@ -139,6 +139,8 @@ struct db_filter_attr { uint32_t tsync_enable; /* allow rules with a -1 syscall value */ uint32_t api_tskip; + /* SECCOMP_FILTER_FLAG_LOG related attributes */ + uint32_t log_enable; }; struct db_filter { diff --git a/src/python/libseccomp.pxd b/src/python/libseccomp.pxd index b851d25..4cc83fd 100644 --- a/src/python/libseccomp.pxd +++ b/src/python/libseccomp.pxd @@ -57,6 +57,7 @@ cdef extern from "seccomp.h": SCMP_FLTATR_CTL_NNP SCMP_FLTATR_CTL_TSYNC SCMP_FLTATR_API_TSKIP + SCMP_FLTATR_CTL_LOG cdef enum scmp_compare: SCMP_CMP_NE diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index 27e374f..dbf0e0a 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -303,6 +303,7 @@ cdef class Attr: CTL_NNP = libseccomp.SCMP_FLTATR_CTL_NNP CTL_TSYNC = libseccomp.SCMP_FLTATR_CTL_TSYNC API_TSKIP = libseccomp.SCMP_FLTATR_API_TSKIP + CTL_LOG = libseccomp.SCMP_FLTATR_CTL_LOG cdef class Arg: """ Python object representing a SyscallFilter syscall argument. diff --git a/src/system.c b/src/system.c index 4ff641b..f84cab6 100644 --- a/src/system.c +++ b/src/system.c @@ -41,6 +41,7 @@ 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; /** * Check to see if the seccomp() syscall is supported @@ -149,6 +150,11 @@ int sys_chk_seccomp_flag(int flag) _support_seccomp_flag_tsync = _sys_chk_seccomp_flag_kernel(flag); return _support_seccomp_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; } return -EOPNOTSUPP; @@ -169,6 +175,9 @@ void sys_set_seccomp_flag(int flag, bool enable) case SECCOMP_FILTER_FLAG_TSYNC: _support_seccomp_flag_tsync = (enable ? 1 : 0); break; + case SECCOMP_FILTER_FLAG_LOG: + _support_seccomp_flag_log = (enable ? 1 : 0); + break; } } @@ -202,7 +211,9 @@ int sys_filter_load(const struct db_filter_col *col) if (sys_chk_seccomp_syscall() == 1) { int flgs = 0; if (col->attr.tsync_enable) - flgs = SECCOMP_FILTER_FLAG_TSYNC; + flgs |= SECCOMP_FILTER_FLAG_TSYNC; + if (col->attr.log_enable) + flgs |= SECCOMP_FILTER_FLAG_LOG; 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 */ diff --git a/src/system.h b/src/system.h index 0e2cd82..edddf14 100644 --- a/src/system.h +++ b/src/system.h @@ -107,6 +107,9 @@ typedef struct sock_filter bpf_instr_raw; #ifndef SECCOMP_FILTER_FLAG_TSYNC #define SECCOMP_FILTER_FLAG_TSYNC 1 #endif +#ifndef SECCOMP_FILTER_FLAG_LOG +#define SECCOMP_FILTER_FLAG_LOG 2 +#endif int sys_chk_seccomp_syscall(void); void sys_set_seccomp_syscall(bool enable); diff --git a/tests/13-basic-attrs.c b/tests/13-basic-attrs.c index bbb6765..0fe4755 100644 --- a/tests/13-basic-attrs.c +++ b/tests/13-basic-attrs.c @@ -32,6 +32,10 @@ int main(int argc, char *argv[]) uint32_t val = (uint32_t)(-1); scmp_filter_ctx ctx = NULL; + rc = seccomp_api_set(3); + if (rc != 0) + return EOPNOTSUPP; + ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) return ENOMEM; @@ -93,6 +97,17 @@ int main(int argc, char *argv[]) goto out; } + rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_LOG, 1); + if (rc != 0) + goto out; + rc = seccomp_attr_get(ctx, SCMP_FLTATR_CTL_LOG, &val); + if (rc != 0) + goto out; + if (val != 1) { + rc = -1; + goto out; + } + rc = 0; out: seccomp_release(ctx); diff --git a/tests/13-basic-attrs.py b/tests/13-basic-attrs.py index 8133942..49759ee 100755 --- a/tests/13-basic-attrs.py +++ b/tests/13-basic-attrs.py @@ -29,6 +29,8 @@ import util from seccomp import * def test(): + set_api(3) + f = SyscallFilter(ALLOW) if f.get_attr(Attr.ACT_DEFAULT) != ALLOW: raise RuntimeError("Failed getting Attr.ACT_DEFAULT") @@ -47,6 +49,9 @@ def test(): f.set_attr(Attr.API_TSKIP, 0) if f.get_attr(Attr.API_TSKIP) != 0: raise RuntimeError("Failed getting Attr.API_TSKIP") + f.set_attr(Attr.CTL_LOG, 1) + if f.get_attr(Attr.CTL_LOG) != 1: + raise RuntimeError("Failed getting Attr.CTL_LOG") test() diff --git a/tests/39-basic-api_level.c b/tests/39-basic-api_level.c index 18c082a..9ce3b41 100644 --- a/tests/39-basic-api_level.c +++ b/tests/39-basic-api_level.c @@ -47,14 +47,21 @@ int main(int argc, char *argv[]) if (api != 2) return -5; + rc = seccomp_api_set(3); + if (rc != 0) + return -6; + api = seccomp_api_get(); + if (api != 3) + return -7; + /* Attempt to set a high, invalid API level */ rc = seccomp_api_set(1024); if (rc != -EINVAL) - return -6; + return -8; /* Ensure that the previously set API level didn't change */ api = seccomp_api_get(); - if (api != 2) - return -7; + if (api != 3) + return -9; return 0; } diff --git a/tests/39-basic-api_level.py b/tests/39-basic-api_level.py index 49d23f2..9c40c33 100755 --- a/tests/39-basic-api_level.py +++ b/tests/39-basic-api_level.py @@ -45,6 +45,11 @@ def test(): if api != 2: raise RuntimeError("Failed getting API level 2") + set_api(3) + api = get_api() + if api != 3: + raise RuntimeError("Failed getting API level 3") + # Attempt to set a high, invalid API level try: set_api(1024) @@ -54,7 +59,7 @@ def test(): raise RuntimeError("Missing failure when setting invalid API level") # Ensure that the previously set API level didn't change api = get_api() - if api != 2: + if api != 3: raise RuntimeError("Failed getting old API level after setting an invalid API level") test() |