The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
@ 2026-05-26 15:32 Jamie Hill-Daniel
  2026-05-26 15:32 ` [PATCH RESEND 1/2] " Jamie Hill-Daniel
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Jamie Hill-Daniel @ 2026-05-26 15:32 UTC (permalink / raw)
  To: Kees Cook, Andy Lutomirski, Will Drewry, Shuah Khan
  Cc: linux-kernel, linux-kselftest, bpf, Jamie Hill-Daniel

This patch adjusts the logic used by seccomp to allow applying both
`SECCOMP_MODE_FILTER` and `SECCOMP_MODE_STRICT` to the same process.

Currently, once seccomp has been initialized, a process may not
transition to a different mode (only add additional filters).
This means that in container environments such as Docker, which by
default runs with `SECCOMP_MODE_FILTER`, processes may not enable
`SECCOMP_MODE_STRICT`. This is an obstacle to using applications
requiring `SECCOMP_MODE_STRICT` in these environments, and requires
disabling these security measures.

This patch introduces a new `SECCOMP_MODE_COMBINED` (used internally,
not exposed to userspace). When a process attempts to apply
`SECCOMP_MODE_FILTER` or `SECCOMP_MODE_STRICT`, this mode will be used
instead if the other mode is already enabled.

When subsequently running secure computing checks, we run the strict
checks followed by any installed filters.

Link: https://github.com/moby/moby/issues/42082

Signed-off-by: Jamie Hill-Daniel <jamie@hill-daniel.co.uk>
---
Jamie Hill-Daniel (2):
      seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
      selftest: seccomp: Adjust test for using both `STRICT` and `FILTER`

 kernel/seccomp.c                              | 46 +++++++++++++++------------
 tools/testing/selftests/seccomp/seccomp_bpf.c |  5 ++-
 2 files changed, 28 insertions(+), 23 deletions(-)
---
base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
change-id: 20260302-seccomp-combined-24bc3dbe32fd

Best regards,
-- 
Jamie Hill-Daniel <jamie@hill-daniel.co.uk>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-05-26 15:32 [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Jamie Hill-Daniel
@ 2026-05-26 15:32 ` Jamie Hill-Daniel
  2026-06-12 19:25   ` Will Drewry
  2026-05-26 15:32 ` [PATCH RESEND 2/2] selftest: seccomp: Adjust test for using both `STRICT` and `FILTER` Jamie Hill-Daniel
  2026-06-13  4:14 ` [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Kees Cook
  2 siblings, 1 reply; 14+ messages in thread
From: Jamie Hill-Daniel @ 2026-05-26 15:32 UTC (permalink / raw)
  To: Kees Cook, Andy Lutomirski, Will Drewry, Shuah Khan
  Cc: linux-kernel, linux-kselftest, bpf, Jamie Hill-Daniel

It is currently impossible to enable `SECCOMP_MODE_STRICT` if
`SECCOMP_MODE_FILTER` is enabled, and vice-versa. This makes using
seccomp difficult in environments such as Docker, which installs a
seccomp filter by default.

Introduce a new internal `SECCOMP_MODE_COMBINED`
that runs `strict` checks, followed by any installed filters.

Link: https://github.com/moby/moby/issues/42082
Signed-off-by: Jamie Hill-Daniel <jamie@hill-daniel.co.uk>
---
 kernel/seccomp.c | 46 ++++++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 25f62867a16d..8201a050d358 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -33,6 +33,8 @@
 
 /* Not exposed in headers: strictly internal use only. */
 #define SECCOMP_MODE_DEAD	(SECCOMP_MODE_FILTER + 1)
+/* Run SECCOMP_MODE_STRICT checks, followed by SECCOMP_MODE_FILTER  */
+#define SECCOMP_MODE_COMBINED (SECCOMP_MODE_DEAD + 1)
 
 #ifdef CONFIG_SECCOMP_FILTER
 #include <linux/file.h>
@@ -432,14 +434,21 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd,
 }
 #endif /* CONFIG_SECCOMP_FILTER */
 
-static inline bool seccomp_may_assign_mode(unsigned long seccomp_mode)
+/**
+ * seccomp_needs_combined: internal function for checking if requested mode
+ * needs to be upgraded to `SECCOMP_MODE_COMBINED`.
+ *
+ */
+static inline bool seccomp_needs_combined(unsigned long seccomp_mode)
 {
 	assert_spin_locked(&current->sighand->siglock);
 
-	if (current->seccomp.mode && current->seccomp.mode != seccomp_mode)
-		return false;
+	if ((current->seccomp.mode == SECCOMP_MODE_STRICT ||
+	     current->seccomp.mode == SECCOMP_MODE_FILTER) &&
+	    current->seccomp.mode != seccomp_mode)
+		return true;
 
-	return true;
+	return false;
 }
 
 void __weak arch_seccomp_spec_mitigate(struct task_struct *task) { }
@@ -1407,6 +1416,9 @@ int __secure_computing(void)
 		WARN_ON_ONCE(1);
 		do_exit(SIGKILL);
 		return -1;
+	case SECCOMP_MODE_COMBINED:
+		__secure_computing_strict(this_syscall);
+		return __seccomp_filter(this_syscall, false);
 	default:
 		BUG();
 	}
@@ -1421,30 +1433,23 @@ long prctl_get_seccomp(void)
 /**
  * seccomp_set_mode_strict: internal function for setting strict seccomp
  *
- * Once current->seccomp.mode is non-zero, it may not be changed.
+ * Once current->seccomp.mode is non-zero, it may only be changed to `COMBINED` or `DEAD`.
  *
- * Returns 0 on success or -EINVAL on failure.
  */
-static long seccomp_set_mode_strict(void)
+static void seccomp_set_mode_strict(void)
 {
-	const unsigned long seccomp_mode = SECCOMP_MODE_STRICT;
-	long ret = -EINVAL;
+	unsigned long seccomp_mode = SECCOMP_MODE_STRICT;
 
 	spin_lock_irq(&current->sighand->siglock);
 
-	if (!seccomp_may_assign_mode(seccomp_mode))
-		goto out;
+	if (seccomp_needs_combined(seccomp_mode))
+		seccomp_mode = SECCOMP_MODE_COMBINED;
 
 #ifdef TIF_NOTSC
 	disable_TSC();
 #endif
 	seccomp_assign_mode(current, seccomp_mode, 0);
-	ret = 0;
-
-out:
 	spin_unlock_irq(&current->sighand->siglock);
-
-	return ret;
 }
 
 #ifdef CONFIG_SECCOMP_FILTER
@@ -1956,7 +1961,7 @@ static bool has_duplicate_listener(struct seccomp_filter *new_child)
 static long seccomp_set_mode_filter(unsigned int flags,
 				    const char __user *filter)
 {
-	const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
+	long seccomp_mode = SECCOMP_MODE_FILTER;
 	struct seccomp_filter *prepared = NULL;
 	long ret = -EINVAL;
 	int listener = -1;
@@ -2016,8 +2021,8 @@ static long seccomp_set_mode_filter(unsigned int flags,
 
 	spin_lock_irq(&current->sighand->siglock);
 
-	if (!seccomp_may_assign_mode(seccomp_mode))
-		goto out;
+	if (seccomp_needs_combined(seccomp_mode))
+		seccomp_mode = SECCOMP_MODE_COMBINED;
 
 	if (has_duplicate_listener(prepared)) {
 		ret = -EBUSY;
@@ -2105,7 +2110,8 @@ static long do_seccomp(unsigned int op, unsigned int flags,
 	case SECCOMP_SET_MODE_STRICT:
 		if (flags != 0 || uargs != NULL)
 			return -EINVAL;
-		return seccomp_set_mode_strict();
+		seccomp_set_mode_strict();
+		return 0;
 	case SECCOMP_SET_MODE_FILTER:
 		return seccomp_set_mode_filter(flags, uargs);
 	case SECCOMP_GET_ACTION_AVAIL:

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH RESEND 2/2] selftest: seccomp: Adjust test for using both `STRICT` and `FILTER`
  2026-05-26 15:32 [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Jamie Hill-Daniel
  2026-05-26 15:32 ` [PATCH RESEND 1/2] " Jamie Hill-Daniel
