Skip to contentSkip to conversation

seccomp: remove the 'sd' argument from __secure_computing()

PATCH Superseded Oleg Nesterov 3 participants 12 messages Jan 20, 2025 – Jan 27, 2025

Subsystems (5)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Oleg Nesterov

author maintainer
#0 lore raw

cover seccomp: remove the 'sd' argument from __secure_computing()

Hello,

I know nothing about arch/mips and I don't have a mips machine, 1/4 wasn't even compile tested.

Oleg.
---

 arch/mips/kernel/ptrace.c           | 20 ++------------------
 arch/powerpc/kernel/ptrace/ptrace.c |  2 +-
 include/linux/seccomp.h             | 12 ++++--------
 kernel/entry/common.c               |  2 +-
 kernel/seccomp.c                    | 26 ++++++++++----------------
 5 files changed, 18 insertions(+), 44 deletions(-)
author maintainer
#1 lore raw

PATCH 1/4 seccomp/mips: change syscall_trace_enter() to use secure_computing()

arch/mips/Kconfig selects HAVE_ARCH_SECCOMP_FILTER so syscall_trace_enter() can just use __secure_computing(NULL) and rely on populate_seccomp_data(sd) and "sd == NULL" checks in __secure_computing(sd) paths.

With the change above syscall_trace_enter() can just use secure_computing() and avoid #ifdef + test_thread_flag(TIF_SECCOMP). CONFIG_GENERIC_ENTRY is not defined, so test_syscall_work(SECCOMP) will check TIF_SECCOMP.

---
 arch/mips/kernel/ptrace.c | 20 ++------------------
 1 file changed, 2 insertions(+), 18 deletions(-)
arch/mips/kernel/ptrace.c +2 -18
index 61503a36067e..f7107479c7fa 100644
@@ -1326,24 +1326,8 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs)
 			return -1;
 	}
 
-#ifdef CONFIG_SECCOMP
-	if (unlikely(test_thread_flag(TIF_SECCOMP))) {
-		int ret, i;
-		struct seccomp_data sd;
-		unsigned long args[6];
-
-		sd.nr = current_thread_info()->syscall;
-		sd.arch = syscall_get_arch(current);
-		syscall_get_arguments(current, regs, args);
-		for (i = 0; i < 6; i++)
-			sd.args[i] = args[i];
-		sd.instruction_pointer = KSTK_EIP(current);
-
-		ret = __secure_computing(&sd);
-		if (ret == -1)
-			return ret;
-	}
-#endif
+	if (secure_computing())
+		return -1;
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_enter(regs, regs->regs[2]);
Signature · 1 line
2.25.1.362.g51ebf55
author maintainer
#4 lore raw

PATCH 2/4 seccomp: kill the dead code in the !CONFIG_HAVE_ARCH_SECCOMP_FILTER version of __secure_computing()

In reply to Oleg Nesterov

Depending on CONFIG_HAVE_ARCH_SECCOMP_FILTER, __secure_computing(NULL) will crash or not, this is not consistent/safe.

Fortunately, if CONFIG_HAVE_ARCH_SECCOMP_FILTER=n, __secure_computing() has no callers, these architectures use secure_computing_strict().

Also, after the previous change __secure_computing(sd) is always called with sd == NULL, so it is clear that we can remove the code which makes no sense.

---
 include/linux/seccomp.h | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
include/linux/seccomp.h +1 -5
index e45531455d3b..e01dfe57a884 100644
@@ -32,11 +32,7 @@ static inline int secure_computing(void)
 }
 #else
 extern void secure_computing_strict(int this_syscall);
-static inline int __secure_computing(const struct seccomp_data *sd)
-{
-	secure_computing_strict(sd->nr);
-	return 0;
-}
+static inline int __secure_computing(const struct seccomp_data *sd) { return 0; }
 #endif
 
 extern long prctl_get_seccomp(void);
Signature · 1 line
2.25.1.362.g51ebf55
author maintainer
#8 lore raw

PATCH 3/4 seccomp: remove the 'sd' argument from __secure_computing()

In reply to Oleg Nesterov

After the previous changes 'sd' is always NULL.

---
 arch/powerpc/kernel/ptrace/ptrace.c | 2 +-
 include/linux/seccomp.h             | 8 ++++----
 kernel/entry/common.c               | 2 +-
 kernel/seccomp.c                    | 7 +++----
 4 files changed, 9 insertions(+), 10 deletions(-)
arch/powerpc/kernel/ptrace/ptrace.c +1 -1
index 727ed4a14545..c6997df63287 100644
@@ -215,7 +215,7 @@ static int do_seccomp(struct pt_regs *regs)
 	 * have already loaded -ENOSYS into r3, or seccomp has put
 	 * something else in r3 (via SECCOMP_RET_ERRNO/TRACE).
 	 */
