Add the current value of the PKRU register to data available for seccomp-bpf programs to work on. This allows filters based on the currently enabled protection keys. Cc: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Andy Lutomirski <luto@xxxxxxxxxxxxxx> Cc: Will Drewry <wad@xxxxxxxxxxxx> Cc: linux-api@xxxxxxxxxxxxxxx Signed-off-by: Michael Sammler <msammler@xxxxxxxxxxx> --- arch/mips/kernel/ptrace.c | 2 ++ arch/x86/entry/common.c | 2 ++ include/uapi/linux/seccomp.h | 4 ++++ kernel/seccomp.c | 2 ++ tools/testing/selftests/seccomp/seccomp_bpf.c | 4 +++- 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index e5ba56c0..07d55955 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -1277,6 +1277,8 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) for (i = 0; i < 6; i++) sd.args[i] = args[i]; sd.instruction_pointer = KSTK_EIP(current); + sd.pkru = 0; + sd.reserved = 0; ret = __secure_computing(&sd); if (ret == -1) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 3b2490b8..2afa85d7 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -98,6 +98,8 @@ static long syscall_trace_enter(struct pt_regs *regs) sd.arch = arch; sd.nr = regs->orig_ax; sd.instruction_pointer = regs->ip; + sd.pkru = read_pkru(); + sd.reserved = 0; #ifdef CONFIG_X86_64 if (arch == AUDIT_ARCH_X86_64) { sd.args[0] = regs->di; diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h index 9efc0e73..e8b9ecfc 100644 --- a/include/uapi/linux/seccomp.h +++ b/include/uapi/linux/seccomp.h @@ -52,12 +52,16 @@ * @instruction_pointer: at the time of the system call. * @args: up to 6 system call arguments always stored as 64-bit values * regardless of the architecture. + * @pkru: value of the pkru register + * @reserved: pad the structure to a multiple of eight bytes */ struct seccomp_data { int nr; __u32 arch; __u64 instruction_pointer; __u64 args[6]; + __u32 pkru; + __u32 reserved; }; #endif /* _UAPI_LINUX_SECCOMP_H */ diff --git a/kernel/seccomp.c b/kernel/seccomp.c index fd023ac2..b193c26e 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -91,6 +91,8 @@ static void populate_seccomp_data(struct seccomp_data *sd) sd->args[4] = args[4]; sd->args[5] = args[5]; sd->instruction_pointer = KSTK_EIP(task); + sd->pkru = read_pkru(); + sd->reserved = 0; } /** diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index e1473234..359249cd 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -732,7 +732,9 @@ TEST(KILL_process) TEST(arg_out_of_range) { struct sock_filter filter[] = { - BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(6)), + BPF_STMT(BPF_LD|BPF_W|BPF_ABS, + offsetof(struct seccomp_data, reserved) + + sizeof(__u32)), BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), }; struct sock_fprog prog = { -- 2.11.0