hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/arm64/kernel/syscall.c
....@@ -50,10 +50,7 @@
5050 ret = do_ni_syscall(regs, scno);
5151 }
5252
53
- if (is_compat_task())
54
- ret = lower_32_bits(ret);
55
-
56
- regs->regs[0] = ret;
53
+ syscall_set_return_value(current, regs, 0, ret);
5754 }
5855
5956 static inline bool has_syscall_work(unsigned long flags)
....@@ -101,14 +98,55 @@
10198 regs->orig_x0 = regs->regs[0];
10299 regs->syscallno = scno;
103100
101
+ /*
102
+ * BTI note:
103
+ * The architecture does not guarantee that SPSR.BTYPE is zero
104
+ * on taking an SVC, so we could return to userspace with a
105
+ * non-zero BTYPE after the syscall.
106
+ *
107
+ * This shouldn't matter except when userspace is explicitly
108
+ * doing something stupid, such as setting PROT_BTI on a page
109
+ * that lacks conforming BTI/PACIxSP instructions, falling
110
+ * through from one executable page to another with differing
111
+ * PROT_BTI, or messing with BTYPE via ptrace: in such cases,
112
+ * userspace should not be surprised if a SIGILL occurs on
113
+ * syscall return.
114
+ *
115
+ * So, don't touch regs->pstate & PSR_BTYPE_MASK here.
116
+ * (Similarly for HVC and SMC elsewhere.)
117
+ */
118
+
104119 cortex_a76_erratum_1463225_svc_handler();
105
- user_exit_irqoff();
106120 local_daif_restore(DAIF_PROCCTX);
107121
122
+ if (flags & _TIF_MTE_ASYNC_FAULT) {
123
+ /*
124
+ * Process the asynchronous tag check fault before the actual
125
+ * syscall. do_notify_resume() will send a signal to userspace
126
+ * before the syscall is restarted.
127
+ */
128
+ syscall_set_return_value(current, regs, -ERESTARTNOINTR, 0);
129
+ return;
130
+ }
131
+
108132 if (has_syscall_work(flags)) {
109
- /* set default errno for user-issued syscall(-1) */
133
+ /*
134
+ * The de-facto standard way to skip a system call using ptrace
135
+ * is to set the system call to -1 (NO_SYSCALL) and set x0 to a
136
+ * suitable error code for consumption by userspace. However,
137
+ * this cannot be distinguished from a user-issued syscall(-1)
138
+ * and so we must set x0 to -ENOSYS here in case the tracer doesn't
139
+ * issue the skip and we fall into trace_exit with x0 preserved.
140
+ *
141
+ * This is slightly odd because it also means that if a tracer
142
+ * sets the system call number to -1 but does not initialise x0,
143
+ * then x0 will be preserved for all system calls apart from a
144
+ * user-issued syscall(-1). However, requesting a skip and not
145
+ * setting the return value is unlikely to do anything sensible
146
+ * anyway.
147
+ */
110148 if (scno == NO_SYSCALL)
111
- regs->regs[0] = -ENOSYS;
149
+ syscall_set_return_value(current, regs, -ENOSYS, 0);
112150 scno = syscall_trace_enter(regs);
113151 if (scno == NO_SYSCALL)
114152 goto trace_exit;
....@@ -124,15 +162,8 @@
124162 if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
125163 local_daif_mask();
126164 flags = current_thread_info()->flags;
127
- if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP)) {
128
- /*
129
- * We're off to userspace, where interrupts are
130
- * always enabled after we restore the flags from
131
- * the SPSR.
132
- */
133
- trace_hardirqs_on();
165
+ if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP))
134166 return;
135
- }
136167 local_daif_restore(DAIF_PROCCTX);
137168 }
138169
....@@ -157,14 +188,14 @@
157188 sve_user_disable();
158189 }
159190
160
-asmlinkage void el0_svc_handler(struct pt_regs *regs)
191
+void do_el0_svc(struct pt_regs *regs)
161192 {
162193 sve_user_discard();
163194 el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table);
164195 }
165196
166197 #ifdef CONFIG_COMPAT
167
-asmlinkage void el0_svc_compat_handler(struct pt_regs *regs)
198
+void do_el0_svc_compat(struct pt_regs *regs)
168199 {
169200 el0_svc_common(regs, regs->regs[7], __NR_compat_syscalls,
170201 compat_sys_call_table);