-	if (__secure_computing(NULL))
+	if (__secure_computing())
 		return -1;
 
 	/*
include/linux/seccomp.h +4 -4
index e01dfe57a884..6125baa96b76 100644
@@ -23,16 +23,16 @@
 #include <asm/seccomp.h>
 
 #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
-extern int __secure_computing(const struct seccomp_data *sd);
+extern int __secure_computing(void);
 static inline int secure_computing(void)
 {
 	if (unlikely(test_syscall_work(SECCOMP)))
-		return  __secure_computing(NULL);
+		return  __secure_computing();
 	return 0;
 }
 #else
 extern void secure_computing_strict(int this_syscall);
-static inline int __secure_computing(const struct seccomp_data *sd) { return 0; }
+static inline int __secure_computing(void) { return 0; }
 #endif
 
 extern long prctl_get_seccomp(void);
@@ -54,7 +54,7 @@ static inline int secure_computing(void) { return 0; }
 #else
 static inline void secure_computing_strict(int this_syscall) { return; }
 #endif
-static inline int __secure_computing(const struct seccomp_data *sd) { return 0; }
+static inline int __secure_computing(void) { return 0; }
 
 static inline long prctl_get_seccomp(void)
 {
kernel/entry/common.c +1 -1
index e33691d5adf7..20154572ede9 100644
@@ -49,7 +49,7 @@ long syscall_trace_enter(struct pt_regs *regs, long syscall,
 
 	/* Do seccomp after ptrace, to catch any tracer changes. */
 	if (work & SYSCALL_WORK_SECCOMP) {
-		ret = __secure_computing(NULL);
+		ret = __secure_computing();
 		if (ret == -1L)
 			return ret;
 	}
kernel/seccomp.c +3 -4
index 385d48293a5f..c29dfe82139e 100644
@@ -1347,7 +1347,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 }
 #endif
 
-int __secure_computing(const struct seccomp_data *sd)
+int __secure_computing(void)
 {
 	int mode = current->seccomp.mode;
 	int this_syscall;
@@ -1356,15 +1356,14 @@ int __secure_computing(const struct seccomp_data *sd)
 	    unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
 		return 0;
 
-	this_syscall = sd ? sd->nr :
-		syscall_get_nr(current, current_pt_regs());
+	this_syscall = syscall_get_nr(current, current_pt_regs());
 
 	switch (mode) {
 	case SECCOMP_MODE_STRICT:
 		__secure_computing_strict(this_syscall);  /* may call do_exit */
 		return 0;
 	case SECCOMP_MODE_FILTER:
-		return __seccomp_filter(this_syscall, sd, false);
+		return __seccomp_filter(this_syscall, NULL, false);
 	/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */
 	case SECCOMP_MODE_DEAD:
 		WARN_ON_ONCE(1);
Signature · 1 line
2.25.1.362.g51ebf55
author maintainer
#10 lore raw

PATCH 4/4 seccomp: remove the 'sd' argument from __seccomp_filter()

In reply to Oleg Nesterov

After the previous change 'sd' is always NULL.

---
 kernel/seccomp.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)
kernel/seccomp.c +8 -13
index c29dfe82139e..75e293d3c1a1 100644
@@ -1213,13 +1213,12 @@ static int seccomp_do_user_notification(int this_syscall,
 	return -1;
 }
 
-static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
-			    const bool recheck_after_trace)
+static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)
 {
 	u32 filter_ret, action;
+	struct seccomp_data sd;
 	struct seccomp_filter *match = NULL;
 	int data;
-	struct seccomp_data sd_local;
 
 	/*
 	 * Make sure that any changes to mode from another thread have
@@ -1227,12 +1226,9 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 	 */
 	smp_rmb();
 
-	if (!sd) {
-		populate_seccomp_data(&sd_local);
-		sd = &sd_local;
-	}
+	populate_seccomp_data(&sd);
 
-	filter_ret = seccomp_run_filters(sd, &match);
+	filter_ret = seccomp_run_filters(&sd, &match);
 	data = filter_ret & SECCOMP_RET_DATA;
 	action = filter_ret & SECCOMP_RET_ACTION_FULL;
 
@@ -1290,13 +1286,13 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 		 * a reload of all registers. This does not goto skip since
 		 * a skip would have already been reported.
 		 */
-		if (__seccomp_filter(this_syscall, NULL, true))
+		if (__seccomp_filter(this_syscall, true))
 			return -1;
 
 		return 0;
 
 	case SECCOMP_RET_USER_NOTIF:
-		if (seccomp_do_user_notification(this_syscall, match, sd))
+		if (seccomp_do_user_notification(this_syscall, match, &sd))
 			goto skip;
 
 		return 0;
@@ -1338,8 +1334,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 	return -1;
 }
 #else
