Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'core_urgent_for_v5.11_rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull syscall entry fixes from Borislav Petkov:

- For syscall user dispatch, separate prctl operation from syscall
redirection range specification before the API has been made official
in 5.11.

- Ensure tasks using the generic syscall code do trap after returning
from a syscall when single-stepping is requested.

* tag 'core_urgent_for_v5.11_rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
entry: Use different define for selector variable in SUD
entry: Ensure trap after single-step on system call return

+33 -27
+2 -2
Documentation/admin-guide/syscall-user-dispatch.rst
··· 70 70 [selector] is a pointer to a char-sized region in the process memory 71 71 region, that provides a quick way to enable disable syscall redirection 72 72 thread-wide, without the need to invoke the kernel directly. selector 73 - can be set to PR_SYS_DISPATCH_ON or PR_SYS_DISPATCH_OFF. Any other 74 - value should terminate the program with a SIGSYS. 73 + can be set to SYSCALL_DISPATCH_FILTER_ALLOW or SYSCALL_DISPATCH_FILTER_BLOCK. 74 + Any other value should terminate the program with a SIGSYS. 75 75 76 76 Security Notes 77 77 --------------
-2
arch/x86/include/asm/entry-common.h
··· 43 43 } 44 44 #define arch_check_user_regs arch_check_user_regs 45 45 46 - #define ARCH_SYSCALL_EXIT_WORK (_TIF_SINGLESTEP) 47 - 48 46 static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs, 49 47 unsigned long ti_work) 50 48 {
+8 -2
arch/x86/kernel/step.c
··· 127 127 regs->flags |= X86_EFLAGS_TF; 128 128 129 129 /* 130 - * Always set TIF_SINGLESTEP - this guarantees that 131 - * we single-step system calls etc.. This will also 130 + * Always set TIF_SINGLESTEP. This will also 132 131 * cause us to set TF when returning to user mode. 133 132 */ 134 133 set_tsk_thread_flag(child, TIF_SINGLESTEP); 134 + 135 + /* 136 + * Ensure that a trap is triggered once stepping out of a system 137 + * call prior to executing any user instruction. 138 + */ 139 + set_task_syscall_work(child, SYSCALL_EXIT_TRAP); 135 140 136 141 oflags = regs->flags; 137 142 ··· 235 230 236 231 /* Always clear TIF_SINGLESTEP... */ 237 232 clear_tsk_thread_flag(child, TIF_SINGLESTEP); 233 + clear_task_syscall_work(child, SYSCALL_EXIT_TRAP); 238 234 239 235 /* But touch TF only if it was set by us.. */ 240 236 if (test_and_clear_tsk_thread_flag(child, TIF_FORCED_TF))
+1
include/linux/entry-common.h
··· 46 46 SYSCALL_WORK_SYSCALL_TRACE | \ 47 47 SYSCALL_WORK_SYSCALL_AUDIT | \ 48 48 SYSCALL_WORK_SYSCALL_USER_DISPATCH | \ 49 + SYSCALL_WORK_SYSCALL_EXIT_TRAP | \ 49 50 ARCH_SYSCALL_WORK_EXIT) 50 51 51 52 /*
+2
include/linux/thread_info.h
··· 43 43 SYSCALL_WORK_BIT_SYSCALL_EMU, 44 44 SYSCALL_WORK_BIT_SYSCALL_AUDIT, 45 45 SYSCALL_WORK_BIT_SYSCALL_USER_DISPATCH, 46 + SYSCALL_WORK_BIT_SYSCALL_EXIT_TRAP, 46 47 }; 47 48 48 49 #define SYSCALL_WORK_SECCOMP BIT(SYSCALL_WORK_BIT_SECCOMP) ··· 52 51 #define SYSCALL_WORK_SYSCALL_EMU BIT(SYSCALL_WORK_BIT_SYSCALL_EMU) 53 52 #define SYSCALL_WORK_SYSCALL_AUDIT BIT(SYSCALL_WORK_BIT_SYSCALL_AUDIT) 54 53 #define SYSCALL_WORK_SYSCALL_USER_DISPATCH BIT(SYSCALL_WORK_BIT_SYSCALL_USER_DISPATCH) 54 + #define SYSCALL_WORK_SYSCALL_EXIT_TRAP BIT(SYSCALL_WORK_BIT_SYSCALL_EXIT_TRAP) 55 55 #endif 56 56 57 57 #include <asm/thread_info.h>
+3
include/uapi/linux/prctl.h
··· 251 251 #define PR_SET_SYSCALL_USER_DISPATCH 59 252 252 # define PR_SYS_DISPATCH_OFF 0 253 253 # define PR_SYS_DISPATCH_ON 1 254 + /* The control values for the user space selector when dispatch is enabled */ 255 + # define SYSCALL_DISPATCH_FILTER_ALLOW 0 256 + # define SYSCALL_DISPATCH_FILTER_BLOCK 1 254 257 255 258 #endif /* _LINUX_PRCTL_H */
+2 -10
kernel/entry/common.c
··· 209 209 lockdep_sys_exit(); 210 210 } 211 211 212 - #ifndef _TIF_SINGLESTEP 213 - static inline bool report_single_step(unsigned long work) 214 - { 215 - return false; 216 - } 217 - #else 218 212 /* 219 213 * If SYSCALL_EMU is set, then the only reason to report is when 220 - * TIF_SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall 214 + * SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall 221 215 * instruction has been already reported in syscall_enter_from_user_mode(). 222 216 */ 223 217 static inline bool report_single_step(unsigned long work) ··· 219 225 if (work & SYSCALL_WORK_SYSCALL_EMU) 220 226 return false; 221 227 222 - return !!(current_thread_info()->flags & _TIF_SINGLESTEP); 228 + return work & SYSCALL_WORK_SYSCALL_EXIT_TRAP; 223 229 } 224 - #endif 225 - 226 230 227 231 static void syscall_exit_work(struct pt_regs *regs, unsigned long work) 228 232 {
+2 -2
kernel/entry/syscall_user_dispatch.c
··· 50 50 if (unlikely(__get_user(state, sd->selector))) 51 51 do_exit(SIGSEGV); 52 52 53 - if (likely(state == PR_SYS_DISPATCH_OFF)) 53 + if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW)) 54 54 return false; 55 55 56 - if (state != PR_SYS_DISPATCH_ON) 56 + if (state != SYSCALL_DISPATCH_FILTER_BLOCK) 57 57 do_exit(SIGSYS); 58 58 } 59 59
+5 -3
tools/testing/selftests/syscall_user_dispatch/sud_benchmark.c
··· 22 22 # define PR_SET_SYSCALL_USER_DISPATCH 59 23 23 # define PR_SYS_DISPATCH_OFF 0 24 24 # define PR_SYS_DISPATCH_ON 1 25 + # define SYSCALL_DISPATCH_FILTER_ALLOW 0 26 + # define SYSCALL_DISPATCH_FILTER_BLOCK 1 25 27 #endif 26 28 27 29 #ifdef __NR_syscalls ··· 57 55 unsigned long native_call_count = 0; 58 56 59 57 char selector; 60 - #define SYSCALL_BLOCK (selector = PR_SYS_DISPATCH_ON) 61 - #define SYSCALL_UNBLOCK (selector = PR_SYS_DISPATCH_OFF) 58 + #define SYSCALL_BLOCK (selector = SYSCALL_DISPATCH_FILTER_BLOCK) 59 + #define SYSCALL_UNBLOCK (selector = SYSCALL_DISPATCH_FILTER_ALLOW) 62 60 63 61 #define CALIBRATION_STEP 100000 64 62 #define CALIBRATE_TO_SECS 5 ··· 172 170 syscall(MAGIC_SYSCALL_1); 173 171 174 172 #ifdef TEST_BLOCKED_RETURN 175 - if (selector == PR_SYS_DISPATCH_OFF) { 173 + if (selector == SYSCALL_DISPATCH_FILTER_ALLOW) { 176 174 fprintf(stderr, "Failed to return with selector blocked.\n"); 177 175 exit(-1); 178 176 }
+8 -6
tools/testing/selftests/syscall_user_dispatch/sud_test.c
··· 18 18 # define PR_SET_SYSCALL_USER_DISPATCH 59 19 19 # define PR_SYS_DISPATCH_OFF 0 20 20 # define PR_SYS_DISPATCH_ON 1 21 + # define SYSCALL_DISPATCH_FILTER_ALLOW 0 22 + # define SYSCALL_DISPATCH_FILTER_BLOCK 1 21 23 #endif 22 24 23 25 #ifndef SYS_USER_DISPATCH ··· 32 30 # define MAGIC_SYSCALL_1 (0xff00) /* Bad Linux syscall number */ 33 31 #endif 34 32 35 - #define SYSCALL_DISPATCH_ON(x) ((x) = 1) 36 - #define SYSCALL_DISPATCH_OFF(x) ((x) = 0) 33 + #define SYSCALL_DISPATCH_ON(x) ((x) = SYSCALL_DISPATCH_FILTER_BLOCK) 34 + #define SYSCALL_DISPATCH_OFF(x) ((x) = SYSCALL_DISPATCH_FILTER_ALLOW) 37 35 38 36 /* Test Summary: 39 37 * ··· 58 56 59 57 TEST_SIGNAL(dispatch_trigger_sigsys, SIGSYS) 60 58 { 61 - char sel = 0; 59 + char sel = SYSCALL_DISPATCH_FILTER_ALLOW; 62 60 struct sysinfo info; 63 61 int ret; 64 62 ··· 81 79 82 80 TEST(bad_prctl_param) 83 81 { 84 - char sel = 0; 82 + char sel = SYSCALL_DISPATCH_FILTER_ALLOW; 85 83 int op; 86 84 87 85 /* Invalid op */ ··· 222 220 sigset_t mask; 223 221 struct sysinfo info; 224 222 225 - glob_sel = 0; 223 + glob_sel = SYSCALL_DISPATCH_FILTER_ALLOW; 226 224 nr_syscalls_emulated = 0; 227 225 si_code = 0; 228 226 si_errno = 0; ··· 290 288 { 291 289 int ret = 0; 292 290 struct sysinfo info; 293 - char sel = 0; 291 + char sel = SYSCALL_DISPATCH_FILTER_ALLOW; 294 292 295 293 /* 296 294 * Instead of calculating libc addresses; allow the entire