]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
enosys: remove long jumps from BPF
authorThomas Weißschuh <thomas@t-8ch.de>
Thu, 4 May 2023 22:38:11 +0000 (00:38 +0200)
committerThomas Weißschuh <thomas@t-8ch.de>
Tue, 16 May 2023 20:44:50 +0000 (22:44 +0200)
BPF encodes the jump distance in a uint8_t. To avoid overflows of this
value reorganize the generated bytecode to work without long jumps.

Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
misc-utils/enosys.c

index 83e1847ff50c6469d4a8652b97ee1a56fc1b273f..79f57b255379c4d39222aa09d6b9181d7b0c7de2 100644 (file)
@@ -139,7 +139,7 @@ int main(int argc, char **argv)
        if (optind >= argc)
                errtryhelp(EXIT_FAILURE);
 
-#define N_FILTERS (ARRAY_SIZE(syscalls) + 6)
+#define N_FILTERS (ARRAY_SIZE(syscalls) * 2 + 5)
 
        struct sock_filter filter[N_FILTERS] = {
                [0] = BPF_STMT(BPF_LD | BPF_W | BPF_ABS, syscall_arch),
@@ -147,19 +147,21 @@ int main(int argc, char **argv)
                [2] = BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),
                [3] = BPF_STMT(BPF_LD | BPF_W | BPF_ABS, syscall_nr),
 
-               [N_FILTERS - 2] = BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-               [N_FILTERS - 1] = BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | ENOSYS),
+               [N_FILTERS - 1] = BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
        };
+       static_assert(ARRAY_SIZE(filter) <= BPF_MAXINSNS, "bpf filter too big");
 
        for (i = 0; i < ARRAY_SIZE(syscalls); i++) {
-               if (blocked_syscalls[i]) {
-                       filter[i + 4] = (struct sock_filter) BPF_JUMP(
-                                               BPF_JMP | BPF_JEQ | BPF_K,
-                                               syscalls[i].number,
-                                               N_FILTERS - 3 - i, 0);
-               } else {
-                       filter[i + 4] = UL_BPF_NOP;
-               }
+               struct sock_filter *f = &filter[4 + i * 2];
+
+               *f = (struct sock_filter) BPF_JUMP(
+                               BPF_JMP | BPF_JEQ | BPF_K,
+                               syscalls[i].number,
+                               0, 1);
+               *(f + 1) = blocked_syscalls[i]
+                       ? (struct sock_filter) BPF_STMT(
+                                       BPF_RET | BPF_K, SECCOMP_RET_ERRNO | ENOSYS)
+                       : UL_BPF_NOP;
        }
 
        struct sock_fprog prog = {