hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
kernel/arch/arm64/kernel/signal.c
....@@ -11,6 +11,7 @@
1111 #include <linux/errno.h>
1212 #include <linux/kernel.h>
1313 #include <linux/signal.h>
14
+#include <linux/irq_pipeline.h>
1415 #include <linux/personality.h>
1516 #include <linux/freezer.h>
1617 #include <linux/stddef.h>
....@@ -914,19 +915,36 @@
914915 restore_saved_sigmask();
915916 }
916917
918
+static inline void do_retuser(void)
919
+{
920
+ unsigned long thread_flags;
921
+
922
+ if (dovetailing()) {
923
+ thread_flags = current_thread_info()->flags;
924
+ if (thread_flags & _TIF_RETUSER)
925
+ inband_retuser_notify();
926
+ }
927
+}
928
+
917929 asmlinkage void do_notify_resume(struct pt_regs *regs,
918930 unsigned long thread_flags)
919931 {
932
+ WARN_ON_ONCE(irq_pipeline_debug() && running_oob());
933
+
934
+ stall_inband();
935
+
920936 do {
921937 /* Check valid user FS if needed */
922938 addr_limit_user_check();
923939
924940 if (thread_flags & _TIF_NEED_RESCHED) {
925941 /* Unmask Debug and SError for the next task */
926
- local_daif_restore(DAIF_PROCCTX_NOIRQ);
942
+ local_daif_restore(irqs_pipelined() ? DAIF_PROCCTX :
943
+ DAIF_PROCCTX_NOIRQ);
927944
928945 schedule();
929946 } else {
947
+ unstall_inband();
930948 local_daif_restore(DAIF_PROCCTX);
931949
932950 if (thread_flags & _TIF_UPROBE)
....@@ -948,11 +966,29 @@
948966
949967 if (thread_flags & _TIF_FOREIGN_FPSTATE)
950968 fpsimd_restore_current_state();
969
+
970
+ do_retuser();
971
+ /* RETUSER might have switched oob */
972
+ if (running_oob()) {
973
+ local_daif_mask();
974
+ return;
975
+ }
951976 }
952977
978
+ /*
979
+ * Dovetail: we may have restored the fpsimd state for
980
+ * current with no other opportunity to check for
981
+ * _TIF_FOREIGN_FPSTATE until we are back running on
982
+ * el0, so we must not take any interrupt until then,
983
+ * otherwise we may end up resuming with some OOB
984
+ * thread's fpsimd state.
985
+ */
953986 local_daif_mask();
987
+ stall_inband();
954988 thread_flags = READ_ONCE(current_thread_info()->flags);
955989 } while (thread_flags & _TIF_WORK_MASK);
990
+
991
+ unstall_inband();
956992 }
957993
958994 unsigned long __ro_after_init signal_minsigstksz;