diff --git a/doc/man/man3/seccomp_api_get.3 b/doc/man/man3/seccomp_api_get.3 index a209dcc3..0def6863 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 and the SCMP_ACT_LOG action are supported. .\" ////////////////////////////////////////////////////////////////////////// .SH RETURN VALUE .\" ////////////////////////////////////////////////////////////////////////// diff --git a/doc/man/man3/seccomp_attr_set.3 b/doc/man/man3/seccomp_attr_set.3 index 091d6d15..7050d5f9 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/doc/man/man3/seccomp_init.3 b/doc/man/man3/seccomp_init.3 index 65f9a7f2..d7cd383a 100644 --- a/doc/man/man3/seccomp_init.3 +++ b/doc/man/man3/seccomp_init.3 @@ -79,6 +79,11 @@ can be retrieved using the .B PTRACE_GETEVENTMSG option. .TP +.B SCMP_ACT_LOG +The seccomp filter will have no effect on the thread calling the syscall if it +does not match any of the configured seccomp filter rules but the syscall will +be logged. +.TP .B SCMP_ACT_ALLOW The seccomp filter will have no effect on the thread calling the syscall if it does not match any of the configured seccomp filter rules. diff --git a/doc/man/man3/seccomp_rule_add.3 b/doc/man/man3/seccomp_rule_add.3 index afb173a2..86c53b19 100644 --- a/doc/man/man3/seccomp_rule_add.3 +++ b/doc/man/man3/seccomp_rule_add.3 @@ -133,6 +133,10 @@ can be retrieved using the .B PTRACE_GETEVENTMSG option. .TP +.B SCMP_ACT_LOG +The seccomp filter will have no effect on the thread calling the syscall if it +matches the filter rule but the syscall will be logged. +.TP .B SCMP_ACT_ALLOW The seccomp filter will have no effect on the thread calling the syscall if it matches the filter rule. diff --git a/include/seccomp.h.in b/include/seccomp.h.in index 350a840b..56ae73e2 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, }; @@ -256,6 +257,10 @@ struct scmp_arg_cmp { * Notify a tracing process with the specified value */ #define SCMP_ACT_TRACE(x) (0x7ff00000U | ((x) & 0x0000ffffU)) +/** + * Allow the syscall to be executed after the action has been logged + */ +#define SCMP_ACT_LOG 0x7ffc0000U /** * Allow the syscall to be executed */ @@ -290,6 +295,8 @@ 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 + * support for the SCMP_ACT_LOG action * */ const unsigned int seccomp_api_get(void); diff --git a/src/api.c b/src/api.c index 8d01738d..e1a5e8b1 100644 --- a/src/api.c +++ b/src/api.c @@ -102,6 +102,12 @@ 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 && + sys_chk_seccomp_action(SCMP_ACT_LOG) == 1) + level = 3; + /* update the stored api level and return */ seccomp_api_level = level; return seccomp_api_level; @@ -127,10 +133,20 @@ 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); + sys_set_seccomp_action(SCMP_ACT_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); + sys_set_seccomp_action(SCMP_ACT_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); + sys_set_seccomp_action(SCMP_ACT_LOG, true); break; default: return -EINVAL; diff --git a/src/db.c b/src/db.c index 3ea8d64c..dcd5f65c 100644 --- a/src/db.c +++ b/src/db.c @@ -660,18 +660,8 @@ void db_col_release(struct db_filter_col *col) */ int db_action_valid(uint32_t action) { - if (action == SCMP_ACT_KILL) + if (sys_chk_seccomp_action(action) == 1) return 0; - else if (action == SCMP_ACT_TRAP) - return 0; - else if ((action == SCMP_ACT_ERRNO(action & 0x0000ffff)) && - ((action & 0x0000ffff) < MAX_ERRNO)) - return 0; - else if (action == SCMP_ACT_TRACE(action & 0x0000ffff)) - return 0; - else if (action == SCMP_ACT_ALLOW) - return 0; - return -EINVAL; } @@ -792,6 +782,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 +835,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; diff --git a/src/db.h b/src/db.h index c4ad5490..b82491aa 100644 --- a/src/db.h +++ b/src/db.h @@ -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/gen_pfc.c b/src/gen_pfc.c index 0215ee8a..2453d466 100644 --- a/src/gen_pfc.c +++ b/src/gen_pfc.c @@ -130,6 +130,9 @@ static void _pfc_action(FILE *fds, uint32_t action) case SCMP_ACT_TRACE(0): fprintf(fds, "action TRACE(%u);\n", (action & 0x0000ffff)); break; + case SCMP_ACT_LOG: + fprintf(fds, "action LOG;\n"); + break; case SCMP_ACT_ALLOW: fprintf(fds, "action ALLOW;\n"); break; diff --git a/src/python/libseccomp.pxd b/src/python/libseccomp.pxd index b851d250..a599ef2e 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 @@ -70,6 +71,7 @@ cdef extern from "seccomp.h": cdef enum: SCMP_ACT_KILL SCMP_ACT_TRAP + SCMP_ACT_LOG SCMP_ACT_ALLOW unsigned int SCMP_ACT_ERRNO(int errno) unsigned int SCMP_ACT_TRACE(int value) diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index 27e374f5..159cbc18 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -30,6 +30,7 @@ by application developers. Filter action values: KILL - kill the process + LOG - allow the syscall to be executed after the action has been logged ALLOW - allow the syscall to execute TRAP - a SIGSYS signal will be thrown ERRNO(x) - syscall will return (x) @@ -95,6 +96,7 @@ def c_str(string): KILL = libseccomp.SCMP_ACT_KILL TRAP = libseccomp.SCMP_ACT_TRAP +LOG = libseccomp.SCMP_ACT_LOG ALLOW = libseccomp.SCMP_ACT_ALLOW def ERRNO(int errno): """The action ERRNO(x) means that the syscall will return (x). @@ -303,6 +305,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. @@ -542,7 +545,7 @@ cdef class SyscallFilter: """ Add a new rule to filter. Arguments: - action - the rule action: KILL, TRAP, ERRNO(), TRACE(), or ALLOW + action - the rule action: KILL, TRAP, ERRNO(), TRACE(), LOG, or ALLOW syscall - the syscall name or number args - variable number of Arg objects @@ -624,7 +627,7 @@ cdef class SyscallFilter: """ Add a new rule to filter. Arguments: - action - the rule action: KILL, TRAP, ERRNO(), TRACE(), or ALLOW + action - the rule action: KILL, TRAP, ERRNO(), TRACE(), LOG, or ALLOW syscall - the syscall name or number args - variable number of Arg objects diff --git a/src/system.c b/src/system.c index f54d00ec..af461098 100644 --- a/src/system.c +++ b/src/system.c @@ -41,6 +41,8 @@ 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; /** * Check to see if the seccomp() syscall is supported @@ -111,6 +113,78 @@ void sys_set_seccomp_syscall(bool enable) _support_seccomp_syscall = (enable ? 1 : 0); } +/** + * Check to see if a seccomp action is supported + * @param action the seccomp action + * + * This function checks to see if a seccomp action is supported by the system. + * Return one if the action is supported, zero otherwise. + * + */ +int sys_chk_seccomp_action(uint32_t action) +{ + if (action == SCMP_ACT_KILL) { + return 1; + } else if (action == SCMP_ACT_TRAP) { + return 1; + } else if ((action == SCMP_ACT_ERRNO(action & 0x0000ffff)) && + ((action & 0x0000ffff) < MAX_ERRNO)) { + return 1; + } else if (action == SCMP_ACT_TRACE(action & 0x0000ffff)) { + return 1; + } else if (action == SCMP_ACT_LOG) { + if (_support_seccomp_action_log < 0) { + if (sys_chk_seccomp_syscall() == 1 && + syscall(_nr_seccomp, SECCOMP_GET_ACTION_AVAIL, 0, + &action) == 0) + _support_seccomp_action_log = 1; + else + _support_seccomp_action_log = 0; + } + + return _support_seccomp_action_log; + } else if (action == SCMP_ACT_ALLOW) { + return 1; + } + + return 0; +} + +/** + * Force a seccomp action support setting + * @param action the seccomp action + * @param enable the intended support state + * + * This function overrides the current seccomp action support setting; this + * is very much a "use at your own risk" function. + */ +void sys_set_seccomp_action(uint32_t action, bool enable) +{ + if (action == SCMP_ACT_LOG) + _support_seccomp_action_log = (enable ? 1 : 0); +} + +/** + * Check to see if a seccomp() flag is supported by the kernel + * @param flag the seccomp() flag + * + * This function checks to see if a seccomp() flag is supported by the kernel. + * Return one if the flag is supported, zero otherwise. + * + */ +static int _sys_chk_seccomp_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 && + errno == EFAULT) + return 1; + + return 0; +} + /** * Check to see if a seccomp() flag is supported * @param flag the seccomp() flag @@ -122,15 +196,17 @@ void sys_set_seccomp_syscall(bool enable) */ int sys_chk_seccomp_flag(int flag) { - int rc; - switch (flag) { case SECCOMP_FILTER_FLAG_TSYNC: - if (_support_seccomp_flag_tsync < 0) { - rc = sys_chk_seccomp_syscall(); - _support_seccomp_flag_tsync = (rc == 1 ? 1 : 0); - } + if (_support_seccomp_flag_tsync < 0) + _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; @@ -151,6 +227,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; } } @@ -184,7 +263,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 0e2cd82e..b7936877 100644 --- a/src/system.h +++ b/src/system.h @@ -102,15 +102,28 @@ typedef struct sock_filter bpf_instr_raw; #ifndef SECCOMP_SET_MODE_FILTER #define SECCOMP_SET_MODE_FILTER 1 #endif +#ifndef SECCOMP_GET_ACTION_AVAIL +#define SECCOMP_GET_ACTION_AVAIL 2 +#endif /* flags for the seccomp() syscall */ #ifndef SECCOMP_FILTER_FLAG_TSYNC #define SECCOMP_FILTER_FLAG_TSYNC 1 #endif +#ifndef SECCOMP_FILTER_FLAG_LOG +#define SECCOMP_FILTER_FLAG_LOG 2 +#endif + +#ifndef SECCOMP_RET_LOG +#define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */ +#endif int sys_chk_seccomp_syscall(void); void sys_set_seccomp_syscall(bool enable); +int sys_chk_seccomp_action(uint32_t action); +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); diff --git a/tests/.gitignore b/tests/.gitignore index 47953e5a..eef049a7 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -45,3 +45,4 @@ util.pyc 37-sim-ipc_syscalls_be 38-basic-pfc_coverage 39-basic-api_level +40-sim-log diff --git a/tests/06-sim-actions.c b/tests/06-sim-actions.c index 6561cde4..d81e5211 100644 --- a/tests/06-sim-actions.c +++ b/tests/06-sim-actions.c @@ -36,6 +36,10 @@ int main(int argc, char *argv[]) if (rc < 0) goto out; + rc = seccomp_api_set(3); + if (rc != 0) + return EOPNOTSUPP; + ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) return ENOMEM; @@ -44,6 +48,10 @@ int main(int argc, char *argv[]) if (rc != 0) goto out; + rc = seccomp_rule_add(ctx, SCMP_ACT_LOG, SCMP_SYS(rt_sigreturn), 0); + if (rc != 0) + goto out; + rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(write), 0); if (rc != 0) goto out; diff --git a/tests/06-sim-actions.py b/tests/06-sim-actions.py index c59813b4..e3f91e98 100755 --- a/tests/06-sim-actions.py +++ b/tests/06-sim-actions.py @@ -30,8 +30,11 @@ from seccomp import * def test(args): + set_api(3) + f = SyscallFilter(KILL) f.add_rule(ALLOW, "read") + f.add_rule(LOG, "rt_sigreturn") f.add_rule(ERRNO(errno.EPERM), "write") f.add_rule(TRAP, "close") f.add_rule(TRACE(1234), "open") diff --git a/tests/06-sim-actions.tests b/tests/06-sim-actions.tests index d0c2e444..1402e213 100644 --- a/tests/06-sim-actions.tests +++ b/tests/06-sim-actions.tests @@ -7,14 +7,17 @@ test type: bpf-sim -# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result -06-sim-actions all read 4 0x856B008 80 N N N ALLOW -06-sim-actions all write 1 0x856B008 N N N N ERRNO(1) -06-sim-actions all close 4 N N N N N TRAP -06-sim-actions all,-aarch64 open 0x856B008 4 N N N N TRACE(1234) -06-sim-actions x86 0-2 N N N N N N KILL -06-sim-actions x86 7-350 N N N N N N KILL -06-sim-actions x86_64 4-350 N N N N N N KILL +# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result +06-sim-actions all read 4 0x856B008 80 N N N ALLOW +06-sim-actions all write 1 0x856B008 N N N N ERRNO(1) +06-sim-actions all close 4 N N N N N TRAP +06-sim-actions all,-aarch64 open 0x856B008 4 N N N N TRACE(1234) +06-sim-actions all rt_sigreturn N N N N N N LOG +06-sim-actions x86 0-2 N N N N N N KILL +06-sim-actions x86 7-172 N N N N N N KILL +06-sim-actions x86 174-350 N N N N N N KILL +06-sim-actions x86_64 4-14 N N N N N N KILL +06-sim-actions x86_64 16-350 N N N N N N KILL test type: bpf-sim-fuzz diff --git a/tests/13-basic-attrs.c b/tests/13-basic-attrs.c index bbb67657..0fe47550 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 8133942b..49759ee8 100755 --- a/tests/13-basic-attrs.py +++ b/tests/13-basic-attrs.py @@ -29,6 +29,8 @@ 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 18c082a9..9ce3b413 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 49d23f2a..9c40c339 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() diff --git a/tests/40-sim-log.c b/tests/40-sim-log.c new file mode 100644 index 00000000..cdd2a5e5 --- /dev/null +++ b/tests/40-sim-log.c @@ -0,0 +1,59 @@ +/** + * Seccomp Library test program + * + * Originally 01-sim-allow.c but updated to use SCMP_ACT_LOG. + * + * Copyright (c) 2012 Red Hat + * Author: Paul Moore + * + * Copyright (c) 2017 Canonical Ltd. + * Author: Tyler Hicks + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + +#include +#include + +#include + +#include "util.h" + +int main(int argc, char *argv[]) +{ + int rc; + struct util_options opts; + scmp_filter_ctx ctx = NULL; + + rc = util_getopt(argc, argv, &opts); + if (rc < 0) + goto out; + + rc = seccomp_api_set(3); + if (rc != 0) + return EOPNOTSUPP; + + ctx = seccomp_init(SCMP_ACT_LOG); + if (ctx == NULL) + return ENOMEM; + + rc = util_filter_output(&opts, ctx); + if (rc) + goto out; + +out: + seccomp_release(ctx); + return (rc < 0 ? -rc : rc); +} diff --git a/tests/40-sim-log.py b/tests/40-sim-log.py new file mode 100755 index 00000000..63b217e4 --- /dev/null +++ b/tests/40-sim-log.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# +# Seccomp Library test program +# +# Originally 01-sim-allow.py but updated to use LOG. +# +# Copyright (c) 2012 Red Hat +# Author: Paul Moore +# +# Copyright (c) 2017 Canonical Ltd. +# Author: Tyler Hicks +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see . +# + +import argparse +import sys + +import util + +from seccomp import * + +def test(args): + set_api(3) + + f = SyscallFilter(LOG) + return f + +args = util.get_opt() +ctx = test(args) +util.filter_output(args, ctx) + +# kate: syntax python; +# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off; diff --git a/tests/40-sim-log.tests b/tests/40-sim-log.tests new file mode 100644 index 00000000..8fd55108 --- /dev/null +++ b/tests/40-sim-log.tests @@ -0,0 +1,21 @@ +# +# libseccomp regression test automation data +# +# Copyright Canonical Ltd. 2017 +# Author: Tyler Hicks +# + +test type: bpf-sim + +# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result +40-sim-log all 0-350 N N N N N N LOG + +test type: bpf-sim-fuzz + +# Testname StressCount +40-sim-log 50 + +test type: bpf-valgrind + +# Testname +40-sim-log diff --git a/tests/Makefile.am b/tests/Makefile.am index df1a2445..f1d9969a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -78,7 +78,8 @@ check_PROGRAMS = \ 36-sim-ipc_syscalls \ 37-sim-ipc_syscalls_be \ 38-basic-pfc_coverage \ - 39-basic-api_level + 39-basic-api_level \ + 40-sim-log EXTRA_DIST_TESTPYTHON = \ util.py \ @@ -118,7 +119,8 @@ EXTRA_DIST_TESTPYTHON = \ 34-sim-basic_blacklist.py \ 35-sim-negative_one.py \ 36-sim-ipc_syscalls.py \ - 37-sim-ipc_syscalls_be.py + 37-sim-ipc_syscalls_be.py \ + 40-sim-log.py EXTRA_DIST_TESTCFGS = \ 01-sim-allow.tests \ @@ -159,7 +161,8 @@ EXTRA_DIST_TESTCFGS = \ 36-sim-ipc_syscalls.tests \ 37-sim-ipc_syscalls_be.tests \ 38-basic-pfc_coverage.tests \ - 39-basic-api_level.tests + 39-basic-api_level.tests \ + 40-sim-log.tests EXTRA_DIST_TESTSCRIPTS = \ 38-basic-pfc_coverage.sh 38-basic-pfc_coverage.pfc diff --git a/tests/regression b/tests/regression index 1e799f75..2a7a5024 100755 --- a/tests/regression +++ b/tests/regression @@ -729,6 +729,7 @@ function run_test_live() { rc_trap=161 rc_trace=162 rc_errno=163 + rc_log=164 ;; mips|mipsel|mips64|mips64n32|mipsel64|mipsel64n32) rc_kill=140 @@ -736,6 +737,7 @@ function run_test_live() { rc_trap=161 rc_trace=162 rc_errno=163 + rc_log=164 ;; *) print_result $testnumstr "ERROR" "arch $arch not supported" @@ -760,6 +762,9 @@ function run_test_live() { elif [[ $line_act == "ERRNO" && $rc -eq $rc_errno ]]; then print_result $1 "SUCCESS" "" stats_success=$(($stats_success+1)) + elif [[ $line_act == "LOG" && $rc -eq $rc_log ]]; then + print_result $1 "SUCCESS" "" + stats_success=$(($stats_success+1)) else print_result $1 "FAILURE" "$line_test rc=$rc" stats_failure=$(($stats_failure+1)) diff --git a/tests/util.c b/tests/util.c index 9c069d60..f079a53f 100644 --- a/tests/util.c +++ b/tests/util.c @@ -176,6 +176,8 @@ int util_action_parse(const char *action) return -1; /* not yet supported */ else if (strcasecmp(action, "ALLOW") == 0) return SCMP_ACT_ALLOW; + else if (strcasecmp(action, "LOG") == 0) + return SCMP_ACT_LOG; return -1; } diff --git a/tools/bpf.h b/tools/bpf.h index 7679d01b..b8e6d818 100644 --- a/tools/bpf.h +++ b/tools/bpf.h @@ -64,6 +64,7 @@ typedef struct sock_filter bpf_instr_raw; #define SECCOMP_RET_TRAP 0x00030000U #define SECCOMP_RET_ERRNO 0x00050000U #define SECCOMP_RET_TRACE 0x7ff00000U +#define SECCOMP_RET_LOG 0x7ffc0000U #define SECCOMP_RET_ALLOW 0x7fff0000U /* bpf command classes */ diff --git a/tools/scmp_bpf_disasm.c b/tools/scmp_bpf_disasm.c index 05590f45..6e5282a5 100644 --- a/tools/scmp_bpf_disasm.c +++ b/tools/scmp_bpf_disasm.c @@ -189,6 +189,9 @@ static void bpf_decode_action(uint32_t k) case SECCOMP_RET_TRACE: printf("TRACE(%u)", data); break; + case SECCOMP_RET_LOG: + printf("LOG"); + break; case SECCOMP_RET_ALLOW: printf("ALLOW"); break; diff --git a/tools/scmp_bpf_sim.c b/tools/scmp_bpf_sim.c index 3d3204ac..6e422c5b 100644 --- a/tools/scmp_bpf_sim.c +++ b/tools/scmp_bpf_sim.c @@ -128,6 +128,9 @@ static void end_action(uint32_t action, unsigned int line) case SECCOMP_RET_TRACE: fprintf(stdout, "TRACE(%u)\n", data); break; + case SECCOMP_RET_LOG: + fprintf(stdout, "LOG\n"); + break; case SECCOMP_RET_ALLOW: fprintf(stdout, "ALLOW\n"); break;