.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Based on arch/arm/kernel/signal.c |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 1995-2009 Russell King |
---|
5 | 6 | * Copyright (C) 2012 ARM Ltd. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | | - * |
---|
16 | | - * You should have received a copy of the GNU General Public License |
---|
17 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
18 | 7 | */ |
---|
19 | 8 | |
---|
20 | 9 | #include <linux/cache.h> |
---|
.. | .. |
---|
40 | 29 | #include <asm/unistd.h> |
---|
41 | 30 | #include <asm/fpsimd.h> |
---|
42 | 31 | #include <asm/ptrace.h> |
---|
| 32 | +#include <asm/syscall.h> |
---|
43 | 33 | #include <asm/signal32.h> |
---|
44 | 34 | #include <asm/traps.h> |
---|
45 | 35 | #include <asm/vdso.h> |
---|
.. | .. |
---|
255 | 245 | if (vq) { |
---|
256 | 246 | /* |
---|
257 | 247 | * This assumes that the SVE state has already been saved to |
---|
258 | | - * the task struct by calling preserve_fpsimd_context(). |
---|
| 248 | + * the task struct by calling the function |
---|
| 249 | + * fpsimd_signal_preserve_current_state(). |
---|
259 | 250 | */ |
---|
260 | 251 | err |= __copy_to_user((char __user *)ctx + SVE_SIG_REGS_OFFSET, |
---|
261 | 252 | current->thread.sve_state, |
---|
.. | .. |
---|
296 | 287 | */ |
---|
297 | 288 | |
---|
298 | 289 | fpsimd_flush_task_state(current); |
---|
299 | | - barrier(); |
---|
300 | | - /* From now, fpsimd_thread_switch() won't clear TIF_FOREIGN_FPSTATE */ |
---|
301 | | - |
---|
302 | | - set_thread_flag(TIF_FOREIGN_FPSTATE); |
---|
303 | | - barrier(); |
---|
304 | 290 | /* From now, fpsimd_thread_switch() won't touch thread.sve_state */ |
---|
305 | 291 | |
---|
306 | 292 | sve_alloc(current); |
---|
.. | .. |
---|
387 | 373 | goto done; |
---|
388 | 374 | |
---|
389 | 375 | case FPSIMD_MAGIC: |
---|
| 376 | + if (!system_supports_fpsimd()) |
---|
| 377 | + goto invalid; |
---|
390 | 378 | if (user->fpsimd) |
---|
391 | 379 | goto invalid; |
---|
392 | 380 | |
---|
.. | .. |
---|
470 | 458 | offset = 0; |
---|
471 | 459 | limit = extra_size; |
---|
472 | 460 | |
---|
473 | | - if (!access_ok(VERIFY_READ, base, limit)) |
---|
| 461 | + if (!access_ok(base, limit)) |
---|
474 | 462 | goto invalid; |
---|
475 | 463 | |
---|
476 | 464 | continue; |
---|
.. | .. |
---|
522 | 510 | if (err == 0) |
---|
523 | 511 | err = parse_user_sigframe(&user, sf); |
---|
524 | 512 | |
---|
525 | | - if (err == 0) { |
---|
| 513 | + if (err == 0 && system_supports_fpsimd()) { |
---|
526 | 514 | if (!user.fpsimd) |
---|
527 | 515 | return -EINVAL; |
---|
528 | 516 | |
---|
.. | .. |
---|
556 | 544 | |
---|
557 | 545 | frame = (struct rt_sigframe __user *)regs->sp; |
---|
558 | 546 | |
---|
559 | | - if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) |
---|
| 547 | + if (!access_ok(frame, sizeof (*frame))) |
---|
560 | 548 | goto badframe; |
---|
561 | 549 | |
---|
562 | 550 | if (restore_sigframe(regs, frame)) |
---|
.. | .. |
---|
584 | 572 | { |
---|
585 | 573 | int err; |
---|
586 | 574 | |
---|
587 | | - err = sigframe_alloc(user, &user->fpsimd_offset, |
---|
588 | | - sizeof(struct fpsimd_context)); |
---|
589 | | - if (err) |
---|
590 | | - return err; |
---|
| 575 | + if (system_supports_fpsimd()) { |
---|
| 576 | + err = sigframe_alloc(user, &user->fpsimd_offset, |
---|
| 577 | + sizeof(struct fpsimd_context)); |
---|
| 578 | + if (err) |
---|
| 579 | + return err; |
---|
| 580 | + } |
---|
591 | 581 | |
---|
592 | 582 | /* fault information, if valid */ |
---|
593 | 583 | if (add_all || current->thread.fault_code) { |
---|
.. | .. |
---|
639 | 629 | |
---|
640 | 630 | err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); |
---|
641 | 631 | |
---|
642 | | - if (err == 0) { |
---|
| 632 | + if (err == 0 && system_supports_fpsimd()) { |
---|
643 | 633 | struct fpsimd_context __user *fpsimd_ctx = |
---|
644 | 634 | apply_user_offset(user, user->fpsimd_offset); |
---|
645 | 635 | err |= preserve_fpsimd_context(fpsimd_ctx); |
---|
.. | .. |
---|
730 | 720 | /* |
---|
731 | 721 | * Check that we can actually write to the signal frame. |
---|
732 | 722 | */ |
---|
733 | | - if (!access_ok(VERIFY_WRITE, user->sigframe, sp_top - sp)) |
---|
| 723 | + if (!access_ok(user->sigframe, sp_top - sp)) |
---|
734 | 724 | return -EFAULT; |
---|
735 | 725 | |
---|
736 | 726 | return 0; |
---|
.. | .. |
---|
745 | 735 | regs->sp = (unsigned long)user->sigframe; |
---|
746 | 736 | regs->regs[29] = (unsigned long)&user->next_frame->fp; |
---|
747 | 737 | regs->pc = (unsigned long)ka->sa.sa_handler; |
---|
| 738 | + |
---|
| 739 | + /* |
---|
| 740 | + * Signal delivery is a (wacky) indirect function call in |
---|
| 741 | + * userspace, so simulate the same setting of BTYPE as a BLR |
---|
| 742 | + * <register containing the signal handler entry point>. |
---|
| 743 | + * Signal delivery to a location in a PROT_BTI guarded page |
---|
| 744 | + * that is not a function entry point will now trigger a |
---|
| 745 | + * SIGILL in userspace. |
---|
| 746 | + * |
---|
| 747 | + * If the signal handler entry point is not in a PROT_BTI |
---|
| 748 | + * guarded page, this is harmless. |
---|
| 749 | + */ |
---|
| 750 | + if (system_supports_bti()) { |
---|
| 751 | + regs->pstate &= ~PSR_BTYPE_MASK; |
---|
| 752 | + regs->pstate |= PSR_BTYPE_C; |
---|
| 753 | + } |
---|
| 754 | + |
---|
| 755 | + /* TCO (Tag Check Override) always cleared for signal handlers */ |
---|
| 756 | + regs->pstate &= ~PSR_TCO_BIT; |
---|
748 | 757 | |
---|
749 | 758 | if (ka->sa.sa_flags & SA_RESTORER) |
---|
750 | 759 | sigtramp = ka->sa.sa_restorer; |
---|
.. | .. |
---|
884 | 893 | retval == -ERESTART_RESTARTBLOCK || |
---|
885 | 894 | (retval == -ERESTARTSYS && |
---|
886 | 895 | !(ksig.ka.sa.sa_flags & SA_RESTART)))) { |
---|
887 | | - regs->regs[0] = -EINTR; |
---|
| 896 | + syscall_set_return_value(current, regs, -EINTR, 0); |
---|
888 | 897 | regs->pc = continue_addr; |
---|
889 | 898 | } |
---|
890 | 899 | |
---|
.. | .. |
---|
908 | 917 | asmlinkage void do_notify_resume(struct pt_regs *regs, |
---|
909 | 918 | unsigned long thread_flags) |
---|
910 | 919 | { |
---|
911 | | - /* |
---|
912 | | - * The assembly code enters us with IRQs off, but it hasn't |
---|
913 | | - * informed the tracing code of that for efficiency reasons. |
---|
914 | | - * Update the trace code with the current status. |
---|
915 | | - */ |
---|
916 | | - trace_hardirqs_off(); |
---|
917 | | - |
---|
918 | 920 | do { |
---|
919 | 921 | /* Check valid user FS if needed */ |
---|
920 | 922 | addr_limit_user_check(); |
---|
.. | .. |
---|
930 | 932 | if (thread_flags & _TIF_UPROBE) |
---|
931 | 933 | uprobe_notify_resume(regs); |
---|
932 | 934 | |
---|
933 | | - if (thread_flags & _TIF_SIGPENDING) |
---|
| 935 | + if (thread_flags & _TIF_MTE_ASYNC_FAULT) { |
---|
| 936 | + clear_thread_flag(TIF_MTE_ASYNC_FAULT); |
---|
| 937 | + send_sig_fault(SIGSEGV, SEGV_MTEAERR, |
---|
| 938 | + (void __user *)NULL, current); |
---|
| 939 | + } |
---|
| 940 | + |
---|
| 941 | + if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) |
---|
934 | 942 | do_signal(regs); |
---|
935 | 943 | |
---|
936 | 944 | if (thread_flags & _TIF_NOTIFY_RESUME) { |
---|
937 | | - clear_thread_flag(TIF_NOTIFY_RESUME); |
---|
938 | 945 | tracehook_notify_resume(regs); |
---|
939 | 946 | rseq_handle_notify_resume(NULL, regs); |
---|
940 | 947 | } |
---|