@ 2026-05-26 15:32 ` Jamie Hill-Daniel
  2026-06-13  4:14 ` [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Kees Cook
  2 siblings, 0 replies; 14+ messages in thread
From: Jamie Hill-Daniel @ 2026-05-26 15:32 UTC (permalink / raw)
  To: Kees Cook, Andy Lutomirski, Will Drewry, Shuah Khan
  Cc: linux-kernel, linux-kselftest, bpf, Jamie Hill-Daniel

This test previously tested that applying `STRICT` after `FILTER` is
impossible - update it to test that it is now possible.

Signed-off-by: Jamie Hill-Daniel <jamie@hill-daniel.co.uk>
---
 tools/testing/selftests/seccomp/seccomp_bpf.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 874f17763536..ba042828dcbd 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -516,7 +516,7 @@ TEST(filter_chain_limits)
 	}
 }
 
-TEST(mode_filter_cannot_move_to_strict)
+TEST(mode_filter_combined)
 {
 	struct sock_filter filter[] = {
 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
@@ -534,8 +534,7 @@ TEST(mode_filter_cannot_move_to_strict)
 	ASSERT_EQ(0, ret);
 
 	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, 0, 0);
-	EXPECT_EQ(-1, ret);
-	EXPECT_EQ(EINVAL, errno);
+	ASSERT_EQ(0, ret);
 }
 
 

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-05-26 15:32 ` [PATCH RESEND 1/2] " Jamie Hill-Daniel
@ 2026-06-12 19:25   ` Will Drewry
  2026-06-12 21:24     ` Andy Lutomirski
  2026-06-12 22:37     ` clubby789
  0 siblings, 2 replies; 14+ messages in thread
