Skip to content

Commit

Permalink
api: add the SCMP_FLTATR_API_SYSRAWRC filter attribute
Browse files Browse the repository at this point in the history
See the manpage additions as part of this patch, but the basic idea
is that when this attribute is non-zero we make every effort to
convey the system's errno value back to the caller when something
goes wrong in libc or the kernel.  It is important to note from a
support perspective that our ability to support callers who make use
of this attribute will be diminished as the libc and kernel errno
values are beyond libseccomp's control.

If the attribute is zero, the library hides all of the system
failures under -ECANCELED.

Acked-by: Tom Hromatka <[email protected]>
Signed-off-by: Paul Moore <[email protected]>
  • Loading branch information
pcmoore committed Jun 16, 2020
1 parent 047a591 commit 34bf78a
Show file tree
Hide file tree
Showing 20 changed files with 254 additions and 19 deletions.
8 changes: 7 additions & 1 deletion doc/man/man3/seccomp_attr_set.3
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH "seccomp_attr_set" 3 "30 May 2020" "[email protected]" "libseccomp Documentation"
.TH "seccomp_attr_set" 3 "06 June 2020" "[email protected]" "libseccomp Documentation"
.\" //////////////////////////////////////////////////////////////////////////
.SH NAME
.\" //////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -100,6 +100,12 @@ A flag to disable Speculative Store Bypass mitigations for this filter.
Defaults to off (
.I value
== 0).
.TP
.B SCMP_FLTATR_API_SYSRAWRC
A flag to specify if libseccomp should pass system error codes back to the
caller instead of the default -ECANCELED. Defaults to off (
.I value
== 0).
.\" //////////////////////////////////////////////////////////////////////////
.SH RETURN VALUE
.\" //////////////////////////////////////////////////////////////////////////
Expand Down
7 changes: 6 additions & 1 deletion doc/man/man3/seccomp_export_bpf.3
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Return zero on success or one of the following error codes on
failure:
.TP
.B -ECANCELED
There was a kernel failure beyond the control of the library.
There was a system failure beyond the control of the library.
.TP
.B -EFAULT
Internal libseccomp failure.
Expand All @@ -59,6 +59,11 @@ Invalid input, either the context or architecture token is invalid.
.TP
.B -ENOMEM
The library was unable to allocate enough memory.
.P
If the \fISCMP_FLTATR_API_SYSRAWRC\fP filter attribute is non-zero then
additional error codes may be returned to the caller; these additional error
codes are the negative \fIerrno\fP values returned by the system. Unfortunately
libseccomp can make no guarantees about these return values.
.\" //////////////////////////////////////////////////////////////////////////
.SH EXAMPLES
.\" //////////////////////////////////////////////////////////////////////////
Expand Down
7 changes: 6 additions & 1 deletion doc/man/man3/seccomp_load.3
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ is "stricter" than
Returns zero on success or one of the following error codes on failure:
.TP
.B -ECANCELED
There was a kernel failure beyond the control of the library.
There was a system failure beyond the control of the library.
.TP
.B -EFAULT
Internal libseccomp failure.
Expand All @@ -52,6 +52,11 @@ The library was unable to allocate enough memory.
.TP
.B -ESRCH
Unable to load the filter due to thread issues.
.P
If the \fISCMP_FLTATR_API_SYSRAWRC\fP filter attribute is non-zero then
additional error codes may be returned to the caller; these additional error
codes are the negative \fIerrno\fP values returned by the system. Unfortunately
libseccomp can make no guarantees about these return values.
.\" //////////////////////////////////////////////////////////////////////////
.SH EXAMPLES
.\" //////////////////////////////////////////////////////////////////////////
Expand Down
7 changes: 4 additions & 3 deletions doc/man/man3/seccomp_notify_alloc.3
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ this response corresponds to.
.P
The
.BR seccomp_notify_id_valid ()
function checks to see if the syscall from a particualr notification request is
function checks to see if the syscall from a particular notification request is
still valid, i.e. if the task is still alive. See NOTES below for details on
race conditions.
.P
Expand All @@ -70,11 +70,12 @@ The
.BR seccomp_notify_receive (),
and
.BR seccomp_notify_respond ()
functions return zero on success or one of the following error codes on
functions return zero on success, or one of the following error codes on
failure:
.TP
.B -ECANCELED
There was a kernel failure beyond the control of the library.
There was a system failure beyond the control of the library, check the
\fIerrno\fP value for more information.
.TP
.B -EFAULT
Internal libseccomp failure.
Expand Down
1 change: 1 addition & 0 deletions include/seccomp.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ enum scmp_filter_attr {
* 2 - binary tree sorted by syscall
* number
*/
SCMP_FLTATR_API_SYSRAWRC = 9, /**< return the system return codes */
_SCMP_FLTATR_MAX,
};

Expand Down
40 changes: 35 additions & 5 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,27 @@ static int _rc_filter(int err)
}
}

