.. | .. |
---|
50 | 50 | ret = do_ni_syscall(regs, scno); |
---|
51 | 51 | } |
---|
52 | 52 | |
---|
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); |
---|
57 | 54 | } |
---|
58 | 55 | |
---|
59 | 56 | static inline bool has_syscall_work(unsigned long flags) |
---|
.. | .. |
---|
101 | 98 | regs->orig_x0 = regs->regs[0]; |
---|
102 | 99 | regs->syscallno = scno; |
---|
103 | 100 | |
---|
| 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 | + |
---|
104 | 119 | cortex_a76_erratum_1463225_svc_handler(); |
---|
105 | | - user_exit_irqoff(); |
---|
106 | 120 | local_daif_restore(DAIF_PROCCTX); |
---|
107 | 121 | |
---|
| 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 | + |
---|
108 | 132 | 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 | + */ |
---|
110 | 148 | if (scno == NO_SYSCALL) |
---|
111 | | - regs->regs[0] = -ENOSYS; |
---|
| 149 | + syscall_set_return_value(current, regs, -ENOSYS, 0); |
---|
112 | 150 | scno = syscall_trace_enter(regs); |
---|
113 | 151 | if (scno == NO_SYSCALL) |
---|
114 | 152 | goto trace_exit; |
---|
.. | .. |
---|
124 | 162 | if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) { |
---|
125 | 163 | local_daif_mask(); |
---|
126 | 164 | 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)) |
---|
134 | 166 | return; |
---|
135 | | - } |
---|
136 | 167 | local_daif_restore(DAIF_PROCCTX); |
---|
137 | 168 | } |
---|
138 | 169 | |
---|
.. | .. |
---|
157 | 188 | sve_user_disable(); |
---|
158 | 189 | } |
---|
159 | 190 | |
---|
160 | | -asmlinkage void el0_svc_handler(struct pt_regs *regs) |
---|
| 191 | +void do_el0_svc(struct pt_regs *regs) |
---|
161 | 192 | { |
---|
162 | 193 | sve_user_discard(); |
---|
163 | 194 | el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table); |
---|
164 | 195 | } |
---|
165 | 196 | |
---|
166 | 197 | #ifdef CONFIG_COMPAT |
---|
167 | | -asmlinkage void el0_svc_compat_handler(struct pt_regs *regs) |
---|
| 198 | +void do_el0_svc_compat(struct pt_regs *regs) |
---|
168 | 199 | { |
---|
169 | 200 | el0_svc_common(regs, regs->regs[7], __NR_compat_syscalls, |
---|
170 | 201 | compat_sys_call_table); |
---|