[RFC PATCH 8/9] um: Implement kernel side of SECCOMP based process handling

Johannes Berg johannes at sipsolutions.net
Thu Oct 10 05:12:17 PDT 2024


On Wed, 2024-09-25 at 22:32 +0200, Benjamin Berg wrote:
> 
> +	/*
> +	 * If in seccomp mode, install the SECCOMP filter and trigger a syscall.
> +	 * Otherwise set PTRACE_TRACEME and do a SIGSTOP.
> +	 */
> +	if (init_data.seccomp) {
> +		struct sock_filter filter[] = {
> +#if __BITS_PER_LONG > 32
> +			/* [0] Load upper 32bit of instruction pointer from seccomp_data */
> +			BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
> +				 (offsetof(struct seccomp_data, instruction_pointer) + 4)),
> +
> +			/* [1] Jump forward 3 instructions if the upper address is not identical */
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (init_data.stub_start) >> 32, 0, 3),
> +#endif
> +			/* [2] Load lower 32bit of instruction pointer from seccomp_data */
> +			BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
> +				 (offsetof(struct seccomp_data, instruction_pointer))),
> +
> +			/* [3] Mask out lower bits */
> +			BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xfffff000),
> +
> +			/* [4] Jump to [6] if the lower bits are not on the expected page */
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (init_data.stub_start) & 0xfffff000, 1, 0),
> +
> +			/* [5] Trap call, allow */
> +			BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),
> +
> +			/* [6,7] Check architecture */
> +			BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
> +				 offsetof(struct seccomp_data, arch)),
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,
> +				 UM_SECCOMP_ARCH_NATIVE, 1, 0),
> +
> +			/* [8] Kill (for architecture check) */
> +			BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
> +
> +			/* [9] Load syscall number */
> +			BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
> +				 offsetof(struct seccomp_data, nr)),
> +
> +			/* [10-14] Check against permitted syscalls */
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_futex,
> +				 5, 0),
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, STUB_MMAP_NR,
> +				 4, 0),
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_munmap,
> +				 3, 0),
> +#ifdef __i386__
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_set_thread_area,
> +				 2, 0),
> +#else
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_arch_prctl,
> +				 2, 0),
> +#endif
> +			BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_rt_sigreturn,
> +				 1, 0),
> +
> +			/* [15] Not one of the permitted syscalls */
> +			BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
> +
> +			/* [16] Permitted call for the stub */
> +			BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
> +		};

So not sure, but what else would you need per the cover letter's
description that it's not complete for the filter?


>   * skas/process.c
>   */
>  void wait_stub_done(int pid);
> +void wait_stub_done_seccomp(struct mm_id *mm_idp, int running, int wait_sigsys);
> +

nit: extra newline

Also the function can be static?

> +++ b/arch/um/os-Linux/skas/process.c
> @@ -1,9 +1,11 @@
>  // SPDX-License-Identifier: GPL-2.0
>  /*
> + * Copyright (C) 2021 Benjamin Berg <benjamin at sipsolutions.net>
>   * Copyright (C) 2015 Thomas Meyer (thomas at m3y3r.de)
>   * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
>   */
>  
> +#include <linux/kconfig.h>

Hmm. If this works, why do we have UML_CONFIG_64BIT? For ASM stuff?

But you also use "using_seccomp" so this shouldn't be needed, or you've
set it up very dangerously - that header file should probably include
this then, or whatever is needed?

Otherwise could end up with using_seccomp being used but not defined
properly per the ifdef, and just be statically 0 anyway?

>  #include <stdlib.h>
>  #include <stdbool.h>
>  #include <unistd.h>
> @@ -25,8 +27,11 @@
>  #include <registers.h>
>  #include <skas.h>
>  #include <sysdep/stub.h>
> +#include <sysdep/mcontext.h>
> +#include <linux/futex.h>
>  #include <linux/threads.h>
>  #include <timetravel.h>
> +#include <asm-generic/rwonce.h>
>  #include "../internal.h"
>  
>  int is_skas_winch(int pid, int fd, void *data)
> @@ -142,6 +147,74 @@ void wait_stub_done(int pid)
>  	fatal_sigsegv();
>  }
>  
> +#ifdef CONFIG_UML_SECCOMP

Also not sure you need the ifdef at all?

> +void wait_stub_done_seccomp(struct mm_id *mm_idp, int running, int wait_sigsys)

This could be static and then it doesn't matter to have the ifdef?

> -		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
> -		if (n < 0) {
> +	if (using_seccomp) {
> +		wait_stub_done_seccomp(mm_id, 1, 1);

Also this builds because you declare the function but don't define it,
but you already rely on the optimisation throwing it out anyway.

> +#ifdef CONFIG_X86_32
> +		extern int have_fpx_regs;
> +
> +		/*
> +		 * FIXME: This is wrong, but the non-FPX layout is closer to
> +		 * what the mcontext presents to us. So, for all intents and
> +		 * purposes we'll behave mostly correct if we do this.

"correctly"

but you don't care anyway since seccomp is only for 64-bit?

johannes



More information about the linux-um mailing list