Skip to content

Commit

Permalink
all: treat syscall -1 as a valid syscall
Browse files Browse the repository at this point in the history
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:
* #80

Signed-off-by: Paul Moore <paul@paul-moore.com>
  • Loading branch information
pcmoore committed Feb 21, 2017
1 parent a66f000 commit dc87999
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 18 deletions.
12 changes: 11 additions & 1 deletion doc/man/man3/seccomp_attr_set.3
Expand Up @@ -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
.\" //////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -130,4 +139,5 @@ Paul Moore <paul@paul-moore.com>
.\" //////////////////////////////////////////////////////////////////////////
.BR seccomp_init (3),
.BR seccomp_reset (3),
.BR seccomp_load (3)
.BR seccomp_load (3),
.BR seccomp (2)
11 changes: 10 additions & 1 deletion doc/man/man3/seccomp_rule_add.3
Expand Up @@ -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
Expand Down Expand Up @@ -301,4 +309,5 @@ Paul Moore <paul@paul-moore.com>
.\" //////////////////////////////////////////////////////////////////////////
.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)
1 change: 1 addition & 0 deletions include/seccomp.h.in
Expand Up @@ -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,
};

Expand Down
11 changes: 7 additions & 4 deletions src/api.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 9 additions & 9 deletions src/arch.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}
Expand Down
14 changes: 11 additions & 3 deletions src/db.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/db.h
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions src/python/libseccomp.pxd
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/python/seccomp.pyx
Expand Up @@ -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.
Expand Down

0 comments on commit dc87999

Please sign in to comment.