diff options
Diffstat (limited to 'arch/x86/kernel/signal.c')
-rw-r--r-- | arch/x86/kernel/signal.c | 346 |
1 files changed, 164 insertions, 182 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index df0587f24c54..7cdcd16885ed 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -50,27 +50,23 @@ | |||
50 | # define FIX_EFLAGS __FIX_EFLAGS | 50 | # define FIX_EFLAGS __FIX_EFLAGS |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | #define COPY(x) { \ | 53 | #define COPY(x) do { \ |
54 | err |= __get_user(regs->x, &sc->x); \ | 54 | get_user_ex(regs->x, &sc->x); \ |
55 | } | 55 | } while (0) |
56 | 56 | ||
57 | #define COPY_SEG(seg) { \ | 57 | #define GET_SEG(seg) ({ \ |
58 | unsigned short tmp; \ | 58 | unsigned short tmp; \ |
59 | err |= __get_user(tmp, &sc->seg); \ | 59 | get_user_ex(tmp, &sc->seg); \ |
60 | regs->seg = tmp; \ | 60 | tmp; \ |
61 | } | 61 | }) |
62 | 62 | ||
63 | #define COPY_SEG_CPL3(seg) { \ | 63 | #define COPY_SEG(seg) do { \ |
64 | unsigned short tmp; \ | 64 | regs->seg = GET_SEG(seg); \ |
65 | err |= __get_user(tmp, &sc->seg); \ | 65 | } while (0) |
66 | regs->seg = tmp | 3; \ | ||
67 | } | ||
68 | 66 | ||
69 | #define GET_SEG(seg) { \ | 67 | #define COPY_SEG_CPL3(seg) do { \ |
70 | unsigned short tmp; \ | 68 | regs->seg = GET_SEG(seg) | 3; \ |
71 | err |= __get_user(tmp, &sc->seg); \ | 69 | } while (0) |
72 | loadsegment(seg, tmp); \ | ||
73 | } | ||
74 | 70 | ||
75 | static int | 71 | static int |
76 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | 72 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, |
@@ -83,45 +79,49 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
83 | /* Always make any pending restarted system calls return -EINTR */ | 79 | /* Always make any pending restarted system calls return -EINTR */ |
84 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 80 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
85 | 81 | ||
82 | get_user_try { | ||
83 | |||
86 | #ifdef CONFIG_X86_32 | 84 | #ifdef CONFIG_X86_32 |
87 | GET_SEG(gs); | 85 | set_user_gs(regs, GET_SEG(gs)); |
88 | COPY_SEG(fs); | 86 | COPY_SEG(fs); |
89 | COPY_SEG(es); | 87 | COPY_SEG(es); |
90 | COPY_SEG(ds); | 88 | COPY_SEG(ds); |
91 | #endif /* CONFIG_X86_32 */ | 89 | #endif /* CONFIG_X86_32 */ |
92 | 90 | ||
93 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 91 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
94 | COPY(dx); COPY(cx); COPY(ip); | 92 | COPY(dx); COPY(cx); COPY(ip); |
95 | 93 | ||
96 | #ifdef CONFIG_X86_64 | 94 | #ifdef CONFIG_X86_64 |
97 | COPY(r8); | 95 | COPY(r8); |
98 | COPY(r9); | 96 | COPY(r9); |
99 | COPY(r10); | 97 | COPY(r10); |
100 | COPY(r11); | 98 | COPY(r11); |
101 | COPY(r12); | 99 | COPY(r12); |
102 | COPY(r13); | 100 | COPY(r13); |
103 | COPY(r14); | 101 | COPY(r14); |
104 | COPY(r15); | 102 | COPY(r15); |
105 | #endif /* CONFIG_X86_64 */ | 103 | #endif /* CONFIG_X86_64 */ |
106 | 104 | ||
107 | #ifdef CONFIG_X86_32 | 105 | #ifdef CONFIG_X86_32 |
108 | COPY_SEG_CPL3(cs); | 106 | COPY_SEG_CPL3(cs); |
109 | COPY_SEG_CPL3(ss); | 107 | COPY_SEG_CPL3(ss); |
110 | #else /* !CONFIG_X86_32 */ | 108 | #else /* !CONFIG_X86_32 */ |
111 | /* Kernel saves and restores only the CS segment register on signals, | 109 | /* Kernel saves and restores only the CS segment register on signals, |
112 | * which is the bare minimum needed to allow mixed 32/64-bit code. | 110 | * which is the bare minimum needed to allow mixed 32/64-bit code. |
113 | * App's signal handler can save/restore other segments if needed. */ | 111 | * App's signal handler can save/restore other segments if needed. */ |
114 | COPY_SEG_CPL3(cs); | 112 | COPY_SEG_CPL3(cs); |
115 | #endif /* CONFIG_X86_32 */ | 113 | #endif /* CONFIG_X86_32 */ |
116 | 114 | ||
117 | err |= __get_user(tmpflags, &sc->flags); | 115 | get_user_ex(tmpflags, &sc->flags); |
118 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); | 116 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
119 | regs->orig_ax = -1; /* disable syscall checks */ | 117 | regs->orig_ax = -1; /* disable syscall checks */ |
118 | |||
119 | get_user_ex(buf, &sc->fpstate); | ||
120 | err |= restore_i387_xstate(buf); | ||
120 | 121 | ||
121 | err |= __get_user(buf, &sc->fpstate); | 122 | get_user_ex(*pax, &sc->ax); |
122 | err |= restore_i387_xstate(buf); | 123 | } get_user_catch(err); |
123 | 124 | ||
124 | err |= __get_user(*pax, &sc->ax); | ||
125 | return err; | 125 | return err; |
126 | } | 126 | } |
127 | 127 | ||
@@ -131,57 +131,55 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, | |||
131 | { | 131 | { |
132 | int err = 0; | 132 | int err = 0; |
133 | 133 | ||
134 | #ifdef CONFIG_X86_32 | 134 | put_user_try { |
135 | { | ||
136 | unsigned int tmp; | ||
137 | 135 | ||
138 | savesegment(gs, tmp); | 136 | #ifdef CONFIG_X86_32 |
139 | err |= __put_user(tmp, (unsigned int __user *)&sc->gs); | 137 | put_user_ex(get_user_gs(regs), (unsigned int __user *)&sc->gs); |
140 | } | 138 | put_user_ex(regs->fs, (unsigned int __user *)&sc->fs); |
141 | err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs); | 139 | put_user_ex(regs->es, (unsigned int __user *)&sc->es); |
142 | err |= __put_user(regs->es, (unsigned int __user *)&sc->es); | 140 | put_user_ex(regs->ds, (unsigned int __user *)&sc->ds); |
143 | err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds); | ||
144 | #endif /* CONFIG_X86_32 */ | 141 | #endif /* CONFIG_X86_32 */ |
145 | 142 | ||
146 | err |= __put_user(regs->di, &sc->di); | 143 | put_user_ex(regs->di, &sc->di); |
147 | err |= __put_user(regs->si, &sc->si); | 144 | put_user_ex(regs->si, &sc->si); |
148 | err |= __put_user(regs->bp, &sc->bp); | 145 | put_user_ex(regs->bp, &sc->bp); |
149 | err |= __put_user(regs->sp, &sc->sp); | 146 | put_user_ex(regs->sp, &sc->sp); |
150 | err |= __put_user(regs->bx, &sc->bx); | 147 | put_user_ex(regs->bx, &sc->bx); |
151 | err |= __put_user(regs->dx, &sc->dx); | 148 | put_user_ex(regs->dx, &sc->dx); |
152 | err |= __put_user(regs->cx, &sc->cx); | 149 | put_user_ex(regs->cx, &sc->cx); |
153 | err |= __put_user(regs->ax, &sc->ax); | 150 | put_user_ex(regs->ax, &sc->ax); |
154 | #ifdef CONFIG_X86_64 | 151 | #ifdef CONFIG_X86_64 |
155 | err |= __put_user(regs->r8, &sc->r8); | 152 | put_user_ex(regs->r8, &sc->r8); |
156 | err |= __put_user(regs->r9, &sc->r9); | 153 | put_user_ex(regs->r9, &sc->r9); |
157 | err |= __put_user(regs->r10, &sc->r10); | 154 | put_user_ex(regs->r10, &sc->r10); |
158 | err |= __put_user(regs->r11, &sc->r11); | 155 | put_user_ex(regs->r11, &sc->r11); |
159 | err |= __put_user(regs->r12, &sc->r12); | 156 | put_user_ex(regs->r12, &sc->r12); |
160 | err |= __put_user(regs->r13, &sc->r13); | 157 | put_user_ex(regs->r13, &sc->r13); |
161 | err |= __put_user(regs->r14, &sc->r14); | 158 | put_user_ex(regs->r14, &sc->r14); |
162 | err |= __put_user(regs->r15, &sc->r15); | 159 | put_user_ex(regs->r15, &sc->r15); |
163 | #endif /* CONFIG_X86_64 */ | 160 | #endif /* CONFIG_X86_64 */ |
164 | 161 | ||
165 | err |= __put_user(current->thread.trap_no, &sc->trapno); | 162 | put_user_ex(current->thread.trap_no, &sc->trapno); |
166 | err |= __put_user(current->thread.error_code, &sc->err); | 163 | put_user_ex(current->thread.error_code, &sc->err); |
167 | err |= __put_user(regs->ip, &sc->ip); | 164 | put_user_ex(regs->ip, &sc->ip); |
168 | #ifdef CONFIG_X86_32 | 165 | #ifdef CONFIG_X86_32 |
169 | err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); | 166 | put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); |
170 | err |= __put_user(regs->flags, &sc->flags); | 167 | put_user_ex(regs->flags, &sc->flags); |
171 | err |= __put_user(regs->sp, &sc->sp_at_signal); | 168 | put_user_ex(regs->sp, &sc->sp_at_signal); |
172 | err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); | 169 | put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); |
173 | #else /* !CONFIG_X86_32 */ | 170 | #else /* !CONFIG_X86_32 */ |
174 | err |= __put_user(regs->flags, &sc->flags); | 171 | put_user_ex(regs->flags, &sc->flags); |
175 | err |= __put_user(regs->cs, &sc->cs); | 172 | put_user_ex(regs->cs, &sc->cs); |
176 | err |= __put_user(0, &sc->gs); | 173 | put_user_ex(0, &sc->gs); |
177 | err |= __put_user(0, &sc->fs); | 174 | put_user_ex(0, &sc->fs); |
178 | #endif /* CONFIG_X86_32 */ | 175 | #endif /* CONFIG_X86_32 */ |
179 | 176 | ||
180 | err |= __put_user(fpstate, &sc->fpstate); | 177 | put_user_ex(fpstate, &sc->fpstate); |
181 | 178 | ||
182 | /* non-iBCS2 extensions.. */ | 179 | /* non-iBCS2 extensions.. */ |
183 | err |= __put_user(mask, &sc->oldmask); | 180 | put_user_ex(mask, &sc->oldmask); |
184 | err |= __put_user(current->thread.cr2, &sc->cr2); | 181 | put_user_ex(current->thread.cr2, &sc->cr2); |
182 | } put_user_catch(err); | ||
185 | 183 | ||
186 | return err; | 184 | return err; |
187 | } | 185 | } |
@@ -336,43 +334,41 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
336 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 334 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
337 | return -EFAULT; | 335 | return -EFAULT; |
338 | 336 | ||
339 | err |= __put_user(sig, &frame->sig); | 337 | put_user_try { |
340 | err |= __put_user(&frame->info, &frame->pinfo); | 338 | put_user_ex(sig, &frame->sig); |
341 | err |= __put_user(&frame->uc, &frame->puc); | 339 | put_user_ex(&frame->info, &frame->pinfo); |
342 | err |= copy_siginfo_to_user(&frame->info, info); | 340 | put_user_ex(&frame->uc, &frame->puc); |
343 | if (err) | 341 | err |= copy_siginfo_to_user(&frame->info, info); |
344 | return -EFAULT; | ||
345 | |||
346 | /* Create the ucontext. */ | ||
347 | if (cpu_has_xsave) | ||
348 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | ||
349 | else | ||
350 | err |= __put_user(0, &frame->uc.uc_flags); | ||
351 | err |= __put_user(0, &frame->uc.uc_link); | ||
352 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
353 | err |= __put_user(sas_ss_flags(regs->sp), | ||
354 | &frame->uc.uc_stack.ss_flags); | ||
355 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
356 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
357 | regs, set->sig[0]); | ||
358 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
359 | if (err) | ||
360 | return -EFAULT; | ||
361 | 342 | ||
362 | /* Set up to return from userspace. */ | 343 | /* Create the ucontext. */ |
363 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); | 344 | if (cpu_has_xsave) |
364 | if (ka->sa.sa_flags & SA_RESTORER) | 345 | put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); |
365 | restorer = ka->sa.sa_restorer; | 346 | else |
366 | err |= __put_user(restorer, &frame->pretcode); | 347 | put_user_ex(0, &frame->uc.uc_flags); |
348 | put_user_ex(0, &frame->uc.uc_link); | ||
349 | put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
350 | put_user_ex(sas_ss_flags(regs->sp), | ||
351 | &frame->uc.uc_stack.ss_flags); | ||
352 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
353 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
354 | regs, set->sig[0]); | ||
355 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
356 | |||
357 | /* Set up to return from userspace. */ | ||
358 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); | ||
359 | if (ka->sa.sa_flags & SA_RESTORER) | ||
360 | restorer = ka->sa.sa_restorer; | ||
361 | put_user_ex(restorer, &frame->pretcode); | ||
367 | 362 | ||
368 | /* | 363 | /* |
369 | * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 | 364 | * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 |
370 | * | 365 | * |
371 | * WE DO NOT USE IT ANY MORE! It's only left here for historical | 366 | * WE DO NOT USE IT ANY MORE! It's only left here for historical |
372 | * reasons and because gdb uses it as a signature to notice | 367 | * reasons and because gdb uses it as a signature to notice |
373 | * signal handler stack frames. | 368 | * signal handler stack frames. |
374 | */ | 369 | */ |
375 | err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode); | 370 | put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); |
371 | } put_user_catch(err); | ||
376 | 372 | ||
377 | if (err) | 373 | if (err) |
378 | return -EFAULT; | 374 | return -EFAULT; |
@@ -436,28 +432,30 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
436 | return -EFAULT; | 432 | return -EFAULT; |
437 | } | 433 | } |
438 | 434 | ||
439 | /* Create the ucontext. */ | 435 | put_user_try { |
440 | if (cpu_has_xsave) | 436 | /* Create the ucontext. */ |
441 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | 437 | if (cpu_has_xsave) |
442 | else | 438 | put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); |
443 | err |= __put_user(0, &frame->uc.uc_flags); | 439 | else |
444 | err |= __put_user(0, &frame->uc.uc_link); | 440 | put_user_ex(0, &frame->uc.uc_flags); |
445 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 441 | put_user_ex(0, &frame->uc.uc_link); |
446 | err |= __put_user(sas_ss_flags(regs->sp), | 442 | put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
447 | &frame->uc.uc_stack.ss_flags); | 443 | put_user_ex(sas_ss_flags(regs->sp), |
448 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | 444 | &frame->uc.uc_stack.ss_flags); |
449 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); | 445 | put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size); |
450 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 446 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); |
451 | 447 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | |
452 | /* Set up to return from userspace. If provided, use a stub | 448 | |
453 | already in userspace. */ | 449 | /* Set up to return from userspace. If provided, use a stub |
454 | /* x86-64 should always use SA_RESTORER. */ | 450 | already in userspace. */ |
455 | if (ka->sa.sa_flags & SA_RESTORER) { | 451 | /* x86-64 should always use SA_RESTORER. */ |
456 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 452 | if (ka->sa.sa_flags & SA_RESTORER) { |
457 | } else { | 453 | put_user_ex(ka->sa.sa_restorer, &frame->pretcode); |
458 | /* could use a vstub here */ | 454 | } else { |
459 | return -EFAULT; | 455 | /* could use a vstub here */ |
460 | } | 456 | err |= -EFAULT; |
457 | } | ||
458 | } put_user_catch(err); | ||
461 | 459 | ||
462 | if (err) | 460 | if (err) |
463 | return -EFAULT; | 461 | return -EFAULT; |
@@ -509,31 +507,41 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
509 | struct old_sigaction __user *oact) | 507 | struct old_sigaction __user *oact) |
510 | { | 508 | { |
511 | struct k_sigaction new_ka, old_ka; | 509 | struct k_sigaction new_ka, old_ka; |
512 | int ret; | 510 | int ret = 0; |
513 | 511 | ||
514 | if (act) { | 512 | if (act) { |
515 | old_sigset_t mask; | 513 | old_sigset_t mask; |
516 | 514 | ||
517 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 515 | if (!access_ok(VERIFY_READ, act, sizeof(*act))) |
518 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | ||
519 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | ||
520 | return -EFAULT; | 516 | return -EFAULT; |
521 | 517 | ||
522 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | 518 | get_user_try { |
523 | __get_user(mask, &act->sa_mask); | 519 | get_user_ex(new_ka.sa.sa_handler, &act->sa_handler); |
520 | get_user_ex(new_ka.sa.sa_flags, &act->sa_flags); | ||
521 | get_user_ex(mask, &act->sa_mask); | ||
522 | get_user_ex(new_ka.sa.sa_restorer, &act->sa_restorer); | ||
523 | } get_user_catch(ret); | ||
524 | |||
525 | if (ret) | ||
526 | return -EFAULT; | ||
524 | siginitset(&new_ka.sa.sa_mask, mask); | 527 | siginitset(&new_ka.sa.sa_mask, mask); |
525 | } | 528 | } |
526 | 529 | ||
527 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | 530 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); |
528 | 531 | ||
529 | if (!ret && oact) { | 532 | if (!ret && oact) { |
530 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 533 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) |
531 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | ||
532 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | ||
533 | return -EFAULT; | 534 | return -EFAULT; |
534 | 535 | ||
535 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | 536 | put_user_try { |
536 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | 537 | put_user_ex(old_ka.sa.sa_handler, &oact->sa_handler); |
538 | put_user_ex(old_ka.sa.sa_flags, &oact->sa_flags); | ||
539 | put_user_ex(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
540 | put_user_ex(old_ka.sa.sa_restorer, &oact->sa_restorer); | ||
541 | } put_user_catch(ret); | ||
542 | |||
543 | if (ret) | ||
544 | return -EFAULT; | ||
537 | } | 545 | } |
538 | 546 | ||
539 | return ret; | 547 | return ret; |
@@ -541,14 +549,9 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
541 | #endif /* CONFIG_X86_32 */ | 549 | #endif /* CONFIG_X86_32 */ |
542 | 550 | ||
543 | #ifdef CONFIG_X86_32 | 551 | #ifdef CONFIG_X86_32 |
544 | asmlinkage int sys_sigaltstack(unsigned long bx) | 552 | int sys_sigaltstack(struct pt_regs *regs) |
545 | { | 553 | { |
546 | /* | 554 | const stack_t __user *uss = (const stack_t __user *)regs->bx; |
547 | * This is needed to make gcc realize it doesn't own the | ||
548 | * "struct pt_regs" | ||
549 | */ | ||
550 | struct pt_regs *regs = (struct pt_regs *)&bx; | ||
551 | const stack_t __user *uss = (const stack_t __user *)bx; | ||
552 | stack_t __user *uoss = (stack_t __user *)regs->cx; | 555 | stack_t __user *uoss = (stack_t __user *)regs->cx; |
553 | 556 | ||
554 | return do_sigaltstack(uss, uoss, regs->sp); | 557 | return do_sigaltstack(uss, uoss, regs->sp); |
@@ -566,14 +569,12 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
566 | * Do a signal return; undo the signal stack. | 569 | * Do a signal return; undo the signal stack. |
567 | */ | 570 | */ |
568 | #ifdef CONFIG_X86_32 | 571 | #ifdef CONFIG_X86_32 |
569 | asmlinkage unsigned long sys_sigreturn(unsigned long __unused) | 572 | unsigned long sys_sigreturn(struct pt_regs *regs) |
570 | { | 573 | { |
571 | struct sigframe __user *frame; | 574 | struct sigframe __user *frame; |
572 | struct pt_regs *regs; | ||
573 | unsigned long ax; | 575 | unsigned long ax; |
574 | sigset_t set; | 576 | sigset_t set; |
575 | 577 | ||
576 | regs = (struct pt_regs *) &__unused; | ||
577 | frame = (struct sigframe __user *)(regs->sp - 8); | 578 | frame = (struct sigframe __user *)(regs->sp - 8); |
578 | 579 | ||
579 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 580 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -600,7 +601,7 @@ badframe: | |||
600 | } | 601 | } |
601 | #endif /* CONFIG_X86_32 */ | 602 | #endif /* CONFIG_X86_32 */ |
602 | 603 | ||
603 | static long do_rt_sigreturn(struct pt_regs *regs) | 604 | long sys_rt_sigreturn(struct pt_regs *regs) |
604 | { | 605 | { |
605 | struct rt_sigframe __user *frame; | 606 | struct rt_sigframe __user *frame; |
606 | unsigned long ax; | 607 | unsigned long ax; |
@@ -631,25 +632,6 @@ badframe: | |||
631 | return 0; | 632 | return 0; |
632 | } | 633 | } |
633 | 634 | ||
634 | #ifdef CONFIG_X86_32 | ||
635 | /* | ||
636 | * Note: do not pass in pt_regs directly as with tail-call optimization | ||
637 | * GCC will incorrectly stomp on the caller's frame and corrupt user-space | ||
638 | * register state: | ||
639 | */ | ||
640 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | ||
641 | { | ||
642 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
643 | |||
644 | return do_rt_sigreturn(regs); | ||
645 | } | ||
646 | #else /* !CONFIG_X86_32 */ | ||
647 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | ||
648 | { | ||
649 | return do_rt_sigreturn(regs); | ||
650 | } | ||
651 | #endif /* CONFIG_X86_32 */ | ||
652 | |||
653 | /* | 635 | /* |
654 | * OK, we're invoking a handler: | 636 | * OK, we're invoking a handler: |
655 | */ | 637 | */ |