summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Moore <paul@paul-moore.com>2020-06-06 16:36:38 -0400
committerPaul Moore <paul@paul-moore.com>2020-06-16 11:22:29 -0400
commit34bf78abc9567b66c72dbe67e7f243072162a25f (patch)
tree5687b1d38934d4d592f02ce0efb7eca791fa59af
parent047a591721631e5da13de7038680ba4000f4365b (diff)
downloadlibseccomp-34bf78abc9567b66c72dbe67e7f243072162a25f.tar.gz
api: add the SCMP_FLTATR_API_SYSRAWRC filter attribute
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 <tom.hromatka@oracle.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--doc/man/man3/seccomp_attr_set.38
-rw-r--r--doc/man/man3/seccomp_export_bpf.37
-rw-r--r--doc/man/man3/seccomp_load.37
-rw-r--r--doc/man/man3/seccomp_notify_alloc.37
-rw-r--r--include/seccomp.h.in1
-rw-r--r--src/api.c40
-rw-r--r--src/db.c26
-rw-r--r--src/db.h4
-rw-r--r--src/gen_pfc.c6
-rw-r--r--src/python/libseccomp.pxd1
-rw-r--r--src/python/seccomp.pyx6
-rw-r--r--src/system.c5
-rw-r--r--src/system.h2
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/13-basic-attrs.c22
-rwxr-xr-xtests/13-basic-attrs.py3
-rw-r--r--tests/57-basic-rawsysrc.c64
-rwxr-xr-xtests/57-basic-rawsysrc.py46
-rw-r--r--tests/57-basic-rawsysrc.tests11
-rw-r--r--tests/Makefile.am6
20 files changed, 254 insertions, 19 deletions
diff --git a/doc/man/man3/seccomp_attr_set.3 b/doc/man/man3/seccomp_attr_set.3
index a23d875..6183493 100644
--- a/doc/man/man3/seccomp_attr_set.3
+++ b/doc/man/man3/seccomp_attr_set.3
@@ -1,4 +1,4 @@
-.TH "seccomp_attr_set" 3 "30 May 2020" "paul@paul-moore.com" "libseccomp Documentation"
+.TH "seccomp_attr_set" 3 "06 June 2020" "paul@paul-moore.com" "libseccomp Documentation"
.\" //////////////////////////////////////////////////////////////////////////
.SH NAME
.\" //////////////////////////////////////////////////////////////////////////
@@ -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
.\" //////////////////////////////////////////////////////////////////////////
diff --git a/doc/man/man3/seccomp_export_bpf.3 b/doc/man/man3/seccomp_export_bpf.3
index 68e735f..98b3572 100644
--- a/doc/man/man3/seccomp_export_bpf.3
+++ b/doc/man/man3/seccomp_export_bpf.3
@@ -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.
@@ -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
.\" //////////////////////////////////////////////////////////////////////////
diff --git a/doc/man/man3/seccomp_load.3 b/doc/man/man3/seccomp_load.3
index dcca7f5..8e2e6f0 100644
--- a/doc/man/man3/seccomp_load.3
+++ b/doc/man/man3/seccomp_load.3
@@ -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.
@@ -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
.\" //////////////////////////////////////////////////////////////////////////
diff --git a/doc/man/man3/seccomp_notify_alloc.3 b/doc/man/man3/seccomp_notify_alloc.3
index 48c4599..50c8970 100644
--- a/doc/man/man3/seccomp_notify_alloc.3
+++ b/doc/man/man3/seccomp_notify_alloc.3
@@ -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
@@ -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.
diff --git a/include/seccomp.h.in b/include/seccomp.h.in
index 17c90b7..c78846b 100644
--- a/include/seccomp.h.in
+++ b/include/seccomp.h.in
@@ -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,
};
diff --git a/src/api.c b/src/api.c
index e01b196..b4f0c64 100644
--- a/src/api.c
+++ b/src/api.c
@@ -94,6 +94,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
*
@@ -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 */
@@ -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;
}
diff --git a/src/db.c b/src/db.c
index ebf6ad0..f0e0006 100644
--- a/src/db.c
+++ b/src/db.c
@@ -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;
@@ -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;
@@ -1325,6 +1329,25 @@ int db_col_attr_get(const struct db_filter_col *col,
}
/**
+ * 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
* @param attr the filter attribute
@@ -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;
diff --git a/src/db.h b/src/db.h
index ae485ee..b96b104 100644
--- a/src/db.h
+++ b/src/db.h
@@ -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 {
@@ -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);
diff --git a/src/gen_pfc.c b/src/gen_pfc.c
index 9d86e06..405f080 100644
--- a/src/gen_pfc.c
+++ b/src/gen_pfc.c
@@ -464,7 +464,7 @@ arch_return:
*
* 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)
@@ -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 */
diff --git a/src/python/libseccomp.pxd b/src/python/libseccomp.pxd
index b970318..0629bf1 100644
--- a/src/python/libseccomp.pxd
+++ b/src/python/libseccomp.pxd
@@ -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
diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx
index d7c1bb1..13aa669 100644
--- a/src/python/seccomp.pyx
+++ b/src/python/seccomp.pyx
@@ -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
@@ -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.
diff --git a/src/system.c b/src/system.c
index 737558e..741a74e 100644
--- a/src/system.c
+++ b/src/system.c
@@ -291,6 +291,7 @@ 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
@@ -298,7 +299,7 @@ void sys_set_seccomp_flag(int flag, bool enable)
* 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;
@@ -343,7 +344,7 @@ filter_load_out:
if (rc == -ESRCH)
return -ESRCH;
if (rc < 0)
- return -ECANCELED;
+ return (rawrc ? -errno : -ECANCELED);
return rc;
}
diff --git a/src/system.h b/src/system.h
index d183b5e..7517c71 100644
--- a/src/system.h
+++ b/src/system.h
@@ -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);
diff --git a/tests/.gitignore b/tests/.gitignore
index b51acc3..59eb15c 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -62,3 +62,4 @@ util.pyc
54-live-binary_tree
55-basic-pfc_binary_tree
56-basic-iterate_syscalls
+57-basic-rawsysrc
diff --git a/tests/13-basic-attrs.c b/tests/13-basic-attrs.c
index e7b14f0..e3c5881 100644
--- a/tests/13-basic-attrs.c
+++ b/tests/13-basic-attrs.c
@@ -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);
diff --git a/tests/13-basic-attrs.py b/tests/13-basic-attrs.py
index 0435ded..48c25a0 100755
--- a/tests/13-basic-attrs.py
+++ b/tests/13-basic-attrs.py
@@ -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()
diff --git a/tests/57-basic-rawsysrc.c b/tests/57-basic-rawsysrc.c
new file mode 100644
index 0000000..4248c7a
--- /dev/null
+++ b/tests/57-basic-rawsysrc.c
@@ -0,0 +1,64 @@
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2020 Cisco Systems, Inc. <pmoore2@cisco.com>
+ * Author: Paul Moore <paul@paul-moore.com>
+ */
+
+/*
+ * 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 <http://www.gnu.org/licenses>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ int fd;
+ scmp_filter_ctx ctx = NULL;
+
+ rc = seccomp_api_set(3);
+ if (rc != 0)
+ return EOPNOTSUPP;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL) {
+ rc = ENOMEM;
+ goto out;
+ }
+
+ rc = seccomp_attr_set(ctx, SCMP_FLTATR_API_SYSRAWRC, 1);
+ if (rc != 0)
+ goto out;
+
+ /* we must use a closed/invalid fd for this to work */
+ fd = dup(2);
+ close(fd);
+ rc = seccomp_export_pfc(ctx, fd);
+ if (rc == -EBADF)
+ rc = 0;
+ else
+ rc = -1;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
diff --git a/tests/57-basic-rawsysrc.py b/tests/57-basic-rawsysrc.py
new file mode 100755
index 0000000..a88461a
--- /dev/null
+++ b/tests/57-basic-rawsysrc.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2020 Cisco Systems, Inc. <pmoore2@cisco.com>
+# Author: Paul Moore <paul@paul-moore.com>
+#
+
+#
+# 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 <http://www.gnu.org/licenses>.
+#
+
+import argparse
+import sys
+import os
+
+import util
+
+from seccomp import *
+
+def test():
+ # this test really isn't conclusive, but considering how python does error
+ # handling it may be the best we can do
+ f = SyscallFilter(ALLOW)
+ dummy = open("/dev/null", "w")
+ os.close(dummy.fileno())
+ try:
+ f = f.export_pfc(dummy)
+ except RuntimeError:
+ pass
+
+test()
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
diff --git a/tests/57-basic-rawsysrc.tests b/tests/57-basic-rawsysrc.tests
new file mode 100644
index 0000000..fe71632
--- /dev/null
+++ b/tests/57-basic-rawsysrc.tests
@@ -0,0 +1,11 @@
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2020 Cisco Systems, Inc. <pmoore2@cisco.com>
+# Author: Paul Moore <paul@paul-moore.com>
+#
+
+test type: basic
+
+# Test command
+57-basic-rawsysrc
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 629b910..1765eec 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -95,7 +95,8 @@ check_PROGRAMS = \
53-sim-binary_tree \
54-live-binary_tree \
55-basic-pfc_binary_tree \
- 56-basic-iterate_syscalls
+ 56-basic-iterate_syscalls \
+ 57-basic-rawsysrc
EXTRA_DIST_TESTPYTHON = \
util.py \
@@ -210,7 +211,8 @@ EXTRA_DIST_TESTCFGS = \
53-sim-binary_tree.tests \
54-live-binary_tree.tests \
55-basic-pfc_binary_tree.tests \
- 56-basic-iterate_syscalls.tests
+ 56-basic-iterate_syscalls.tests \
+ 57-basic-rawsysrc.tests
EXTRA_DIST_TESTSCRIPTS = \
38-basic-pfc_coverage.sh 38-basic-pfc_coverage.pfc \