Pull exit cleanups from Eric Biederman: "In preparation of doing something about PTRACE_EVENT_EXIT I have started cleaning up various pieces of code related to do_exit. Most of that code I did not manage to get tested and reviewed before the merge window opened but a handful of very useful cleanups are ready to be merged. The first change is simply the removal of the bdflush system call. The code has now been disabled long enough that even the oldest userspace working userspace setups anyone can find to test are fine with the bdflush system call being removed. Changing m68k fsp040_die to use force_sigsegv(SIGSEGV) instead of calling do_exit directly is interesting only in that it is nearly the most difficult of the incorrect uses of do_exit to remove. The change to the seccomp code to simply send a signal instead of calling do_coredump directly is a very nice little cleanup made possible by realizing the existing signal sending helpers were missing a little bit of functionality that is easy to provide" * 'exit-cleanups-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: signal/seccomp: Dump core when there is only one live thread signal/seccomp: Refactor seccomp signal and coredump generation signal/m68k: Use force_sigsegv(SIGSEGV) in fpsp040_die exit/bdflush: Remove the deprecated bdflush system call
Showing the changes to kernel (3 of 25 files). Show all
Unified · Split
| @@ -922,30 +922,6 @@ void get_seccomp_filter(struct task_struct *tsk) · 921 unmodified lines | |||
| 922 | refcount_inc(&orig->users); | 922 | refcount_inc(&orig->users); |
| 923 | } | 923 | } |
| 924 | 924 | ||
| 925 | static void seccomp_init_siginfo(kernel_siginfo_t *info, int syscall, int reason) | ||
| 926 | { | ||
| 927 | clear_siginfo(info); | ||
| 928 | info->si_signo = SIGSYS; | ||
| 929 | info->si_code = SYS_SECCOMP; | ||
| 930 | info->si_call_addr = (void __user *)KSTK_EIP(current); | ||
| 931 | info->si_errno = reason; | ||
| 932 | info->si_arch = syscall_get_arch(current); | ||
| 933 | info->si_syscall = syscall; | ||
| 934 | } | ||
| 935 | |||
| 936 | /** | ||
| 937 | * seccomp_send_sigsys - signals the task to allow in-process syscall emulation | ||
| 938 | * @syscall: syscall number to send to userland | ||
| 939 | * @reason: filter-supplied reason code to send to userland (via si_errno) | ||
| 940 | * | ||
| 941 | * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info. | ||
| 942 | */ | ||
| 943 | static void seccomp_send_sigsys(int syscall, int reason) | ||
| 944 | { | ||
| 945 | struct kernel_siginfo info; | ||
| 946 | seccomp_init_siginfo(&info, syscall, reason); | ||
| 947 | force_sig_info(&info); | ||
| 948 | } | ||
| 949 | #endif /* CONFIG_SECCOMP_FILTER */ | 925 | #endif /* CONFIG_SECCOMP_FILTER */ |
| 950 | 926 | ||
| 951 | /* For use with seccomp_actions_logged */ | 927 | /* For use with seccomp_actions_logged */ |
| @@ -1218,7 +1194,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, · 266 unmodified lines | |||
| 1218 | /* Show the handler the original registers. */ | 1194 | /* Show the handler the original registers. */ |
| 1219 | syscall_rollback(current, current_pt_regs()); | 1195 | syscall_rollback(current, current_pt_regs()); |
| 1220 | /* Let the filter pass back 16 bits of data. */ | 1196 | /* Let the filter pass back 16 bits of data. */ |
| 1221 | seccomp_send_sigsys(this_syscall, data); | 1197 | force_sig_seccomp(this_syscall, data, false); |
| 1222 | goto skip; | 1198 | goto skip; |
| 1223 | 1199 | ||
| 1224 | case SECCOMP_RET_TRACE: | 1200 | case SECCOMP_RET_TRACE: |
| @@ -1288,19 +1264,15 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, · 63 unmodified lines | |||
| 1288 | seccomp_log(this_syscall, SIGSYS, action, true); | 1264 | seccomp_log(this_syscall, SIGSYS, action, true); |
| 1289 | /* Dump core only if this is the last remaining thread. */ | 1265 | /* Dump core only if this is the last remaining thread. */ |
| 1290 | if (action != SECCOMP_RET_KILL_THREAD || | 1266 | if (action != SECCOMP_RET_KILL_THREAD || |
| 1291 | get_nr_threads(current) == 1) { | 1267 | (atomic_read(¤t->signal->live) == 1)) { |
| 1292 | kernel_siginfo_t info; | ||
| 1293 | |||
| 1294 | /* Show the original registers in the dump. */ | 1268 | /* Show the original registers in the dump. */ |
| 1295 | syscall_rollback(current, current_pt_regs()); | 1269 | syscall_rollback(current, current_pt_regs()); |
| 1296 | /* Trigger a manual coredump since do_exit skips it. */ | 1270 | /* Trigger a coredump with SIGSYS */ |
| 1297 | seccomp_init_siginfo(&info, this_syscall, data); | 1271 | force_sig_seccomp(this_syscall, data, true); |
| 1298 | do_coredump(&info); | 1272 | } else { |
| 1299 | } | ||
| 1300 | if (action == SECCOMP_RET_KILL_THREAD) | ||
| 1301 | do_exit(SIGSYS); | 1273 | do_exit(SIGSYS); |
| 1302 | else | 1274 | } |
| 1303 | do_group_exit(SIGSYS); | 1275 | return -1; /* skip the syscall go directly to signal handling */ |
| 1304 | } | 1276 | } |
| 1305 | 1277 | ||
| 1306 | unreachable(); | 1278 | unreachable(); |
| @@ -54,6 +54,7 @@ · 53 unmodified lines | |||
| 54 | #include <asm/unistd.h> | 54 | #include <asm/unistd.h> |
| 55 | #include <asm/siginfo.h> | 55 | #include <asm/siginfo.h> |
| 56 | #include <asm/cacheflush.h> | 56 | #include <asm/cacheflush.h> |
| 57 | #include <asm/syscall.h> /* for syscall_get_* */ | ||
| 57 | 58 | ||
| 58 | /* | 59 | /* |
| 59 | * SLAB caches for signal bits. | 60 | * SLAB caches for signal bits. |
| @@ -1322,7 +1323,7 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p · 1262 unmodified lines | |||
| 1322 | * that is why we also clear SIGNAL_UNKILLABLE. | 1323 | * that is why we also clear SIGNAL_UNKILLABLE. |
| 1323 | */ | 1324 | */ |
| 1324 | static int | 1325 | static int |
| 1325 | force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t) | 1326 | force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl) |
| 1326 | { | 1327 | { |
| 1327 | unsigned long int flags; | 1328 | unsigned long int flags; |
| 1328 | int ret, blocked, ignored; | 1329 | int ret, blocked, ignored; |
| @@ -1333,7 +1334,7 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t) · 4 unmodified lines | |||
| 1333 | action = &t->sighand->action[sig-1]; | 1334 | action = &t->sighand->action[sig-1]; |
| 1334 | ignored = action->sa.sa_handler == SIG_IGN; | 1335 | ignored = action->sa.sa_handler == SIG_IGN; |
| 1335 | blocked = sigismember(&t->blocked, sig); | 1336 | blocked = sigismember(&t->blocked, sig); |
| 1336 | if (blocked || ignored) { | 1337 | if (blocked || ignored || sigdfl) { |
| 1337 | action->sa.sa_handler = SIG_DFL; | 1338 | action->sa.sa_handler = SIG_DFL; |
| 1338 | if (blocked) { | 1339 | if (blocked) { |
| 1339 | sigdelset(&t->blocked, sig); | 1340 | sigdelset(&t->blocked, sig); |
| @@ -1354,7 +1355,7 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t) · 14 unmodified lines | |||
| 1354 | 1355 | ||
| 1355 | int force_sig_info(struct kernel_siginfo *info) | 1356 | int force_sig_info(struct kernel_siginfo *info) |
| 1356 | { | 1357 | { |
| 1357 | return force_sig_info_to_task(info, current); | 1358 | return force_sig_info_to_task(info, current, false); |
| 1358 | } | 1359 | } |
| 1359 | 1360 | ||
| 1360 | /* | 1361 | /* |
| @@ -1696,7 +1697,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr · 335 unmodified lines | |||
| 1696 | info.si_flags = flags; | 1697 | info.si_flags = flags; |
| 1697 | info.si_isr = isr; | 1698 | info.si_isr = isr; |
| 1698 | #endif | 1699 | #endif |
| 1699 | return force_sig_info_to_task(&info, t); | 1700 | return force_sig_info_to_task(&info, t, false); |
| 1700 | } | 1701 | } |
| 1701 | 1702 | ||
| 1702 | int force_sig_fault(int sig, int code, void __user *addr | 1703 | int force_sig_fault(int sig, int code, void __user *addr |
| @@ -1798,6 +1799,27 @@ int force_sig_perf(void __user *addr, u32 type, u64 sig_data) · 95 unmodified lines | |||
| 1798 | return force_sig_info(&info); | 1799 | return force_sig_info(&info); |
| 1799 | } | 1800 | } |
| 1800 | 1801 | ||
| 1802 | /** | ||
| 1803 | * force_sig_seccomp - signals the task to allow in-process syscall emulation | ||
| 1804 | * @syscall: syscall number to send to userland | ||
| 1805 | * @reason: filter-supplied reason code to send to userland (via si_errno) | ||
| 1806 | * | ||
| 1807 | * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info. | ||
| 1808 | */ | ||
| 1809 | int force_sig_seccomp(int syscall, int reason, bool force_coredump) | ||
| 1810 | { | ||
| 1811 | struct kernel_siginfo info; | ||
| 1812 | |||
| 1813 | clear_siginfo(&info); | ||
| 1814 | info.si_signo = SIGSYS; | ||
| 1815 | info.si_code = SYS_SECCOMP; | ||
| 1816 | info.si_call_addr = (void __user *)KSTK_EIP(current); | ||
| 1817 | info.si_errno = reason; | ||
| 1818 | info.si_arch = syscall_get_arch(current); | ||
| 1819 | info.si_syscall = syscall; | ||
| 1820 | return force_sig_info_to_task(&info, current, force_coredump); | ||
| 1821 | } | ||
| 1822 | |||
| 1801 | /* For the crazy architectures that include trap information in | 1823 | /* For the crazy architectures that include trap information in |
| 1802 | * the errno field, instead of an actual errno value. | 1824 | * the errno field, instead of an actual errno value. |
| 1803 | */ | 1825 | */ |
| @@ -416,7 +416,6 @@ COND_SYSCALL(epoll_wait); · 415 unmodified lines | |||
| 416 | COND_SYSCALL(recv); | 416 | COND_SYSCALL(recv); |
| 417 | COND_SYSCALL_COMPAT(recv); | 417 | COND_SYSCALL_COMPAT(recv); |
| 418 | COND_SYSCALL(send); | 418 | COND_SYSCALL(send); |
| 419 | COND_SYSCALL(bdflush); | ||
| 420 | COND_SYSCALL(uselib); | 419 | COND_SYSCALL(uselib); |
| 421 | 420 | ||
| 422 | /* optional: time32 */ | 421 | /* optional: time32 */ |