From: Will Drewry @ 2026-06-12 19:25 UTC (permalink / raw)
  To: Jamie Hill-Daniel
  Cc: Kees Cook, Andy Lutomirski, Shuah Khan, linux-kernel,
	linux-kselftest, bpf, Jamie Hill-Daniel

On Tue, May 26, 2026 at 10:42 AM Jamie Hill-Daniel <clubby789@gmail.com> wrote:
>
> It is currently impossible to enable `SECCOMP_MODE_STRICT` if
> `SECCOMP_MODE_FILTER` is enabled, and vice-versa. This makes using
> seccomp difficult in environments such as Docker, which installs a
> seccomp filter by default.

Some quick thoughts on your resend -- the original reasons for
this approach:
(a) filter policy != strict policy
(b) filter can implement strict, if layering is desired
(c) minimize checks in the syscall entry/return path

I'd expected folks to simply create the ~80 byte strict filter and install
it if they needed STRICT policy. More discussion below.

> Introduce a new internal `SECCOMP_MODE_COMBINED`
> that runs `strict` checks, followed by any installed filters.
>
> Link: https://github.com/moby/moby/issues/42082
> Signed-off-by: Jamie Hill-Daniel <jamie@hill-daniel.co.uk>
> ---
>  kernel/seccomp.c | 46 ++++++++++++++++++++++++++--------------------
>  1 file changed, 26 insertions(+), 20 deletions(-)
>
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index 25f62867a16d..8201a050d358 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -33,6 +33,8 @@
>
>  /* Not exposed in headers: strictly internal use only. */
>  #define SECCOMP_MODE_DEAD      (SECCOMP_MODE_FILTER + 1)
> +/* Run SECCOMP_MODE_STRICT checks, followed by SECCOMP_MODE_FILTER  */
> +#define SECCOMP_MODE_COMBINED (SECCOMP_MODE_DEAD + 1)

I'm not sure if DEAD is meant to be fixed at the end of all modes or
not -- given that it's internal.

>
>  #ifdef CONFIG_SECCOMP_FILTER
>  #include <linux/file.h>
> @@ -432,14 +434,21 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd,
>  }
>  #endif /* CONFIG_SECCOMP_FILTER */
>
> -static inline bool seccomp_may_assign_mode(unsigned long seccomp_mode)
> +/**
> + * seccomp_needs_combined: internal function for checking if requested mode
> + * needs to be upgraded to `SECCOMP_MODE_COMBINED`.
> + *
> + */
> +static inline bool seccomp_needs_combined(unsigned long seccomp_mode)

It is easier to reason about if you keep the access checks separate from the
behavior-change decision. Setting seccomp modes isn't on a particularly
performance-critical path, so we can be more verbose and explicit.

