[PATCH RFC 1/2] filter_seccomp: use seccomp's NO_INHERIT flag when available

Paul Chaignon paul.chaignon at gmail.com
Mon Nov 11 15:19:55 UTC 2019


When adding a new seccomp filter to a process, if the
SECCOMP_FILTER_FLAG_NO_INHERIT is given, the filter won't be inherited by
children tasks.  This patch enables strace to set this flag when seccomp
filter is requested but the -f option is not given.  In such a case,
--seccomp-bpf does not imply -f anymore.  Support for this flag (and the
seccomp syscall) are checked on startup.

* filter_seccomp.c (seccomp_no_inherit): Declare variable.
[!seccomp] (seccomp): Define function.
[!SECCOMP_FILTER_FLAG_NO_INHERIT] (SECCOMP_FILTER_FLAG_NO_INHERIT): Define.
(check_seccomp_inheritance): New function.
(check_seccomp_filter_properties): Call check_seccomp_inheritance.
(init_seccomp_filter): Call seccomp with NO_INHERIT flag.
* filter_seccomp.h (seccomp_no_inherit): Declare variable.
* strace.c (init): Handle --seccomp-bpf without -f.
* tests/filter_seccomp-no-inherit.test: New file.
* Makefile.am (MISC_TESTS): Add it.
* tests/options-syntax.test: Remove test case for --seccomp-bpf implies -f.
* strace.1.in (--seccomp-bpf): Update documentation.

Signed-off-by: Paul Chaignon <paul.chaignon at gmail.com>
---
 filter_seccomp.c                     | 38 +++++++++++++++++++++++++---
 filter_seccomp.h                     |  1 +
 strace.1.in                          |  4 ++-
 strace.c                             |  6 ++---
 tests/Makefile.am                    |  1 +
 tests/filter_seccomp-no-inherit.test | 26 +++++++++++++++++++
 tests/options-syntax.test            |  2 --
 7 files changed, 68 insertions(+), 10 deletions(-)
 create mode 100755 tests/filter_seccomp-no-inherit.test

diff --git a/filter_seccomp.c b/filter_seccomp.c
index 73d3644e..d50bb2dd 100644
--- a/filter_seccomp.c
+++ b/filter_seccomp.c
@@ -22,11 +22,24 @@
 
 bool seccomp_filtering;
 bool seccomp_before_sysentry;
+bool seccomp_no_inherit;
 
 #ifdef HAVE_LINUX_SECCOMP_H
 
 # include <linux/seccomp.h>
 
+#ifndef seccomp
+int seccomp(unsigned int op, unsigned int flags, void *args)
+{
+	errno = 0;
+	return syscall(__NR_seccomp, op, flags, args);
+}
+#endif
+
+#ifndef SECCOMP_FILTER_FLAG_NO_INHERIT
+# define SECCOMP_FILTER_FLAG_NO_INHERIT 16
+#endif
+
 /* PERSONALITY*_AUDIT_ARCH definitions depend on AUDIT_ARCH_* constants.  */
 # ifdef PERSONALITY0_AUDIT_ARCH
 #  include <linux/audit.h>
@@ -281,6 +294,17 @@ check_seccomp_order(void)
 # endif /* HAVE_FORK */
 }
 
+static void
+check_seccomp_inheritance(void)
+{
+	long ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_NO_INHERIT, NULL);
+	seccomp_no_inherit = errno == EFAULT && ret == -1;
+	if (!seccomp_no_inherit) {
+		error_msg("--seccomp-bpf implies -f");
+		followfork = 1;
+	}
+}
+
 static bool
 traced_by_seccomp(unsigned int scno, unsigned int p)
 {
@@ -625,8 +649,11 @@ check_seccomp_filter_properties(void)
 		seccomp_filtering = false;
 	}
 
-	if (seccomp_filtering)
+	if (seccomp_filtering) {
 		check_seccomp_order();
+		if (seccomp_no_inherit)
+			check_seccomp_inheritance();
+	}
 }
 
 static void
@@ -712,8 +739,13 @@ init_seccomp_filter(void)
 	if (debug_flag)
 		dump_seccomp_bpf();
 
-	if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &bpf_prog) < 0)
-		perror_func_msg_and_die("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)");
+	if (seccomp_no_inherit) {
+		if (seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_NO_INHERIT, &bpf_prog) < 0)
+			perror_func_msg_and_die("seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_NO_INHERIT)");
+	} else {
+		if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &bpf_prog) < 0)
+			perror_func_msg_and_die("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)");
+	}
 }
 
 int
