Syscall User Dispatch is presently built under CONFIG_GENERIC_SYSCALL and cannot be disabled independently. Add CONFIG_SYSCALL_USER_DISPATCH to make it an optional feature.
Unified · Split
| @@ -114,6 +114,16 @@ config GENERIC_ENTRY · 113 unmodified lines | |||
| 114 | select GENERIC_IRQ_ENTRY | 114 | select GENERIC_IRQ_ENTRY |
| 115 | select GENERIC_SYSCALL | 115 | select GENERIC_SYSCALL |
| 116 | 116 | ||
| 117 | config SYSCALL_USER_DISPATCH | ||
| 118 | bool "Syscall User Dispatch" | ||
| 119 | depends on GENERIC_ENTRY | ||
| 120 | default y | ||
| 121 | help | ||
| 122 | Syscall User Dispatch lets a thread have its own system calls | ||
| 123 | intercepted and redirected to a userspace signal handler based | ||
| 124 | on a prctl() configured instruction pointer range. | ||
| 125 | If unsure, say Y. | ||
| 126 | |||
| 117 | config KPROBES | 127 | config KPROBES |
| 118 | bool "Kprobes" | 128 | bool "Kprobes" |
| 119 | depends on HAVE_KPROBES | 129 | depends on HAVE_KPROBES |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/resume_user_mode.h> | 9 | #include <linux/resume_user_mode.h> |
| 10 | #include <linux/seccomp.h> | 10 | #include <linux/seccomp.h> |
| 11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
| 12 | #include <linux/syscall_user_dispatch.h> | ||
| 12 | 13 | ||
| 13 | #include <asm/entry-common.h> | 14 | #include <asm/entry-common.h> |
| 14 | #include <asm/syscall.h> | 15 | #include <asm/syscall.h> |
| @@ -55,7 +56,6 @@ static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs · 40 unmodified lines | |||
| 55 | } | 56 | } |
| 56 | #endif | 57 | #endif |
| 57 | 58 | ||
| 58 | bool syscall_user_dispatch(struct pt_regs *regs); | ||
| 59 | long trace_syscall_enter(struct pt_regs *regs, long syscall); | 59 | long trace_syscall_enter(struct pt_regs *regs, long syscall); |
| 60 | void trace_syscall_exit(struct pt_regs *regs, long ret); | 60 | void trace_syscall_exit(struct pt_regs *regs, long ret); |
| 61 | 61 | ||
| @@ -232,10 +232,8 @@ static __always_inline void syscall_exit_work(struct pt_regs *regs, unsigned lon · 170 unmodified lines | |||
| 232 | * of these syscalls is unknown. | 232 | * of these syscalls is unknown. |
| 233 | */ | 233 | */ |
| 234 | if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) { | 234 | if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) { |
| 235 | if (unlikely(current->syscall_dispatch.on_dispatch)) { | 235 | if (syscall_user_dispatch_clear_on_dispatch()) |
| 236 | current->syscall_dispatch.on_dispatch = false; | ||
| 237 | return; | 236 | return; |
| 238 | } | ||
| 239 | } | 237 | } |
| 240 | 238 | ||
| 241 | audit_syscall_exit(regs); | 239 | audit_syscall_exit(regs); |
| @@ -6,9 +6,23 @@ · 5 unmodified lines | |||
| 6 | #define _SYSCALL_USER_DISPATCH_H | 6 | #define _SYSCALL_USER_DISPATCH_H |
| 7 | 7 | ||
| 8 | #include <linux/thread_info.h> | 8 | #include <linux/thread_info.h> |
| 9 | #include <linux/sched.h> | ||
| 9 | #include <linux/syscall_user_dispatch_types.h> | 10 | #include <linux/syscall_user_dispatch_types.h> |
| 10 | 11 | ||
| 11 | #ifdef CONFIG_GENERIC_ENTRY | 12 | struct pt_regs; |
| 13 | |||
| 14 | #ifdef CONFIG_SYSCALL_USER_DISPATCH | ||
| 15 | |||
| 16 | bool syscall_user_dispatch(struct pt_regs *regs); | ||
| 17 | |||
| 18 | static __always_inline bool syscall_user_dispatch_clear_on_dispatch(void) | ||
| 19 | { | ||
| 20 | if (likely(!current->syscall_dispatch.on_dispatch)) | ||
| 21 | return false; | ||
| 22 | |||
| 23 | current->syscall_dispatch.on_dispatch = false; | ||
| 24 | return true; | ||
| 25 | } | ||
| 12 | 26 | ||
| 13 | int set_syscall_user_dispatch(unsigned long mode, unsigned long offset, | 27 | int set_syscall_user_dispatch(unsigned long mode, unsigned long offset, |
| 14 | unsigned long len, char __user *selector); | 28 | unsigned long len, char __user *selector); |
| @@ -24,6 +38,16 @@ int syscall_user_dispatch_set_config(struct task_struct *task, unsigned long siz · 9 unmodified lines | |||
| 24 | 38 | ||
| 25 | #else | 39 | #else |
| 26 | 40 | ||
| 41 | static __always_inline bool syscall_user_dispatch(struct pt_regs *regs) | ||
| 42 | { | ||
| 43 | return false; | ||
| 44 | } | ||
| 45 | |||
| 46 | static __always_inline bool syscall_user_dispatch_clear_on_dispatch(void) | ||
| 47 | { | ||
| 48 | return false; | ||
| 49 | } | ||
| 50 | |||
| 27 | static inline int set_syscall_user_dispatch(unsigned long mode, unsigned long offset, | 51 | static inline int set_syscall_user_dispatch(unsigned long mode, unsigned long offset, |
| 28 | unsigned long len, char __user *selector) | 52 | unsigned long len, char __user *selector) |
| 29 | { | 53 | { |
| @@ -46,6 +70,6 @@ static inline int syscall_user_dispatch_set_config(struct task_struct *task, · 16 unmodified lines | |||
| 46 | return -EINVAL; | 70 | return -EINVAL; |
| 47 | } | 71 | } |
| 48 | 72 | ||
| 49 | #endif /* CONFIG_GENERIC_ENTRY */ | 73 | #endif /* CONFIG_SYSCALL_USER_DISPATCH */ |
| 50 | 74 | ||
| 51 | #endif /* _SYSCALL_USER_DISPATCH_H */ | 75 | #endif /* _SYSCALL_USER_DISPATCH_H */ |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | 6 | ||
| 7 | #ifdef CONFIG_GENERIC_ENTRY | 7 | #ifdef CONFIG_SYSCALL_USER_DISPATCH |
| 8 | 8 | ||
| 9 | struct syscall_user_dispatch { | 9 | struct syscall_user_dispatch { |
| 10 | char __user *selector; | 10 | char __user *selector; |
| @@ -13,5 +13,6 @@ CFLAGS_REMOVE_common.o = -fstack-protector -fstack-protector-strong · 12 unmodified lines | |||
| 13 | CFLAGS_common.o += -fno-stack-protector | 13 | CFLAGS_common.o += -fno-stack-protector |
| 14 | 14 | ||
| 15 | obj-$(CONFIG_GENERIC_IRQ_ENTRY) += common.o | 15 | obj-$(CONFIG_GENERIC_IRQ_ENTRY) += common.o |
| 16 | obj-$(CONFIG_GENERIC_SYSCALL) += syscall-common.o syscall_user_dispatch.o | 16 | obj-$(CONFIG_GENERIC_SYSCALL) += syscall-common.o |
| 17 | obj-$(CONFIG_SYSCALL_USER_DISPATCH) += syscall_user_dispatch.o | ||
| 17 | obj-$(CONFIG_VIRT_XFER_TO_GUEST_WORK) += virt.o | 18 | obj-$(CONFIG_VIRT_XFER_TO_GUEST_WORK) += virt.o |
| @@ -1 +1 @@ | |||
| 1 | CONFIG_GENERIC_ENTRY=y | 1 | CONFIG_SYSCALL_USER_DISPATCH=y |