>  {
>         assert_spin_locked(&current->sighand->siglock);
>
> -       if (current->seccomp.mode && current->seccomp.mode != seccomp_mode)
> -               return false;
> +       if ((current->seccomp.mode == SECCOMP_MODE_STRICT ||
> +            current->seccomp.mode == SECCOMP_MODE_FILTER) &&
> +           current->seccomp.mode != seccomp_mode)
> +               return true;

AFAICT, the only valid "combined" case is current->seccomp.mode==FILTER
and seccomp_mode==STRICT.   There are other allowed transitions, but
not allowed for transitioning from FILTER->STRICT via COMBINED.

If this wasn't subsuming the update access check, then the single allowed
transition could be checked in set_mode_strict() (or a helper).

>
> -       return true;
> +       return false;
>  }
>
>  void __weak arch_seccomp_spec_mitigate(struct task_struct *task) { }
> @@ -1407,6 +1416,9 @@ int __secure_computing(void)
>                 WARN_ON_ONCE(1);
>                 do_exit(SIGKILL);
>                 return -1;
> +       case SECCOMP_MODE_COMBINED:
> +               __secure_computing_strict(this_syscall);
> +               return __seccomp_filter(this_syscall, false);
>         default:
>                 BUG();
>         }
> @@ -1421,30 +1433,23 @@ long prctl_get_seccomp(void)
>  /**
>   * seccomp_set_mode_strict: internal function for setting strict seccomp
>   *
> - * Once current->seccomp.mode is non-zero, it may not be changed.
> + * Once current->seccomp.mode is non-zero, it may only be changed to `COMBINED` or `DEAD`.
>   *
> - * Returns 0 on success or -EINVAL on failure.
>   */
> -static long seccomp_set_mode_strict(void)
> +static void seccomp_set_mode_strict(void)
>  {
> -       const unsigned long seccomp_mode = SECCOMP_MODE_STRICT;
> -       long ret = -EINVAL;
> +       unsigned long seccomp_mode = SECCOMP_MODE_STRICT;
>
>         spin_lock_irq(&current->sighand->siglock);
>
> -       if (!seccomp_may_assign_mode(seccomp_mode))
> -               goto out;
> +       if (seccomp_needs_combined(seccomp_mode))
> +               seccomp_mode = SECCOMP_MODE_COMBINED;
>
>  #ifdef TIF_NOTSC
>         disable_TSC();
>  #endif
>         seccomp_assign_mode(current, seccomp_mode, 0);
> -       ret = 0;
> -
> -out:
>         spin_unlock_irq(&current->sighand->siglock);
> -
> -       return ret;

Is this reachable when mode is DEAD? In its current form, it would fail
out on may_assign_mode(), but now you have to consider if a race
could silently clobber the DEAD value (let's say).

>  }
>
>  #ifdef CONFIG_SECCOMP_FILTER
> @@ -1956,7 +1961,7 @@ static bool has_duplicate_listener(struct seccomp_filter *new_child)
>  static long seccomp_set_mode_filter(unsigned int flags,
>                                     const char __user *filter)
>  {
> -       const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
> +       long seccomp_mode = SECCOMP_MODE_FILTER;
>         struct seccomp_filter *prepared = NULL;
>         long ret = -EINVAL;
>         int listener = -1;
> @@ -2016,8 +2021,8 @@ static long seccomp_set_mode_filter(unsigned int flags,
>
>         spin_lock_irq(&current->sighand->siglock);
>
> -       if (!seccomp_may_assign_mode(seccomp_mode))
> -               goto out;
> +       if (seccomp_needs_combined(seccomp_mode))
> +               seccomp_mode = SECCOMP_MODE_COMBINED;

So I have two concerns here --

1. By layering, STRICT becomes subject to FILTER RET behaviors.
2. If we did want to layer them, it would be ideal to separate the 'upgrade'
    decision from the access checks and make the layering path explicit.

If you are running a legacy binary that uses STRICT in Docker, then I
understand the goal, but there are userspace options.

I think it's hard to want to open the door on changing STRICT without
a good reason to work through all the implications that come with it:
cross-checking every SECCOMP_MODE_FILTER reference, sorting
out thread sync interactions, ...

That said, this change could be streamlined and look for ways
to minimize any potential implications.

Am I missing something or overstating it?

Thanks!
will

>
>         if (has_duplicate_listener(prepared)) {
>                 ret = -EBUSY;
> @@ -2105,7 +2110,8 @@ static long do_seccomp(unsigned int op, unsigned int flags,
>         case SECCOMP_SET_MODE_STRICT:
>                 if (flags != 0 || uargs != NULL)
>                         return -EINVAL;
> -               return seccomp_set_mode_strict();
> +               seccomp_set_mode_strict();
> +               return 0;
>         case SECCOMP_SET_MODE_FILTER:
>                 return seccomp_set_mode_filter(flags, uargs);
>         case SECCOMP_GET_ACTION_AVAIL:
>
> --
> 2.54.0
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-12 19:25   ` Will Drewry
@ 2026-06-12 21:24     ` Andy Lutomirski
  2026-06-12 22:01       ` clubby789
  2026-06-12 22:37     ` clubby789
  1 sibling, 1 reply; 14+ messages in thread
From: Andy Lutomirski @ 2026-06-12 21:24 UTC (permalink / raw)
  To: Will Drewry
  Cc: Jamie Hill-Daniel, Kees Cook, Shuah Khan, linux-kernel,
	linux-kselftest, bpf, Jamie Hill-Daniel

On Fri, Jun 12, 2026 at 12:25 PM Will Drewry <wad@chromium.org> wrote:
>
> On Tue, May 26, 2026 at 10:42 AM Jamie Hill-Daniel <clubby789@gmail.com> wrote:
> >
> > It is currently impossible to enable `SECCOMP_MODE_STRICT` if
> > `SECCOMP_MODE_FILTER` is enabled, and vice-versa. This makes using
> > seccomp difficult in environments such as Docker, which installs a
> > seccomp filter by default.
>
> Some quick thoughts on your resend -- the original reasons for
> this approach:
> (a) filter policy != strict policy
> (b) filter can implement strict, if layering is desired
> (c) minimize checks in the syscall entry/return path
>
> I'd expected folks to simply create the ~80 byte strict filter and install
> it if they needed STRICT policy.

I wonder if It would be reasonable to have the kernel do this on
behalf of the user program that's asking for STRICT.  The
implementation would probably be trivial.

--Andy

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-12 21:24     ` Andy Lutomirski
@ 2026-06-12 22:01       ` clubby789
  2026-06-12 22:37         ` Andy Lutomirski
  0 siblings, 1 reply; 14+ messages in thread
From: clubby789 @ 2026-06-12 22:01 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Will Drewry, Kees Cook, Shuah Khan, linux-kernel, linux-kselftest,
	bpf, Jamie Hill-Daniel

On Fri, Jun 12, 2026 at 10:24 PM Andy Lutomirski <luto@amacapital.net> wrote:
>
> I wonder if It would be reasonable to have the kernel do this on
> behalf of the user program that's asking for STRICT.  The
> implementation would probably be trivial.

I experimented with this approach after the initial AI review, but it
turned out surprisingly complex,
requiring a decent amount of refactoring to allow installing
kernel-resident programs. The filter
itself is also rather complex (mostly due to needing to account for
BPF jump sizes, which differ
as different configs (uprobe, uretprobe, SECCOMP_ARCH_COMPAT) have
different logic., and I'd worry about
keeping logic synced.
If that approach is worth pursuing though, I can submit that version
of this patch.

- Jamie

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-12 22:01       ` clubby789
@ 2026-06-12 22:37         ` Andy Lutomirski
  2026-06-12 22:58           ` clubby789
  0 siblings, 1 reply; 14+ messages in thread
From: Andy Lutomirski @ 2026-06-12 22:37 UTC (permalink / raw)
  To: clubby789
  Cc: Will Drewry, Kees Cook, Shuah Khan, linux-kernel, linux-kselftest,
	bpf, Jamie Hill-Daniel

On Fri, Jun 12, 2026 at 3:02 PM clubby789 <clubby789@gmail.com> wrote:
>
> On Fri, Jun 12, 2026 at 10:24 PM Andy Lutomirski <luto@amacapital.net> wrote:
> >
> > I wonder if It would be reasonable to have the kernel do this on
> > behalf of the user program that's asking for STRICT.  The
> > implementation would probably be trivial.
>
> I experimented with this approach after the initial AI review, but it
> turned out surprisingly complex,
> requiring a decent amount of refactoring to allow installing
> kernel-resident programs.

Maybe so.  But there is a function bpf_prog_create (as opposed to
bpf_prog_create_from_user).

> The filter
> itself is also rather complex (mostly due to needing to account for
> BPF jump sizes, which differ
> as different configs (uprobe, uretprobe, SECCOMP_ARCH_COMPAT) have
> different logic., and I'd worry about
> keeping logic synced.

Perhaps you and your AI could elaborate?  What are these jump sizes?

In any case, I think the actual issue is that the STRICT filter's
failure case doesn't quite correspond to any of the FILTER actions.
So maybe it's too complex to be worthwhile.

--Andy

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-12 19:25   ` Will Drewry
  2026-06-12 21:24     ` Andy Lutomirski
@ 2026-06-12 22:37     ` clubby789
  2026-06-12 22:50       ` Andy Lutomirski
  1 sibling, 1 reply; 14+ messages in thread
From: clubby789 @ 2026-06-12 22:37 UTC (permalink / raw)
  To: Will Drewry
  Cc: Kees Cook, Andy Lutomirski, Shuah Khan, linux-kernel,
	linux-kselftest, bpf, Jamie Hill-Daniel

On Fri, Jun 12, 2026 at 8:25 PM Will Drewry <wad@chromium.org> wrote:
>
> So I have two concerns here --
>
> 1. By layering, STRICT becomes subject to FILTER RET behaviors.
> 2. If we did want to layer them, it would be ideal to separate the 'upgrade'
>     decision from the access checks and make the layering path explicit.
>
> If you are running a legacy binary that uses STRICT in Docker, then I
> understand the goal, but there are userspace options.
>
> I think it's hard to want to open the door on changing STRICT without
> a good reason to work through all the implications that come with it:
> cross-checking every SECCOMP_MODE_FILTER reference, sorting
> out thread sync interactions, ...
>
> That said, this change could be streamlined and look for ways
> to minimize any potential implications.
>
> Am I missing something or overstating it?
>
> Thanks!

Thanks for the review - I'm currently working on a new version which
addresses some of the implementation
issues. On the semantics side:
The current version runs strict checks before filters. I think it
makes more sense to run filters, run strict checks, then return the
filter result (assuming strict checks were survived)
Since the strict checks logically work as another filter layer,
documentation says
> Synchronization will fail if another thread in the same process is in SECCOMP_MODE_STRICT
So refusing to sync threads which are using both modes seems the most
reasonable.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-12 22:37     ` clubby789
@ 2026-06-12 22:50       ` Andy Lutomirski
  0 siblings, 0 replies; 14+ messages in thread
From: Andy Lutomirski @ 2026-06-12 22:50 UTC (permalink / raw)
  To: clubby789
  Cc: Will Drewry, Kees Cook, Shuah Khan, linux-kernel, linux-kselftest,
	bpf, Jamie Hill-Daniel

On Fri, Jun 12, 2026 at 3:37 PM clubby789 <clubby789@gmail.com> wrote:
>
> On Fri, Jun 12, 2026 at 8:25 PM Will Drewry <wad@chromium.org> wrote:
> >
> > So I have two concerns here --
> >
> > 1. By layering, STRICT becomes subject to FILTER RET behaviors.
> > 2. If we did want to layer them, it would be ideal to separate the 'upgrade'
> >     decision from the access checks and make the layering path explicit.
> >
> > If you are running a legacy binary that uses STRICT in Docker, then I
> > understand the goal, but there are userspace options.
> >
> > I think it's hard to want to open the door on changing STRICT without
> > a good reason to work through all the implications that come with it:
> > cross-checking every SECCOMP_MODE_FILTER reference, sorting
> > out thread sync interactions, ...
> >
> > That said, this change could be streamlined and look for ways
> > to minimize any potential implications.
> >
> > Am I missing something or overstating it?
> >
> > Thanks!
>
> Thanks for the review - I'm currently working on a new version which
> addresses some of the implementation
> issues. On the semantics side:
> The current version runs strict checks before filters. I think it
> makes more sense to run filters, run strict checks, then return the
> filter result (assuming strict checks were survived)
> Since the strict checks logically work as another filter layer,
> documentation says
> > Synchronization will fail if another thread in the same process is in SECCOMP_MODE_STRICT
> So refusing to sync threads which are using both modes seems the most
> reasonable.


Can we take a moment to contemplate how filters compose?  The current rule is:

/*
 * All BPF programs must return a 32-bit value.
 * The bottom 16-bits are for optional return data.
 * The upper 16-bits are ordered from least permissive values to most,
 * as a signed value (so 0x8000000 is negative).
 *
 * The ordering ensures that a min_t() over composed return values always
 * selects the least permissive choice.
 */
#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
#define SECCOMP_RET_KILL_THREAD  0x00000000U /* kill the thread */
#define SECCOMP_RET_KILL         SECCOMP_RET_KILL_THREAD
#define SECCOMP_RET_TRAP         0x00030000U /* disallow and force a SIGSYS */
#define SECCOMP_RET_ERRNO        0x00050000U /* returns an errno */
#define SECCOMP_RET_USER_NOTIF   0x7fc00000U /* notifies userspace */
#define SECCOMP_RET_TRACE        0x7ff00000U /* pass to a tracer or disallow */
#define SECCOMP_RET_LOG          0x7ffc0000U /* allow after logging */
#define SECCOMP_RET_ALLOW        0x7fff0000U /* allow */

This has always bothered me.  In the absence of USER_NOTIF and TRACE,
fine, I guess -- we're choosing the least permissive, and this doesn't
seem too crazy.

But TRACE and USER_NOTIF make this very strange, especially as people
keep wanting, quite reasonably, to make USER_NOTIF fancier.  Shouldn't
the actual behavior be that each filter, starting from the innermost,
gets to reject or transform a system call, and the outer filters
should act on the result *after transformation* of the syscall?

For example, if I run a container and set some syscall foobar() to
SECCOMP_RET_ERROR in the container's policy, and the container them
runs a tool that sets foobar() to TRACE, then I think it would make a
lot more sense for the tracer get notified if the task calls foobar().
Or if the container sets foobar() to USER_NOTIF and tries to emulate
it, then it should emulate (and not get ERRORed because no actual
foobar() syscall has been attempted now that the inner filter was
evaluated) and then run the result of USER_NOTIF emulation (assuming
it tries to do a syscall) through the outer syscall?

And, however, this gets done, presumably STRICT would be a different
variant of KILL_PROCESS that does SIGKILL.

--Andy

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 1/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-12 22:37         ` Andy Lutomirski
@ 2026-06-12 22:58           ` clubby789
  0 siblings, 0 replies; 14+ messages in thread
From: clubby789 @ 2026-06-12 22:58 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Will Drewry, Kees Cook, Shuah Khan, linux-kernel, linux-kselftest,
	bpf, Jamie Hill-Daniel

On Fri, Jun 12, 2026 at 11:37 PM Andy Lutomirski <luto@amacapital.net> wrote:
> > The filter
> > itself is also rather complex (mostly due to needing to account for
> > BPF jump sizes, which differ
> > as different configs (uprobe, uretprobe, SECCOMP_ARCH_COMPAT) have
> > different logic., and I'd worry about
> > keeping logic synced.
>
> Perhaps you and your AI could elaborate?  What are these jump sizes?
>
> In any case, I think the actual issue is that the STRICT filter's
> failure case doesn't quite correspond to any of the FILTER actions.
> So maybe it's too complex to be worthwhile.
>
> --Andy

The filter as implemented looks approximately like

load arch
#ifdef SECCOMP_ARCH_COMPAT
    if arch == compat: goto check_compat
#endif
if arch != native arch: goto kill
load syscall nr
if syscall == {read/write/exit/sigreturn}: goto allow
#ifdef URETPROBE
    if syscall == uretprobe: goto allow
#endif
#ifdef UPROBE
    if syscall == uprobe: goto allow
#endif
ret kill
#ifdef SECCOMP_ARCH_COMPAT
    check_compat:
    if syscall == {read/write/exit/sigreturn}: goto allow
    ret kill
#endif
allow:
ret allow

The offsets from each instruction to 'allow' will differ based on the
presence of various options.
I came up with an approach using an enum for numbering each step like so:
> enum {
>   SF_LD_ARCH = 0,
> #ifdef SECCOMP_ARCH_COMPAT
>   SF_JEQ_COMPAT_ARCH,
> #endif
>   SF_JEQ_NATIVE_ARCH,
>  /* ... */
> }
> #define SF_REL(from, to) ((__u8)((to) - (from) - 1))
> static const struct sock_filter seccomp_strict_filter[] = {
>     [SF_LD_ARCH] = BPF_STMT(...),
> #ifdef SECCOMP_ARCH_COMPAT
>     [SF_JEQ_COMPAT_ARCH] = BPF_JUMP(..., SF_REL(SF_JEQ_COMPAT_ARCH, SF_LD_NR_COMPAT))
> #endif
>     /* ... */
> };

But I'm not convinced it's entirely readable/maintainable.

And just to be clear, I'm not using an AI personally; I was referring
to the Sashiko review bot, which I've now realised does not reply-all
with its reviews.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-05-26 15:32 [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Jamie Hill-Daniel
  2026-05-26 15:32 ` [PATCH RESEND 1/2] " Jamie Hill-Daniel
  2026-05-26 15:32 ` [PATCH RESEND 2/2] selftest: seccomp: Adjust test for using both `STRICT` and `FILTER` Jamie Hill-Daniel
@ 2026-06-13  4:14 ` Kees Cook
  2026-06-15 16:23   ` Jamie Hill-Daniel
  2 siblings, 1 reply; 14+ messages in thread
From: Kees Cook @ 2026-06-13  4:14 UTC (permalink / raw)
  To: Jamie Hill-Daniel
  Cc: Andy Lutomirski, Will Drewry, Shuah Khan, linux-kernel,
	linux-kselftest, bpf, Jamie Hill-Daniel

On Tue, May 26, 2026 at 04:32:14PM +0100, Jamie Hill-Daniel wrote:
> This patch adjusts the logic used by seccomp to allow applying both
> `SECCOMP_MODE_FILTER` and `SECCOMP_MODE_STRICT` to the same process.

Honestly, SECCOMP_MODE_STRICT is kinda deprecated. Nothing new should be
using it.

> Currently, once seccomp has been initialized, a process may not
> transition to a different mode (only add additional filters).
> This means that in container environments such as Docker, which by
> default runs with `SECCOMP_MODE_FILTER`, processes may not enable
> `SECCOMP_MODE_STRICT`. This is an obstacle to using applications
> requiring `SECCOMP_MODE_STRICT` in these environments, and requires
> disabling these security measures.

What applications do you have that need SECCOMP_MODE_STRICT and why
can't they be modified to use FILTER?

> When subsequently running secure computing checks, we run the strict
> checks followed by any installed filters.
> 
> Link: https://github.com/moby/moby/issues/42082

This doesn't show any particular application, just a demo program.

I'd *really* prefer to only add complexity to seccomp if it is
absolutely needed.

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-13  4:14 ` [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Kees Cook
@ 2026-06-15 16:23   ` Jamie Hill-Daniel
  2026-06-15 22:38     ` Kees Cook
  0 siblings, 1 reply; 14+ messages in thread
From: Jamie Hill-Daniel @ 2026-06-15 16:23 UTC (permalink / raw)
  To: Kees Cook
  Cc: Andy Lutomirski, Will Drewry, Shuah Khan, linux-kernel,
	linux-kselftest, bpf, Jamie Hill-Daniel

On Sat, Jun 13, 2026 at 5:14 AM Kees Cook <kees@kernel.org> wrote:
> On Tue, May 26, 2026 at 04:32:14PM +0100, Jamie Hill-Daniel wrote:
> > Link: https://github.com/moby/moby/issues/42082
>
> This doesn't show any particular application, just a demo program.
>
> I'd *really* prefer to only add complexity to seccomp if it is
> absolutely needed.

When I filed the original issue it was attempting a minimised
reproduction; I was trying to run some legacy binary in a container
that I unfortunately don't have the context for any more.
I've submitted another series that should hopefully address some of
the concerns raised here, including complexity.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-15 16:23   ` Jamie Hill-Daniel
@ 2026-06-15 22:38     ` Kees Cook
  2026-06-15 23:16       ` Kees Cook
  0 siblings, 1 reply; 14+ messages in thread
From: Kees Cook @ 2026-06-15 22:38 UTC (permalink / raw)
  To: Jamie Hill-Daniel
  Cc: Andy Lutomirski, Will Drewry, Shuah Khan, linux-kernel,
	linux-kselftest, bpf, Jamie Hill-Daniel

On Mon, Jun 15, 2026 at 05:23:53PM +0100, Jamie Hill-Daniel wrote:
> On Sat, Jun 13, 2026 at 5:14 AM Kees Cook <kees@kernel.org> wrote:
> > On Tue, May 26, 2026 at 04:32:14PM +0100, Jamie Hill-Daniel wrote:
> > > Link: https://github.com/moby/moby/issues/42082
> >
> > This doesn't show any particular application, just a demo program.
> >
> > I'd *really* prefer to only add complexity to seccomp if it is
> > absolutely needed.
> 
> When I filed the original issue it was attempting a minimised
> reproduction; I was trying to run some legacy binary in a container
> that I unfortunately don't have the context for any more.
> I've submitted another series that should hopefully address some of
> the concerns raised here, including complexity.

Right, I think I'd prefer the legacy binary be adjusted instead. And not
adding complexity to seccomp given the issue isn't actually a problem
any more. :)

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER`
  2026-06-15 22:38     ` Kees Cook
@ 2026-06-15 23:16       ` Kees Cook
  0 siblings, 0 replies; 14+ messages in thread
From: Kees Cook @ 2026-06-15 23:16 UTC (permalink / raw)
  To: Jamie Hill-Daniel
  Cc: Andy Lutomirski, Will Drewry, Shuah Khan, linux-kernel,
	linux-kselftest, bpf, Jamie Hill-Daniel

On Mon, Jun 15, 2026 at 03:38:35PM -0700, Kees Cook wrote:
> On Mon, Jun 15, 2026 at 05:23:53PM +0100, Jamie Hill-Daniel wrote:
> > On Sat, Jun 13, 2026 at 5:14 AM Kees Cook <kees@kernel.org> wrote:
> > > On Tue, May 26, 2026 at 04:32:14PM +0100, Jamie Hill-Daniel wrote:
> > > > Link: https://github.com/moby/moby/issues/42082
> > >
> > > This doesn't show any particular application, just a demo program.
> > >
> > > I'd *really* prefer to only add complexity to seccomp if it is
> > > absolutely needed.
> > 
> > When I filed the original issue it was attempting a minimised
> > reproduction; I was trying to run some legacy binary in a container
> > that I unfortunately don't have the context for any more.
> > I've submitted another series that should hopefully address some of
> > the concerns raised here, including complexity.
> 
> Right, I think I'd prefer the legacy binary be adjusted instead. And not
> adding complexity to seccomp given the issue isn't actually a problem
> any more. :)

And here's a wrapper, if there's no source for the binary:
https://github.com/kees/kernel-tools/blob/trunk/seccomp/strict_launcher.c

(This could probably be improved...)

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-06-15 23:16 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-26 15:32 [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Jamie Hill-Daniel
2026-05-26 15:32 ` [PATCH RESEND 1/2] " Jamie Hill-Daniel
2026-06-12 19:25   ` Will Drewry
2026-06-12 21:24     ` Andy Lutomirski
2026-06-12 22:01       ` clubby789
2026-06-12 22:37         ` Andy Lutomirski
2026-06-12 22:58           ` clubby789
2026-06-12 22:37     ` clubby789
2026-06-12 22:50       ` Andy Lutomirski
2026-05-26 15:32 ` [PATCH RESEND 2/2] selftest: seccomp: Adjust test for using both `STRICT` and `FILTER` Jamie Hill-Daniel
2026-06-13  4:14 ` [PATCH RESEND 0/2] seccomp: Allow using `SECCOMP_MODE_STRICT` with `SECCOMP_MODE_FILTER` Kees Cook
2026-06-15 16:23   ` Jamie Hill-Daniel
2026-06-15 22:38     ` Kees Cook
2026-06-15 23:16       ` Kees Cook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox