From dc879990774b5fe0b5d3362ae592e8a5bb615fbb Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 15 Feb 2017 19:10:35 -0500 Subject: all: treat syscall -1 as a valid syscall Process tracers use a -1 syscall value to indicate that a syscall should be skipped. This turns out to be quite an undertaking as we need to workaround __NR_SCMP_ERROR (which also has a value of -1). Pay special attention to the new attribute, SCMP_FLTATR_API_TSKIP, and the documentation additions. More information in the GitHub issue: * https://github.com/seccomp/libseccomp/issues/80 Signed-off-by: Paul Moore --- doc/man/man3/seccomp_attr_set.3 | 12 +++++++++++- doc/man/man3/seccomp_rule_add.3 | 11 ++++++++++- include/seccomp.h.in | 1 + src/api.c | 11 +++++++---- src/arch.c | 18 +++++++++--------- src/db.c | 14 +++++++++++--- src/db.h | 2 ++ src/python/libseccomp.pxd | 1 + src/python/seccomp.pyx | 1 + 9 files changed, 53 insertions(+), 18 deletions(-) diff --git a/doc/man/man3/seccomp_attr_set.3 b/doc/man/man3/seccomp_attr_set.3 index f9d8ec1..6a54a71 100644 --- a/doc/man/man3/seccomp_attr_set.3 +++ b/doc/man/man3/seccomp_attr_set.3 @@ -77,6 +77,15 @@ greater; attempting to enable this flag on earlier kernels will result in an error being returned. Defaults to off ( .I value == 0). +.TP +.B SCMP_FLTATR_ATL_TSKIP +A flag to specify if libseccomp should allow filter rules to be created for +the -1 syscall. The -1 syscall value can be used by tracer programs to skip +specific syscall invocations, see +.BR seccomp (2) +for more information. Defaults to off ( +.I value +== 0). .\" ////////////////////////////////////////////////////////////////////////// .SH RETURN VALUE .\" ////////////////////////////////////////////////////////////////////////// @@ -130,4 +139,5 @@ Paul Moore .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_init (3), .BR seccomp_reset (3), -.BR seccomp_load (3) +.BR seccomp_load (3), +.BR seccomp (2) diff --git a/doc/man/man3/seccomp_rule_add.3 b/doc/man/man3/seccomp_rule_add.3 index eda93ae..afb173a 100644 --- a/doc/man/man3/seccomp_rule_add.3 +++ b/doc/man/man3/seccomp_rule_add.3 @@ -90,6 +90,14 @@ is highly recommended to use the .BR SCMP_SYS () macro instead. See the EXAMPLES section below. .P +Starting with Linux v4.8, there may be a need to create a rule with a syscall +value of -1 to allow tracing programs to skip a syscall invocation; in order +to create a rule with a -1 syscall value it is necessary to first set the +.B SCMP_FLTATR_API_TSKIP +attribute. See +.BR seccomp_attr_set (3) +for more information. +.P The filter context .I ctx is the value returned by the call to @@ -301,4 +309,5 @@ Paul Moore .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_syscall_resolve_name_rewrite (3), .BR seccomp_syscall_priority (3), -.BR seccomp_load (3) +.BR seccomp_load (3), +.BR seccomp_attr_set (3) diff --git a/include/seccomp.h.in b/include/seccomp.h.in index b45de86..5843639 100644 --- a/include/seccomp.h.in +++ b/include/seccomp.h.in @@ -63,6 +63,7 @@ enum scmp_filter_attr { SCMP_FLTATR_ACT_BADARCH = 2, /**< bad architecture action */ 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_MAX, }; diff --git a/src/api.c b/src/api.c index 7ccb9f6..5cc04d2 100644 --- a/src/api.c +++ b/src/api.c @@ -65,8 +65,11 @@ static int _ctx_valid(const scmp_filter_ctx *ctx) * syscall appears valid, negative values on failure. * */ -static int _syscall_valid(int syscall) +static int _syscall_valid(const struct db_filter_col *col, int syscall) { + /* syscall -1 is used by tracers to skip the syscall */ + if (col->attr.api_tskip && syscall == -1) + return 0; if (syscall <= -1 && syscall >= -99) return -EINVAL; return 0; @@ -309,7 +312,7 @@ API int seccomp_syscall_priority(scmp_filter_ctx ctx, { struct db_filter_col *col = (struct db_filter_col *)ctx; - if (db_col_valid(col) || _syscall_valid(syscall)) + if (db_col_valid(col) || _syscall_valid(col, syscall)) return -EINVAL; return db_col_syscall_priority(col, syscall, priority); @@ -329,7 +332,7 @@ API int seccomp_rule_add_array(scmp_filter_ctx ctx, if (arg_cnt > 0 && arg_array == NULL) return -EINVAL; - if (db_col_valid(col) || _syscall_valid(syscall)) + if (db_col_valid(col) || _syscall_valid(col, syscall)) return -EINVAL; rc = db_action_valid(action); @@ -378,7 +381,7 @@ API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, if (arg_cnt > 0 && arg_array == NULL) return -EINVAL; - if (db_col_valid(col) || _syscall_valid(syscall)) + if (db_col_valid(col) || _syscall_valid(col, syscall)) return -EINVAL; rc = db_action_valid(action); diff --git a/src/arch.c b/src/arch.c index 0332fa1..21829c7 100644 --- a/src/arch.c +++ b/src/arch.c @@ -330,6 +330,10 @@ int arch_syscall_translate(const struct arch_def *arch, int *syscall) int sc_num; const char *sc_name; + /* special handling for syscall -1 */ + if (*syscall == -1) + return 0; + if (arch->token != arch_def_native->token) { sc_name = arch_syscall_resolve_num(arch_def_native, *syscall); if (sc_name == NULL) @@ -360,10 +364,10 @@ int arch_syscall_rewrite(const struct arch_def *arch, int *syscall) { int sys = *syscall; - if (sys >= 0) { + if (sys >= -1) { /* we shouldn't be here - no rewrite needed */ return 0; - } else if (sys < 0 && sys > -100) { + } else if (sys < -1 && sys > -100) { /* reserved values */ return -EINVAL; } else if (sys <= -100 && sys > -10000) { @@ -404,10 +408,6 @@ int arch_filter_rule_add(struct db_filter_col *col, struct db_filter *db, int rc; struct db_api_rule_list *rule, *rule_tail; - /* ensure we aren't using any reserved syscall values */ - if (syscall < 0 && syscall > -100) - return -EINVAL; - /* translate the syscall */ rc = arch_syscall_translate(db->arch, &syscall); if (rc < 0) @@ -424,9 +424,9 @@ int arch_filter_rule_add(struct db_filter_col *col, struct db_filter *db, rule->next = NULL; /* add the new rule to the existing filter */ - if (db->arch->rule_add == NULL) { - /* negative syscalls require a db->arch->rule_add() function */ - if (syscall < 0 && strict) { + if (syscall == -1 || db->arch->rule_add == NULL) { + /* syscalls < -1 require a db->arch->rule_add() function */ + if (syscall < -1 && strict) { rc = -EDOM; goto rule_add_failure; } diff --git a/src/db.c b/src/db.c index 946d47c..3ea8d64 100644 --- a/src/db.c +++ b/src/db.c @@ -567,6 +567,7 @@ int db_col_reset(struct db_filter_col *col, uint32_t def_action) col->attr.act_badarch = SCMP_ACT_KILL; col->attr.nnp_enable = 1; col->attr.tsync_enable = 0; + col->attr.api_tskip = 0; /* set the state */ col->state = _DB_STA_VALID; @@ -788,6 +789,9 @@ int db_col_attr_get(const struct db_filter_col *col, case SCMP_FLTATR_CTL_TSYNC: *value = col->attr.tsync_enable; break; + case SCMP_FLTATR_API_TSKIP: + *value = col->attr.api_tskip; + break; default: rc = -EEXIST; break; @@ -835,6 +839,9 @@ int db_col_attr_set(struct db_filter_col *col, /* unsupported */ rc = -EOPNOTSUPP; break; + case SCMP_FLTATR_API_TSKIP: + col->attr.api_tskip = (value ? 1 : 0); + break; default: rc = -EEXIST; break; @@ -1523,9 +1530,10 @@ int db_col_syscall_priority(struct db_filter_col *col, if (rc_tmp < 0) goto priority_failure; - /* if this is a pseudo syscall (syscall < 0) then we need to - * rewrite the syscall for some arch specific reason */ - if (sc_tmp < 0) { + /* if this is a pseudo syscall then we need to rewrite the + * syscall for some arch specific reason, don't forget the + * special handling for syscall -1 */ + if (sc_tmp < -1) { /* we set this as a strict op - we don't really care * since priorities are a "best effort" thing - as we * want to catch the -EDOM error and bail on this diff --git a/src/db.h b/src/db.h index 687e777..c4ad549 100644 --- a/src/db.h +++ b/src/db.h @@ -137,6 +137,8 @@ struct db_filter_attr { uint32_t nnp_enable; /* SECCOMP_FILTER_FLAG_TSYNC related attributes */ uint32_t tsync_enable; + /* allow rules with a -1 syscall value */ + uint32_t api_tskip; }; struct db_filter { diff --git a/src/python/libseccomp.pxd b/src/python/libseccomp.pxd index 500da15..d58a417 100644 --- a/src/python/libseccomp.pxd +++ b/src/python/libseccomp.pxd @@ -56,6 +56,7 @@ cdef extern from "seccomp.h": SCMP_FLTATR_ACT_BADARCH SCMP_FLTATR_CTL_NNP SCMP_FLTATR_CTL_TSYNC + SCMP_FLTATR_API_TSKIP cdef enum scmp_compare: SCMP_CMP_NE diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx index 3986f7d..275019a 100644 --- a/src/python/seccomp.pyx +++ b/src/python/seccomp.pyx @@ -273,6 +273,7 @@ cdef class Attr: ACT_BADARCH = libseccomp.SCMP_FLTATR_ACT_BADARCH CTL_NNP = libseccomp.SCMP_FLTATR_CTL_NNP CTL_TSYNC = libseccomp.SCMP_FLTATR_CTL_TSYNC + API_TSKIP = libseccomp.SCMP_FLTATR_API_TSKIP cdef class Arg: """ Python object representing a SyscallFilter syscall argument. -- cgit v1.2.1