diff --git a/filter_seccomp.h b/filter_seccomp.h
index bc06c8c3..f8d241b9 100644
--- a/filter_seccomp.h
+++ b/filter_seccomp.h
@@ -13,6 +13,7 @@
 
 extern bool seccomp_filtering;
 extern bool seccomp_before_sysentry;
+extern bool seccomp_no_inherit;
 
 extern void check_seccomp_filter(void);
 extern void init_seccomp_filter(void);
diff --git a/strace.1.in b/strace.1.in
index eb872df1..89ee1b8c 100644
--- a/strace.1.in
+++ b/strace.1.in
@@ -1020,7 +1020,9 @@ to have
 only when system calls that are being traced occur in the traced processes.
 Implies the
 .B \-f
-option.
+option on kernels that do not support the
+.B SECCOMP_FILTER_FLAG_NO_INHERIT
+flag.
 An attempt to rely on seccomp-bpf to filter system calls may fail for various
 reasons, e.g. there are too many system calls to filter, the seccomp API is not
 available, or
diff --git a/strace.c b/strace.c
index 23bd17b9..4c8598fe 100644
--- a/strace.c
+++ b/strace.c
@@ -1833,10 +1833,8 @@ init(int argc, char *argv[])
 		if (nprocs && (!argc || debug_flag))
 			error_msg("--seccomp-bpf is not enabled for processes"
 				  " attached with -p");
-		if (!followfork) {
-			error_msg("--seccomp-bpf implies -f");
-			followfork = 1;
-		}
+		if (!followfork)
+			seccomp_no_inherit = true;
 	}
 
 	if (optF) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e0c3b60c..1ecc8881 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -329,6 +329,7 @@ MISC_TESTS = \
 	detach-stopped.test \
 	fflush.test \
 	filter_seccomp-perf.test \
+	filter_seccomp-no-inherit.test \
 	filter-unavailable.test \
 	filtering_fd-syntax.test \
 	filtering_syscall-syntax.test \
diff --git a/tests/filter_seccomp-no-inherit.test b/tests/filter_seccomp-no-inherit.test
new file mode 100755
index 00000000..5775135a
--- /dev/null
+++ b/tests/filter_seccomp-no-inherit.test
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Check seccomp filter with SECCOMP_FILTER_FLAG_NO_INHERIT.
+#
+# Copyright (c) 2019 Paul Chaignon <paul.chaignon at gmail.com>
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/init.sh"
+. "${srcdir=.}/filter_seccomp.sh"
+
+$STRACE --seccomp-bpf -e trace=fchdir / > /dev/null 2> "$LOG" ||:
+if grep -x "[^:]*strace: --seccomp-bpf implies -f" "$LOG" > /dev/null; then
+	skip_ 'SECCOMP_FILTER_FLAG_NO_INHERIT is not supported'
+fi
+
+cat "../filter_seccomp.in" | while read -r t prog_args; do {
+	# skip lines beginning with "#" symbol
+	[ "${t###}" = "$t" ] || continue
+
+	try_run_prog "../$t" || continue
+	run_strace $prog_args --seccomp-bpf "../$t" | grep -E "(\.(start|parent|finish)|exited with 0)" | sed -r 's/^[0-9]+\s+//' > "$EXP"
+	sed -i -r 's/ +/ /g' "$LOG"
+	match_diff "$LOG" "$EXP"
+} < /dev/null; done
diff --git a/tests/options-syntax.test b/tests/options-syntax.test
index 54083e82..6537df29 100755
--- a/tests/options-syntax.test
+++ b/tests/options-syntax.test
@@ -49,8 +49,6 @@ check_h "incorrect personality designator '42' in qualification 'getcwd at 42'" -e
 check_h "incorrect personality designator '42' in qualification 'getcwd at 42'" -e trace=gettid,getcwd at 42
 check_h "incorrect personality designator '42' in qualification '23 at 42'" -e trace=23 at 42,123
 
-check_h '--seccomp-bpf implies -f
--w must be given with (-c or -C)' --seccomp-bpf -w /
 check_h '--seccomp-bpf is not enabled for processes attached with -p
 -w must be given with (-c or -C)' --seccomp-bpf -f -p 1 -w
 
-- 
2.17.1



More information about the Strace-devel mailing list