Discussion:
[PATCH] seccomp: allow BPF_MOD ALU instructions
(too old to reply)
Anton Protopopov
2020-03-16 16:36:46 UTC
Permalink
The BPF_MOD ALU instructions could be utilized by seccomp classic BPF filters,
but were missing from the explicit list of allowed calls since its introduction
in the original e2cfabdfd075 ("seccomp: add system call filtering using BPF")
commit. Add support for these instructions by adding them to the allowed list
in the seccomp_check_filter function.

Signed-off-by: Anton Protopopov <***@gmail.com>
---
kernel/seccomp.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index b6ea3dcb57bf..cae7561b44d4 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -206,6 +206,8 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
case BPF_ALU | BPF_MUL | BPF_X:
case BPF_ALU | BPF_DIV | BPF_K:
case BPF_ALU | BPF_DIV | BPF_X:
+ case BPF_ALU | BPF_MOD | BPF_K:
+ case BPF_ALU | BPF_MOD | BPF_X:
case BPF_ALU | BPF_AND | BPF_K:
case BPF_ALU | BPF_AND | BPF_X:
case BPF_ALU | BPF_OR | BPF_K:
--
2.19.1
Kees Cook
2020-03-16 21:23:59 UTC
Permalink
Post by Anton Protopopov
The BPF_MOD ALU instructions could be utilized by seccomp classic BPF filters,
but were missing from the explicit list of allowed calls since its introduction
in the original e2cfabdfd075 ("seccomp: add system call filtering using BPF")
commit. Add support for these instructions by adding them to the allowed list
in the seccomp_check_filter function.
This has been suggested in the past, but was deemed ultimately redundant:
https://lore.kernel.org/lkml/***@keescook/

Is there a strong reason it's needed?

Thanks!

-Kees
Post by Anton Protopopov
---
kernel/seccomp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index b6ea3dcb57bf..cae7561b44d4 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -206,6 +206,8 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
--
2.19.1
--
Kees Cook
Anton Protopopov
2020-03-16 22:17:34 UTC
Permalink
Post by Kees Cook
Post by Anton Protopopov
The BPF_MOD ALU instructions could be utilized by seccomp classic BPF filters,
but were missing from the explicit list of allowed calls since its introduction
in the original e2cfabdfd075 ("seccomp: add system call filtering using BPF")
commit. Add support for these instructions by adding them to the allowed list
in the seccomp_check_filter function.
Yeah, Paul told me this right after I submitted the patch.
Post by Kees Cook
Is there a strong reason it's needed?
I really don't have such a strong need in BPF_MOD, but let me tell why
I wanted to use it in the first place.

I've used this operation to speedup processing linear blacklist
filters. Namely, if you have a list of syscall numbers to blacklist,
you can do, say,

ldw [0]
mod #4
jeq #1, case1
jeq #1, case2
jeq #1, case3
case0:
...

and in every case to walk only a corresponding factor-list. In my case
I had a list of ~40 syscall numbers and after this change filter
executed in 17.25 instructions on average per syscall vs. 45
instructions for the linear filter (so this removes about 30
instructions penalty per every syscall). To replace "mod #4" I
actually used "and #3", but this obviously doesn't work for
non-power-of-two divisors. If I would use "mod 5", then it would give
me about 15.5 instructions on average.

Thanks,
Anton
Post by Kees Cook
Thanks!
-Kees
Post by Anton Protopopov
---
kernel/seccomp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index b6ea3dcb57bf..cae7561b44d4 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -206,6 +206,8 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
--
2.19.1
--
Kees Cook
Kees Cook
2020-03-17 20:20:54 UTC
Permalink
Post by Anton Protopopov
and in every case to walk only a corresponding factor-list. In my case
I had a list of ~40 syscall numbers and after this change filter
executed in 17.25 instructions on average per syscall vs. 45
instructions for the linear filter (so this removes about 30
instructions penalty per every syscall). To replace "mod #4" I
actually used "and #3", but this obviously doesn't work for
non-power-of-two divisors. If I would use "mod 5", then it would give
me about 15.5 instructions on average.
Gotcha. My real concern is with breaking the ABI here -- using BPF_MOD
would mean a process couldn't run on older kernels without some tricks
on the seccomp side.

Since the syscall list is static for a given filter, why not arrange it
as a binary search? That should get even better average instructions
as O(log n) instead of O(n).

Though frankly I've also been considering an ABI version bump for adding
a syscall bitmap feature: the vast majority of seccomp filters are just
binary yes/no across a list of syscalls. Only the special cases need
special handling (arg inspection, fd notification, etc). Then these
kinds of filters could run as O(1).
--
Kees Cook
Loading...