-static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
-			    const bool recheck_after_trace)
+static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)
 {
 	BUG();
 
@@ -1363,7 +1358,7 @@ int __secure_computing(void)
 		__secure_computing_strict(this_syscall);  /* may call do_exit */
 		return 0;
 	case SECCOMP_MODE_FILTER:
-		return __seccomp_filter(this_syscall, NULL, false);
+		return __seccomp_filter(this_syscall, false);
 	/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */
 	case SECCOMP_MODE_DEAD:
 		WARN_ON_ONCE(1);
Signature · 1 line
2.25.1.362.g51ebf55
maintainer Reviewed-by on v1 1/4
#2 lore raw

Re: [PATCH 1/4] seccomp/mips: change syscall_trace_enter() to use secure_computing()

In reply to Oleg Nesterov
Quoted 18 lines · Oleg Nesterov

arch/mips/Kconfig selects HAVE_ARCH_SECCOMP_FILTER so syscall_trace_enter() can just use __secure_computing(NULL) and rely on populate_seccomp_data(sd) and "sd == NULL" checks in __secure_computing(sd) paths.

With the change above syscall_trace_enter() can just use secure_computing() and avoid #ifdef + test_thread_flag(TIF_SECCOMP). CONFIG_GENERIC_ENTRY is not defined, so test_syscall_work(SECCOMP) will check TIF_SECCOMP.

---
 arch/mips/kernel/ptrace.c | 20 ++------------------
 1 file changed, 2 insertions(+), 18 deletions(-)
arch/mips/kernel/ptrace.c +0 -0
index 61503a36067e..f7107479c7fa 100644

arch/mips/kernel/ptrace.c asmlinkage long syscall_trace_enter(struct pt_regs *regs) · line 1330

Quoted 5 lines
arch/mips/kernel/ptrace.c +0 -2
@@ -1326,24 +1326,8 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs)
 			return -1;
 	}
 
-#ifdef CONFIG_SECCOMP
-	if (unlikely(test_thread_flag(TIF_SECCOMP))) {

Yup, this test works out the same as what secure_computing() does.

arch/mips/kernel/ptrace.c asmlinkage long syscall_trace_enter(struct pt_regs *regs) · line 1335

Quoted 5 lines
arch/mips/kernel/ptrace.c +0 -5
-		int ret, i;
-		struct seccomp_data sd;
-		unsigned long args[6];
-
-		sd.nr = current_thread_info()->syscall;

This matches MIPS's syscall_get_nr() in populate_seccomp_data().

arch/mips/kernel/ptrace.c asmlinkage long syscall_trace_enter(struct pt_regs *regs) · line 1340

Quoted 5 lines
arch/mips/kernel/ptrace.c +0 -5
-		sd.arch = syscall_get_arch(current);
-		syscall_get_arguments(current, regs, args);
-		for (i = 0; i < 6; i++)
-			sd.args[i] = args[i];
-		sd.instruction_pointer = KSTK_EIP(current);

Rest matches the rest of populate_seccomp_data().

arch/mips/kernel/ptrace.c asmlinkage long syscall_trace_enter(struct pt_regs *regs) · line 1333

Quoted 12 lines
arch/mips/kernel/ptrace.c +2 -6
-
-		ret = __secure_computing(&sd);
-		if (ret == -1)
-			return ret;
-	}
-#endif
+	if (secure_computing())
+		return -1;
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_enter(regs, regs->regs[2]);

So this check out logically from what I can see. I can build test it, but I don't have MIPS emulation set up. I'd love an Ack from a MIPS maintainer...

Signature · 1 line
Kees Cook
maintainer
#5 lore raw

Re: [PATCH 2/4] seccomp: kill the dead code in the !CONFIG_HAVE_ARCH_SECCOMP_FILTER version of __secure_computing()

In reply to Oleg Nesterov
Quoted 2 lines · Oleg Nesterov

Depending on CONFIG_HAVE_ARCH_SECCOMP_FILTER, __secure_computing(NULL) will crash or not, this is not consistent/safe.

Right now this never happens because there are no callers.

Quoted 2 lines

Fortunately, if CONFIG_HAVE_ARCH_SECCOMP_FILTER=n, __secure_computing() has no callers, these architectures use secure_computing_strict().

As you say here.

Quoted 3 lines

Also, after the previous change __secure_computing(sd) is always called with sd == NULL, so it is clear that we can remove the code which makes no sense.

However, after this change, if someone were to *add* a caller, it would bypass strict mode. Instead of "return 0", it seems like it'd be better to remove the function entirely (and maybe add a comment about calling secure_computing_strict() directly)?

Quoted 26 lines
---
 include/linux/seccomp.h | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
