.. | .. |
---|
21 | 21 | #include <linux/personality.h> |
---|
22 | 22 | #include <linux/compat.h> |
---|
23 | 23 | #include <linux/binfmts.h> |
---|
| 24 | +#include <linux/syscalls.h> |
---|
24 | 25 | #include <asm/ucontext.h> |
---|
25 | 26 | #include <linux/uaccess.h> |
---|
26 | 27 | #include <asm/fpu/internal.h> |
---|
.. | .. |
---|
35 | 36 | #include <asm/sighandling.h> |
---|
36 | 37 | #include <asm/smap.h> |
---|
37 | 38 | |
---|
| 39 | +static inline void reload_segments(struct sigcontext_32 *sc) |
---|
| 40 | +{ |
---|
| 41 | + unsigned int cur; |
---|
| 42 | + |
---|
| 43 | + savesegment(gs, cur); |
---|
| 44 | + if ((sc->gs | 0x03) != cur) |
---|
| 45 | + load_gs_index(sc->gs | 0x03); |
---|
| 46 | + savesegment(fs, cur); |
---|
| 47 | + if ((sc->fs | 0x03) != cur) |
---|
| 48 | + loadsegment(fs, sc->fs | 0x03); |
---|
| 49 | + savesegment(ds, cur); |
---|
| 50 | + if ((sc->ds | 0x03) != cur) |
---|
| 51 | + loadsegment(ds, sc->ds | 0x03); |
---|
| 52 | + savesegment(es, cur); |
---|
| 53 | + if ((sc->es | 0x03) != cur) |
---|
| 54 | + loadsegment(es, sc->es | 0x03); |
---|
| 55 | +} |
---|
| 56 | + |
---|
38 | 57 | /* |
---|
39 | 58 | * Do a signal return; undo the signal stack. |
---|
40 | 59 | */ |
---|
41 | | -#define loadsegment_gs(v) load_gs_index(v) |
---|
42 | | -#define loadsegment_fs(v) loadsegment(fs, v) |
---|
43 | | -#define loadsegment_ds(v) loadsegment(ds, v) |
---|
44 | | -#define loadsegment_es(v) loadsegment(es, v) |
---|
45 | | - |
---|
46 | | -#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; }) |
---|
47 | | -#define set_user_seg(seg, v) loadsegment_##seg(v) |
---|
48 | | - |
---|
49 | | -#define COPY(x) { \ |
---|
50 | | - get_user_ex(regs->x, &sc->x); \ |
---|
51 | | -} |
---|
52 | | - |
---|
53 | | -#define GET_SEG(seg) ({ \ |
---|
54 | | - unsigned short tmp; \ |
---|
55 | | - get_user_ex(tmp, &sc->seg); \ |
---|
56 | | - tmp; \ |
---|
57 | | -}) |
---|
58 | | - |
---|
59 | | -#define COPY_SEG_CPL3(seg) do { \ |
---|
60 | | - regs->seg = GET_SEG(seg) | 3; \ |
---|
61 | | -} while (0) |
---|
62 | | - |
---|
63 | | -#define RELOAD_SEG(seg) { \ |
---|
64 | | - unsigned int pre = (seg) | 3; \ |
---|
65 | | - unsigned int cur = get_user_seg(seg); \ |
---|
66 | | - if (pre != cur) \ |
---|
67 | | - set_user_seg(seg, pre); \ |
---|
68 | | -} |
---|
69 | | - |
---|
70 | 60 | static int ia32_restore_sigcontext(struct pt_regs *regs, |
---|
71 | | - struct sigcontext_32 __user *sc) |
---|
| 61 | + struct sigcontext_32 __user *usc) |
---|
72 | 62 | { |
---|
73 | | - unsigned int tmpflags, err = 0; |
---|
74 | | - u16 gs, fs, es, ds; |
---|
75 | | - void __user *buf; |
---|
76 | | - u32 tmp; |
---|
| 63 | + struct sigcontext_32 sc; |
---|
77 | 64 | |
---|
78 | 65 | /* Always make any pending restarted system calls return -EINTR */ |
---|
79 | 66 | current->restart_block.fn = do_no_restart_syscall; |
---|
80 | 67 | |
---|
81 | | - get_user_try { |
---|
82 | | - gs = GET_SEG(gs); |
---|
83 | | - fs = GET_SEG(fs); |
---|
84 | | - ds = GET_SEG(ds); |
---|
85 | | - es = GET_SEG(es); |
---|
| 68 | + if (unlikely(copy_from_user(&sc, usc, sizeof(sc)))) |
---|
| 69 | + return -EFAULT; |
---|
86 | 70 | |
---|
87 | | - COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
---|
88 | | - COPY(dx); COPY(cx); COPY(ip); COPY(ax); |
---|
89 | | - /* Don't touch extended registers */ |
---|
| 71 | + /* Get only the ia32 registers. */ |
---|
| 72 | + regs->bx = sc.bx; |
---|
| 73 | + regs->cx = sc.cx; |
---|
| 74 | + regs->dx = sc.dx; |
---|
| 75 | + regs->si = sc.si; |
---|
| 76 | + regs->di = sc.di; |
---|
| 77 | + regs->bp = sc.bp; |
---|
| 78 | + regs->ax = sc.ax; |
---|
| 79 | + regs->sp = sc.sp; |
---|
| 80 | + regs->ip = sc.ip; |
---|
90 | 81 | |
---|
91 | | - COPY_SEG_CPL3(cs); |
---|
92 | | - COPY_SEG_CPL3(ss); |
---|
| 82 | + /* Get CS/SS and force CPL3 */ |
---|
| 83 | + regs->cs = sc.cs | 0x03; |
---|
| 84 | + regs->ss = sc.ss | 0x03; |
---|
93 | 85 | |
---|
94 | | - get_user_ex(tmpflags, &sc->flags); |
---|
95 | | - regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
---|
96 | | - /* disable syscall checks */ |
---|
97 | | - regs->orig_ax = -1; |
---|
98 | | - |
---|
99 | | - get_user_ex(tmp, &sc->fpstate); |
---|
100 | | - buf = compat_ptr(tmp); |
---|
101 | | - } get_user_catch(err); |
---|
| 86 | + regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS); |
---|
| 87 | + /* disable syscall checks */ |
---|
| 88 | + regs->orig_ax = -1; |
---|
102 | 89 | |
---|
103 | 90 | /* |
---|
104 | 91 | * Reload fs and gs if they have changed in the signal |
---|
.. | .. |
---|
106 | 93 | * the handler, but does not clobber them at least in the |
---|
107 | 94 | * normal case. |
---|
108 | 95 | */ |
---|
109 | | - RELOAD_SEG(gs); |
---|
110 | | - RELOAD_SEG(fs); |
---|
111 | | - RELOAD_SEG(ds); |
---|
112 | | - RELOAD_SEG(es); |
---|
113 | | - |
---|
114 | | - err |= fpu__restore_sig(buf, 1); |
---|
115 | | - |
---|
116 | | - force_iret(); |
---|
117 | | - |
---|
118 | | - return err; |
---|
| 96 | + reload_segments(&sc); |
---|
| 97 | + return fpu__restore_sig(compat_ptr(sc.fpstate), 1); |
---|
119 | 98 | } |
---|
120 | 99 | |
---|
121 | | -asmlinkage long sys32_sigreturn(const struct pt_regs *__unused) |
---|
| 100 | +COMPAT_SYSCALL_DEFINE0(sigreturn) |
---|
122 | 101 | { |
---|
123 | 102 | struct pt_regs *regs = current_pt_regs(); |
---|
124 | 103 | struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8); |
---|
125 | 104 | sigset_t set; |
---|
126 | 105 | |
---|
127 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 106 | + if (!access_ok(frame, sizeof(*frame))) |
---|
128 | 107 | goto badframe; |
---|
129 | 108 | if (__get_user(set.sig[0], &frame->sc.oldmask) |
---|
130 | | - || (_COMPAT_NSIG_WORDS > 1 |
---|
131 | | - && __copy_from_user((((char *) &set.sig) + 4), |
---|
132 | | - &frame->extramask, |
---|
133 | | - sizeof(frame->extramask)))) |
---|
| 109 | + || __get_user(((__u32 *)&set)[1], &frame->extramask[0])) |
---|
134 | 110 | goto badframe; |
---|
135 | 111 | |
---|
136 | 112 | set_current_blocked(&set); |
---|
.. | .. |
---|
144 | 120 | return 0; |
---|
145 | 121 | } |
---|
146 | 122 | |
---|
147 | | -asmlinkage long sys32_rt_sigreturn(const struct pt_regs *__unused) |
---|
| 123 | +COMPAT_SYSCALL_DEFINE0(rt_sigreturn) |
---|
148 | 124 | { |
---|
149 | 125 | struct pt_regs *regs = current_pt_regs(); |
---|
150 | 126 | struct rt_sigframe_ia32 __user *frame; |
---|
.. | .. |
---|
152 | 128 | |
---|
153 | 129 | frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4); |
---|
154 | 130 | |
---|
155 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 131 | + if (!access_ok(frame, sizeof(*frame))) |
---|
156 | 132 | goto badframe; |
---|
157 | | - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
---|
| 133 | + if (__get_user(set.sig[0], (__u64 __user *)&frame->uc.uc_sigmask)) |
---|
158 | 134 | goto badframe; |
---|
159 | 135 | |
---|
160 | 136 | set_current_blocked(&set); |
---|
.. | .. |
---|
176 | 152 | * Set up a signal frame. |
---|
177 | 153 | */ |
---|
178 | 154 | |
---|
179 | | -static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc, |
---|
180 | | - void __user *fpstate, |
---|
181 | | - struct pt_regs *regs, unsigned int mask) |
---|
| 155 | +#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; }) |
---|
| 156 | + |
---|
| 157 | +static __always_inline int |
---|
| 158 | +__unsafe_setup_sigcontext32(struct sigcontext_32 __user *sc, |
---|
| 159 | + void __user *fpstate, |
---|
| 160 | + struct pt_regs *regs, unsigned int mask) |
---|
182 | 161 | { |
---|
183 | | - int err = 0; |
---|
| 162 | + unsafe_put_user(get_user_seg(gs), (unsigned int __user *)&sc->gs, Efault); |
---|
| 163 | + unsafe_put_user(get_user_seg(fs), (unsigned int __user *)&sc->fs, Efault); |
---|
| 164 | + unsafe_put_user(get_user_seg(ds), (unsigned int __user *)&sc->ds, Efault); |
---|
| 165 | + unsafe_put_user(get_user_seg(es), (unsigned int __user *)&sc->es, Efault); |
---|
184 | 166 | |
---|
185 | | - put_user_try { |
---|
186 | | - put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs); |
---|
187 | | - put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs); |
---|
188 | | - put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds); |
---|
189 | | - put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es); |
---|
| 167 | + unsafe_put_user(regs->di, &sc->di, Efault); |
---|
| 168 | + unsafe_put_user(regs->si, &sc->si, Efault); |
---|
| 169 | + unsafe_put_user(regs->bp, &sc->bp, Efault); |
---|
| 170 | + unsafe_put_user(regs->sp, &sc->sp, Efault); |
---|
| 171 | + unsafe_put_user(regs->bx, &sc->bx, Efault); |
---|
| 172 | + unsafe_put_user(regs->dx, &sc->dx, Efault); |
---|
| 173 | + unsafe_put_user(regs->cx, &sc->cx, Efault); |
---|
| 174 | + unsafe_put_user(regs->ax, &sc->ax, Efault); |
---|
| 175 | + unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault); |
---|
| 176 | + unsafe_put_user(current->thread.error_code, &sc->err, Efault); |
---|
| 177 | + unsafe_put_user(regs->ip, &sc->ip, Efault); |
---|
| 178 | + unsafe_put_user(regs->cs, (unsigned int __user *)&sc->cs, Efault); |
---|
| 179 | + unsafe_put_user(regs->flags, &sc->flags, Efault); |
---|
| 180 | + unsafe_put_user(regs->sp, &sc->sp_at_signal, Efault); |
---|
| 181 | + unsafe_put_user(regs->ss, (unsigned int __user *)&sc->ss, Efault); |
---|
190 | 182 | |
---|
191 | | - put_user_ex(regs->di, &sc->di); |
---|
192 | | - put_user_ex(regs->si, &sc->si); |
---|
193 | | - put_user_ex(regs->bp, &sc->bp); |
---|
194 | | - put_user_ex(regs->sp, &sc->sp); |
---|
195 | | - put_user_ex(regs->bx, &sc->bx); |
---|
196 | | - put_user_ex(regs->dx, &sc->dx); |
---|
197 | | - put_user_ex(regs->cx, &sc->cx); |
---|
198 | | - put_user_ex(regs->ax, &sc->ax); |
---|
199 | | - put_user_ex(current->thread.trap_nr, &sc->trapno); |
---|
200 | | - put_user_ex(current->thread.error_code, &sc->err); |
---|
201 | | - put_user_ex(regs->ip, &sc->ip); |
---|
202 | | - put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); |
---|
203 | | - put_user_ex(regs->flags, &sc->flags); |
---|
204 | | - put_user_ex(regs->sp, &sc->sp_at_signal); |
---|
205 | | - put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); |
---|
| 183 | + unsafe_put_user(ptr_to_compat(fpstate), &sc->fpstate, Efault); |
---|
206 | 184 | |
---|
207 | | - put_user_ex(ptr_to_compat(fpstate), &sc->fpstate); |
---|
| 185 | + /* non-iBCS2 extensions.. */ |
---|
| 186 | + unsafe_put_user(mask, &sc->oldmask, Efault); |
---|
| 187 | + unsafe_put_user(current->thread.cr2, &sc->cr2, Efault); |
---|
| 188 | + return 0; |
---|
208 | 189 | |
---|
209 | | - /* non-iBCS2 extensions.. */ |
---|
210 | | - put_user_ex(mask, &sc->oldmask); |
---|
211 | | - put_user_ex(current->thread.cr2, &sc->cr2); |
---|
212 | | - } put_user_catch(err); |
---|
213 | | - |
---|
214 | | - return err; |
---|
| 190 | +Efault: |
---|
| 191 | + return -EFAULT; |
---|
215 | 192 | } |
---|
| 193 | + |
---|
| 194 | +#define unsafe_put_sigcontext32(sc, fp, regs, set, label) \ |
---|
| 195 | +do { \ |
---|
| 196 | + if (__unsafe_setup_sigcontext32(sc, fp, regs, set->sig[0])) \ |
---|
| 197 | + goto label; \ |
---|
| 198 | +} while(0) |
---|
216 | 199 | |
---|
217 | 200 | /* |
---|
218 | 201 | * Determine which stack to use.. |
---|
.. | .. |
---|
221 | 204 | size_t frame_size, |
---|
222 | 205 | void __user **fpstate) |
---|
223 | 206 | { |
---|
224 | | - struct fpu *fpu = ¤t->thread.fpu; |
---|
225 | | - unsigned long sp; |
---|
| 207 | + unsigned long sp, fx_aligned, math_size; |
---|
226 | 208 | |
---|
227 | 209 | /* Default to using normal stack */ |
---|
228 | 210 | sp = regs->sp; |
---|
.. | .. |
---|
236 | 218 | ksig->ka.sa.sa_restorer) |
---|
237 | 219 | sp = (unsigned long) ksig->ka.sa.sa_restorer; |
---|
238 | 220 | |
---|
239 | | - if (fpu->initialized) { |
---|
240 | | - unsigned long fx_aligned, math_size; |
---|
241 | | - |
---|
242 | | - sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size); |
---|
243 | | - *fpstate = (struct _fpstate_32 __user *) sp; |
---|
244 | | - if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned, |
---|
245 | | - math_size) < 0) |
---|
246 | | - return (void __user *) -1L; |
---|
247 | | - } |
---|
| 221 | + sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size); |
---|
| 222 | + *fpstate = (struct _fpstate_32 __user *) sp; |
---|
| 223 | + if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned, |
---|
| 224 | + math_size) < 0) |
---|
| 225 | + return (void __user *) -1L; |
---|
248 | 226 | |
---|
249 | 227 | sp -= frame_size; |
---|
250 | 228 | /* Align the stack pointer according to the i386 ABI, |
---|
.. | .. |
---|
258 | 236 | { |
---|
259 | 237 | struct sigframe_ia32 __user *frame; |
---|
260 | 238 | void __user *restorer; |
---|
261 | | - int err = 0; |
---|
262 | | - void __user *fpstate = NULL; |
---|
| 239 | + void __user *fp = NULL; |
---|
263 | 240 | |
---|
264 | 241 | /* copy_to_user optimizes that into a single 8 byte store */ |
---|
265 | 242 | static const struct { |
---|
.. | .. |
---|
272 | 249 | 0x80cd, /* int $0x80 */ |
---|
273 | 250 | }; |
---|
274 | 251 | |
---|
275 | | - frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate); |
---|
276 | | - |
---|
277 | | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
---|
278 | | - return -EFAULT; |
---|
279 | | - |
---|
280 | | - if (__put_user(sig, &frame->sig)) |
---|
281 | | - return -EFAULT; |
---|
282 | | - |
---|
283 | | - if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) |
---|
284 | | - return -EFAULT; |
---|
285 | | - |
---|
286 | | - if (_COMPAT_NSIG_WORDS > 1) { |
---|
287 | | - if (__copy_to_user(frame->extramask, &set->sig[1], |
---|
288 | | - sizeof(frame->extramask))) |
---|
289 | | - return -EFAULT; |
---|
290 | | - } |
---|
| 252 | + frame = get_sigframe(ksig, regs, sizeof(*frame), &fp); |
---|
291 | 253 | |
---|
292 | 254 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
---|
293 | 255 | restorer = ksig->ka.sa.sa_restorer; |
---|
.. | .. |
---|
300 | 262 | restorer = &frame->retcode; |
---|
301 | 263 | } |
---|
302 | 264 | |
---|
303 | | - put_user_try { |
---|
304 | | - put_user_ex(ptr_to_compat(restorer), &frame->pretcode); |
---|
305 | | - |
---|
306 | | - /* |
---|
307 | | - * These are actually not used anymore, but left because some |
---|
308 | | - * gdb versions depend on them as a marker. |
---|
309 | | - */ |
---|
310 | | - put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); |
---|
311 | | - } put_user_catch(err); |
---|
312 | | - |
---|
313 | | - if (err) |
---|
| 265 | + if (!user_access_begin(frame, sizeof(*frame))) |
---|
314 | 266 | return -EFAULT; |
---|
| 267 | + |
---|
| 268 | + unsafe_put_user(sig, &frame->sig, Efault); |
---|
| 269 | + unsafe_put_sigcontext32(&frame->sc, fp, regs, set, Efault); |
---|
| 270 | + unsafe_put_user(set->sig[1], &frame->extramask[0], Efault); |
---|
| 271 | + unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault); |
---|
| 272 | + /* |
---|
| 273 | + * These are actually not used anymore, but left because some |
---|
| 274 | + * gdb versions depend on them as a marker. |
---|
| 275 | + */ |
---|
| 276 | + unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault); |
---|
| 277 | + user_access_end(); |
---|
315 | 278 | |
---|
316 | 279 | /* Set up registers for signal handler */ |
---|
317 | 280 | regs->sp = (unsigned long) frame; |
---|
.. | .. |
---|
329 | 292 | regs->ss = __USER32_DS; |
---|
330 | 293 | |
---|
331 | 294 | return 0; |
---|
| 295 | +Efault: |
---|
| 296 | + user_access_end(); |
---|
| 297 | + return -EFAULT; |
---|
332 | 298 | } |
---|
333 | 299 | |
---|
334 | 300 | int ia32_setup_rt_frame(int sig, struct ksignal *ksig, |
---|
.. | .. |
---|
336 | 302 | { |
---|
337 | 303 | struct rt_sigframe_ia32 __user *frame; |
---|
338 | 304 | void __user *restorer; |
---|
339 | | - int err = 0; |
---|
340 | | - void __user *fpstate = NULL; |
---|
| 305 | + void __user *fp = NULL; |
---|
341 | 306 | |
---|
342 | | - /* __copy_to_user optimizes that into a single 8 byte store */ |
---|
| 307 | + /* unsafe_put_user optimizes that into a single 8 byte store */ |
---|
343 | 308 | static const struct { |
---|
344 | 309 | u8 movl; |
---|
345 | 310 | u32 val; |
---|
.. | .. |
---|
352 | 317 | 0, |
---|
353 | 318 | }; |
---|
354 | 319 | |
---|
355 | | - frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate); |
---|
| 320 | + frame = get_sigframe(ksig, regs, sizeof(*frame), &fp); |
---|
356 | 321 | |
---|
357 | | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
---|
| 322 | + if (!user_access_begin(frame, sizeof(*frame))) |
---|
358 | 323 | return -EFAULT; |
---|
359 | 324 | |
---|
360 | | - put_user_try { |
---|
361 | | - put_user_ex(sig, &frame->sig); |
---|
362 | | - put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo); |
---|
363 | | - put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); |
---|
| 325 | + unsafe_put_user(sig, &frame->sig, Efault); |
---|
| 326 | + unsafe_put_user(ptr_to_compat(&frame->info), &frame->pinfo, Efault); |
---|
| 327 | + unsafe_put_user(ptr_to_compat(&frame->uc), &frame->puc, Efault); |
---|
364 | 328 | |
---|
365 | | - /* Create the ucontext. */ |
---|
366 | | - if (boot_cpu_has(X86_FEATURE_XSAVE)) |
---|
367 | | - put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); |
---|
368 | | - else |
---|
369 | | - put_user_ex(0, &frame->uc.uc_flags); |
---|
370 | | - put_user_ex(0, &frame->uc.uc_link); |
---|
371 | | - compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
---|
| 329 | + /* Create the ucontext. */ |
---|
| 330 | + if (static_cpu_has(X86_FEATURE_XSAVE)) |
---|
| 331 | + unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault); |
---|
| 332 | + else |
---|
| 333 | + unsafe_put_user(0, &frame->uc.uc_flags, Efault); |
---|
| 334 | + unsafe_put_user(0, &frame->uc.uc_link, Efault); |
---|
| 335 | + unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault); |
---|
372 | 336 | |
---|
373 | | - if (ksig->ka.sa.sa_flags & SA_RESTORER) |
---|
374 | | - restorer = ksig->ka.sa.sa_restorer; |
---|
375 | | - else |
---|
376 | | - restorer = current->mm->context.vdso + |
---|
377 | | - vdso_image_32.sym___kernel_rt_sigreturn; |
---|
378 | | - put_user_ex(ptr_to_compat(restorer), &frame->pretcode); |
---|
| 337 | + if (ksig->ka.sa.sa_flags & SA_RESTORER) |
---|
| 338 | + restorer = ksig->ka.sa.sa_restorer; |
---|
| 339 | + else |
---|
| 340 | + restorer = current->mm->context.vdso + |
---|
| 341 | + vdso_image_32.sym___kernel_rt_sigreturn; |
---|
| 342 | + unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault); |
---|
379 | 343 | |
---|
380 | | - /* |
---|
381 | | - * Not actually used anymore, but left because some gdb |
---|
382 | | - * versions need it. |
---|
383 | | - */ |
---|
384 | | - put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); |
---|
385 | | - } put_user_catch(err); |
---|
| 344 | + /* |
---|
| 345 | + * Not actually used anymore, but left because some gdb |
---|
| 346 | + * versions need it. |
---|
| 347 | + */ |
---|
| 348 | + unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault); |
---|
| 349 | + unsafe_put_sigcontext32(&frame->uc.uc_mcontext, fp, regs, set, Efault); |
---|
| 350 | + unsafe_put_user(*(__u64 *)set, (__u64 *)&frame->uc.uc_sigmask, Efault); |
---|
| 351 | + user_access_end(); |
---|
386 | 352 | |
---|
387 | | - err |= __copy_siginfo_to_user32(&frame->info, &ksig->info, false); |
---|
388 | | - err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
---|
389 | | - regs, set->sig[0]); |
---|
390 | | - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
---|
391 | | - |
---|
392 | | - if (err) |
---|
| 353 | + if (__copy_siginfo_to_user32(&frame->info, &ksig->info)) |
---|
393 | 354 | return -EFAULT; |
---|
394 | 355 | |
---|
395 | 356 | /* Set up registers for signal handler */ |
---|
.. | .. |
---|
408 | 369 | regs->ss = __USER32_DS; |
---|
409 | 370 | |
---|
410 | 371 | return 0; |
---|
| 372 | +Efault: |
---|
| 373 | + user_access_end(); |
---|
| 374 | + return -EFAULT; |
---|
411 | 375 | } |
---|