[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251201122406.105045-4-aleksandr.mikhalitsyn@canonical.com>
Date: Mon, 1 Dec 2025 13:24:00 +0100
From: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@...onical.com>
To: kees@...nel.org
Cc: linux-kernel@...r.kernel.org,
bpf@...r.kernel.org,
Andy Lutomirski <luto@...capital.net>,
Will Drewry <wad@...omium.org>,
Jonathan Corbet <corbet@....net>,
Shuah Khan <shuah@...nel.org>,
Tycho Andersen <tycho@...ho.pizza>,
Andrei Vagin <avagin@...il.com>,
Christian Brauner <brauner@...nel.org>,
Stéphane Graber <stgraber@...raber.org>,
Alexander Mikhalitsyn <aleksandr.mikhalitsyn@...onical.com>
Subject: [PATCH v1 3/6] seccomp: limit number of listeners in seccomp tree
We need to limit number of listeners in seccomp tree to
MAX_LISTENERS_PER_PATH, because we don't want to use dynamic
memory allocations in a very hot __seccomp_filter() function
and we use preallocated static array on the stack.
Also, let's return ELOOP to userspace if it attempts to install
more than MAX_LISTENERS_PER_PATH listeners, instead of ENOMEM as
we do when userspace hits the limit of cBPF instructions.
This will make uAPI a bit more convenient.
Notice, that has_duplicate_listener() check is still in place, so this
change is a preparational.
Cc: linux-kernel@...r.kernel.org
Cc: bpf@...r.kernel.org
Cc: Kees Cook <kees@...nel.org>
Cc: Andy Lutomirski <luto@...capital.net>
Cc: Will Drewry <wad@...omium.org>
Cc: Jonathan Corbet <corbet@....net>
Cc: Shuah Khan <shuah@...nel.org>
Cc: Tycho Andersen <tycho@...ho.pizza>
Cc: Andrei Vagin <avagin@...il.com>
Cc: Christian Brauner <brauner@...nel.org>
Cc: Stéphane Graber <stgraber@...raber.org>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@...onical.com>
---
kernel/seccomp.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index c9a1062a53bd..ded3f6a6430b 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -931,17 +931,25 @@ static long seccomp_attach_filter(unsigned int flags,
struct seccomp_filter *filter)
{
unsigned long total_insns;
+ unsigned char total_listeners;
struct seccomp_filter *walker;
assert_spin_locked(¤t->sighand->siglock);
- /* Validate resulting filter length. */
+ /* Validate resulting filter length and number of nested listeners. */
total_insns = filter->prog->len;
- for (walker = current->seccomp.filter; walker; walker = walker->prev)
+ total_listeners = filter->notif ? 1 : 0;
+ for (walker = current->seccomp.filter; walker; walker = walker->prev) {
total_insns += walker->prog->len + 4; /* 4 instr penalty */
+ total_listeners += walker->notif ? 1 : 0;
+ }
+
if (total_insns > MAX_INSNS_PER_PATH)
return -ENOMEM;
+ if (total_listeners > MAX_LISTENERS_PER_PATH)
+ return -ELOOP;
+
/* If thread sync has been requested, check that it is possible. */
if (flags & SECCOMP_FILTER_FLAG_TSYNC) {
int ret;
--
2.43.0
Powered by blists - more mailing lists