include/linux/seccomp.h +1 -5
index e45531455d3b..e01dfe57a884 100644
@@ -32,11 +32,7 @@ static inline int secure_computing(void)
 }
 #else
 extern void secure_computing_strict(int this_syscall);
-static inline int __secure_computing(const struct seccomp_data *sd)
-{
-	secure_computing_strict(sd->nr);
-	return 0;
-}
+static inline int __secure_computing(const struct seccomp_data *sd) { return 0; }
 #endif
 
 extern long prctl_get_seccomp(void);
Signature · 1 line
2.25.1.362.g51ebf55
Signature · 1 line
Kees Cook
author maintainer
#6 lore raw

Re: [PATCH 2/4] seccomp: kill the dead code in the !CONFIG_HAVE_ARCH_SECCOMP_FILTER version of __secure_computing()

In reply to Kees Cook
Quoted 10 lines · Kees Cook
Quoted 2 lines · Oleg Nesterov

Depending on CONFIG_HAVE_ARCH_SECCOMP_FILTER, __secure_computing(NULL) will crash or not, this is not consistent/safe.

Right now this never happens because there are no callers.

Quoted 2 lines

Fortunately, if CONFIG_HAVE_ARCH_SECCOMP_FILTER=n, __secure_computing() has no callers, these architectures use secure_computing_strict().

Quoted 8 lines

As you say here.

Quoted 3 lines

Also, after the previous change __secure_computing(sd) is always called with sd == NULL, so it is clear that we can remove the code which makes no sense.

However, after this change, if someone were to *add* a caller, it would bypass strict mode.

OK, thanks, I agree this is not consistent, even if I think that !CONFIG_HAVE_ARCH_SECCOMP_FILTER arches should not add a new caller.

Quoted 3 lines

Instead of "return 0", it seems like it'd be better
to remove the function entirely (and maybe add a comment about calling secure_computing_strict() directly)?

This means that __secure_computing() will be defined even if !CONFIG_SECCOMP, but it won't be defined if CONFIG_SECCOMP && !CONFIG_HAVE_ARCH_SECCOMP_FILTER.

How about

	__secure_computing()
	{
		return secure_computing_strict(syscall_get_nr(...));
	}

in the "#ifndef CONFIG_HAVE_ARCH_SECCOMP_FILTER" section near secure_computing_strict() in kernel/seccomp.c ?

Oleg.

maintainer Acked-by on v1 1/4
#3 lore raw

Re: [PATCH 1/4] seccomp/mips: change syscall_trace_enter() to use secure_computing()

In reply to Oleg Nesterov
Quoted 46 lines · Oleg Nesterov

arch/mips/Kconfig selects HAVE_ARCH_SECCOMP_FILTER so syscall_trace_enter() can just use __secure_computing(NULL) and rely on populate_seccomp_data(sd) and "sd == NULL" checks in __secure_computing(sd) paths.

With the change above syscall_trace_enter() can just use secure_computing() and avoid #ifdef + test_thread_flag(TIF_SECCOMP). CONFIG_GENERIC_ENTRY is not defined, so test_syscall_work(SECCOMP) will check TIF_SECCOMP.

---
 arch/mips/kernel/ptrace.c | 20 ++------------------
 1 file changed, 2 insertions(+), 18 deletions(-)
arch/mips/kernel/ptrace.c +2 -18
index 61503a36067e..f7107479c7fa 100644
@@ -1326,24 +1326,8 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs)
 			return -1;
 	}
 
-#ifdef CONFIG_SECCOMP
-	if (unlikely(test_thread_flag(TIF_SECCOMP))) {
-		int ret, i;
-		struct seccomp_data sd;
-		unsigned long args[6];
-
-		sd.nr = current_thread_info()->syscall;
-		sd.arch = syscall_get_arch(current);
-		syscall_get_arguments(current, regs, args);
-		for (i = 0; i < 6; i++)
-			sd.args[i] = args[i];
-		sd.instruction_pointer = KSTK_EIP(current);
-
-		ret = __secure_computing(&sd);
-		if (ret == -1)
-			return ret;
-	}
-#endif
+	if (secure_computing())
+		return -1;
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_enter(regs, regs->regs[2]);
Signature · 1 line
2.25.1.362.g51ebf55
Signature · 2 lines
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]
maintainer
#7 lore raw

Re: [PATCH 2/4] seccomp: kill the dead code in the !CONFIG_HAVE_ARCH_SECCOMP_FILTER version of __secure_computing()

In reply to Oleg Nesterov
Quoted 9 lines · Oleg Nesterov

How about

	__secure_computing()
	{
		return secure_computing_strict(syscall_get_nr(...));
	}

in the "#ifndef CONFIG_HAVE_ARCH_SECCOMP_FILTER" section near secure_computing_strict() in kernel/seccomp.c ?

Yeah, that should be good.

Signature · 1 line
Kees Cook