/**
* Filter the system error codes we send back to callers
* @param col the filter collection
* @param err the error code
*
* This is similar to _rc_filter(), but it first checks the filter attribute
* to determine if we should be filtering the return codes.
*
*/
static int _rc_filter_sys(struct db_filter_col *col, int err)
{
/* pass through success values */
if (err >= 0)
return err;

/* pass the return code if the SCMP_FLTATR_API_SYSRAWRC is true */
if (db_col_attr_read(col, SCMP_FLTATR_API_SYSRAWRC))
return err;
return -ECANCELED;
}

/**
* Validate a filter context
* @param ctx the filter context
Expand Down Expand Up @@ -355,12 +376,14 @@ API int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
API int seccomp_load(const scmp_filter_ctx ctx)
{
struct db_filter_col *col;
bool rawrc;

if (_ctx_valid(ctx))
return _rc_filter(-EINVAL);
col = (struct db_filter_col *)ctx;

return _rc_filter(sys_filter_load(col));
rawrc = db_col_attr_read(col, SCMP_FLTATR_API_SYSRAWRC);
return _rc_filter(sys_filter_load(col, rawrc));
}

/* NOTE - function header comment in include/seccomp.h */
Expand Down Expand Up @@ -638,28 +661,35 @@ API int seccomp_notify_fd(const scmp_filter_ctx ctx)
/* NOTE - function header comment in include/seccomp.h */
API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
{
int rc;
struct db_filter_col *col;

if (_ctx_valid(ctx))
return _rc_filter(-EINVAL);
col = (struct db_filter_col *)ctx;

return _rc_filter(gen_pfc_generate((struct db_filter_col *)ctx, fd));
rc = gen_pfc_generate(col, fd);
return _rc_filter_sys(col, rc);
}

/* NOTE - function header comment in include/seccomp.h */
API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
{
int rc;
struct db_filter_col *col;
struct bpf_program *program;

if (_ctx_valid(ctx))
return _rc_filter(-EINVAL);
col = (struct db_filter_col *)ctx;

rc = gen_bpf_generate((struct db_filter_col *)ctx, &program);
rc = gen_bpf_generate(col, &program);
if (rc < 0)
return _rc_filter(rc);
rc = write(fd, program->blks, BPF_PGM_SIZE(program));
gen_bpf_release(program);
if (rc < 0)
return _rc_filter(-ECANCELED);
return _rc_filter_sys(col, -errno);

return _rc_filter(0);
return 0;
}
26 changes: 26 additions & 0 deletions src/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,7 @@ int db_col_reset(struct db_filter_col *col, uint32_t def_action)
col->attr.log_enable = 0;
col->attr.spec_allow = 0;
col->attr.optimize = 1;
col->attr.api_sysrawrc = 0;

/* set the state */
col->state = _DB_STA_VALID;
Expand Down Expand Up @@ -1316,6 +1317,9 @@ int db_col_attr_get(const struct db_filter_col *col,
case SCMP_FLTATR_CTL_OPTIMIZE:
*value = col->attr.optimize;
break;
case SCMP_FLTATR_API_SYSRAWRC:
*value = col->attr.api_sysrawrc;
break;
default:
rc = -EINVAL;
break;
Expand All @@ -1324,6 +1328,25 @@ int db_col_attr_get(const struct db_filter_col *col,
return rc;
}

/**
* Get a filter attribute
* @param col the seccomp filter collection
* @param attr the filter attribute
*
* Returns the requested filter attribute value with zero on any error.
* Special care must be given with this function as error conditions can be
* hidden from the caller.
*
*/
uint32_t db_col_attr_read(const struct db_filter_col *col,
enum scmp_filter_attr attr)
{
uint32_t value = 0;

db_col_attr_get(col, attr, &value);
return value;
}

/**
* Set a filter attribute
* @param col the seccomp filter collection
Expand Down Expand Up @@ -1402,6 +1425,9 @@ int db_col_attr_set(struct db_filter_col *col,
break;
}
break;
case SCMP_FLTATR_API_SYSRAWRC:
col->attr.api_sysrawrc = (value ? 1 : 0);
break;
default:
rc = -EINVAL;
break;
Expand Down
4 changes: 4 additions & 0 deletions src/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ struct db_filter_attr {
uint32_t spec_allow;
/* SCMP_FLTATR_CTL_OPTIMIZE related attributes */
uint32_t optimize;
/* return the raw system return codes */
uint32_t api_sysrawrc;
};

struct db_filter {
Expand Down Expand Up @@ -191,6 +193,8 @@ int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token);

int db_col_attr_get(const struct db_filter_col *col,
enum scmp_filter_attr attr, uint32_t *value);
uint32_t db_col_attr_read(const struct db_filter_col *col,
enum scmp_filter_attr attr);
int db_col_attr_set(struct db_filter_col *col,
enum scmp_filter_attr attr, uint32_t value);

Expand Down
6 changes: 3 additions & 3 deletions src/gen_pfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ static int _gen_pfc_arch(const struct db_filter_col *col,
*
* This function generates a pseudo filter code representation of the given
* filter collection and writes it to the given fd. Returns zero on success,
* negative values on failure.
* negative errno values on failure.
*
*/
int gen_pfc_generate(const struct db_filter_col *col, int fd)
Expand All @@ -475,11 +475,11 @@ int gen_pfc_generate(const struct db_filter_col *col, int fd)

newfd = dup(fd);
if (newfd < 0)
return -ECANCELED;
return -errno;
fds = fdopen(newfd, "a");
if (fds == NULL) {
close(newfd);
return -ECANCELED;
return -errno;
}

/* generate the pfc */
Expand Down
1 change: 1 addition & 0 deletions src/python/libseccomp.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ cdef extern from "seccomp.h":
SCMP_FLTATR_CTL_LOG
SCMP_FLTATR_CTL_SSB
SCMP_FLTATR_CTL_OPTIMIZE
SCMP_FLTATR_API_SYSRAWRC

cdef enum scmp_compare:
SCMP_CMP_NE
Expand Down
6 changes: 6 additions & 0 deletions src/python/seccomp.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@ cdef class Attr:
CTL_TSKIP - allow rules with a -1 syscall number
CTL_LOG - log not-allowed actions
CTL_SSB - disable SSB mitigations
CTL_OPTIMIZE - the filter's optimization level:
0: currently unused
1: rules weighted by priority and complexity (DEFAULT)
2: binary tree sorted by syscall number
API_SYSRAWRC - return the raw syscall codes
"""
ACT_DEFAULT = libseccomp.SCMP_FLTATR_ACT_DEFAULT
ACT_BADARCH = libseccomp.SCMP_FLTATR_ACT_BADARCH
Expand All @@ -327,6 +332,7 @@ cdef class Attr:
CTL_LOG = libseccomp.SCMP_FLTATR_CTL_LOG
CTL_SSB = libseccomp.SCMP_FLTATR_CTL_SSB
CTL_OPTIMIZE = libseccomp.SCMP_FLTATR_CTL_OPTIMIZE
API_SYSRAWRC = libseccomp.SCMP_FLTATR_API_SYSRAWRC

cdef class Arg:
""" Python object representing a SyscallFilter syscall argument.
Expand Down
5 changes: 3 additions & 2 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,15 @@ void sys_set_seccomp_flag(int flag, bool enable)
/**
* Loads the filter into the kernel
* @param col the filter collection
* @param rawrc pass the raw return code if true
*
* This function loads the given seccomp filter context into the kernel. If
* the filter was loaded correctly, the kernel will be enforcing the filter
* when this function returns. Returns zero on success, negative values on
* error.
*
*/
int sys_filter_load(struct db_filter_col *col)
int sys_filter_load(struct db_filter_col *col, bool rawrc)
{
int rc;
struct bpf_program *prgm = NULL;
Expand Down Expand Up @@ -343,7 +344,7 @@ int sys_filter_load(struct db_filter_col *col)
if (rc == -ESRCH)
return -ESRCH;
if (rc < 0)
return -ECANCELED;
return (rawrc ? -errno : -ECANCELED);
return rc;
}

Expand Down
2 changes: 1 addition & 1 deletion src/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ 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);

int sys_filter_load(struct db_filter_col *col);
int sys_filter_load(struct db_filter_col *col, bool rawrc);

int sys_notify_alloc(struct seccomp_notif **req,
struct seccomp_notif_resp **resp);
Expand Down
1 change: 1 addition & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ util.pyc
54-live-binary_tree
55-basic-pfc_binary_tree
56-basic-iterate_syscalls
57-basic-rawsysrc
22 changes: 22 additions & 0 deletions tests/13-basic-attrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,28 @@ int main(int argc, char *argv[])
goto out;
}

rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_OPTIMIZE, 2);
if (rc != 0)
goto out;
rc = seccomp_attr_get(ctx, SCMP_FLTATR_CTL_OPTIMIZE, &val);
if (rc != 0)
goto out;
if (val != 2) {
rc = -1;
goto out;
}

rc = seccomp_attr_set(ctx, SCMP_FLTATR_API_SYSRAWRC, 1);
if (rc != 0)
goto out;
rc = seccomp_attr_get(ctx, SCMP_FLTATR_API_SYSRAWRC, &val);
if (rc != 0)
goto out;
if (val != 1) {
rc = -1;
goto out;
}

rc = 0;
out:
seccomp_release(ctx);
Expand Down
3 changes: 3 additions & 0 deletions tests/13-basic-attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ def test():
f.set_attr(Attr.CTL_OPTIMIZE, 2)
if f.get_attr(Attr.CTL_OPTIMIZE) != 2:
raise RuntimeError("Failed getting Attr.CTL_OPTIMIZE")
f.set_attr(Attr.API_SYSRAWRC, 1)
if f.get_attr(Attr.API_SYSRAWRC) != 1:
raise RuntimeError("Failed getting Attr.API_SYSRAWRC")

test()

Expand Down
Loading

0 comments on commit 34bf78a

Please sign in to comment.