diff options
Diffstat (limited to 'arch/x86/ia32/ia32_signal.c')
| -rw-r--r-- | arch/x86/ia32/ia32_signal.c | 405 |
1 files changed, 207 insertions, 198 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 9dabd00e9805..588a7aa937e1 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
| @@ -33,8 +33,6 @@ | |||
| 33 | #include <asm/sigframe.h> | 33 | #include <asm/sigframe.h> |
| 34 | #include <asm/sys_ia32.h> | 34 | #include <asm/sys_ia32.h> |
| 35 | 35 | ||
| 36 | #define DEBUG_SIG 0 | ||
| 37 | |||
| 38 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 36 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
| 39 | 37 | ||
| 40 | #define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \ | 38 | #define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \ |
| @@ -46,78 +44,83 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where); | |||
| 46 | 44 | ||
| 47 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 45 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) |
| 48 | { | 46 | { |
| 49 | int err; | 47 | int err = 0; |
| 50 | 48 | ||
| 51 | if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) | 49 | if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) |
| 52 | return -EFAULT; | 50 | return -EFAULT; |
| 53 | 51 | ||
| 54 | /* If you change siginfo_t structure, please make sure that | 52 | put_user_try { |
| 55 | this code is fixed accordingly. | 53 | /* If you change siginfo_t structure, please make sure that |
| 56 | It should never copy any pad contained in the structure | 54 | this code is fixed accordingly. |
| 57 | to avoid security leaks, but must copy the generic | 55 | It should never copy any pad contained in the structure |
| 58 | 3 ints plus the relevant union member. */ | 56 | to avoid security leaks, but must copy the generic |
| 59 | err = __put_user(from->si_signo, &to->si_signo); | 57 | 3 ints plus the relevant union member. */ |
| 60 | err |= __put_user(from->si_errno, &to->si_errno); | 58 | put_user_ex(from->si_signo, &to->si_signo); |
| 61 | err |= __put_user((short)from->si_code, &to->si_code); | 59 | put_user_ex(from->si_errno, &to->si_errno); |
| 62 | 60 | put_user_ex((short)from->si_code, &to->si_code); | |
| 63 | if (from->si_code < 0) { | 61 | |
| 64 | err |= __put_user(from->si_pid, &to->si_pid); | 62 | if (from->si_code < 0) { |
| 65 | err |= __put_user(from->si_uid, &to->si_uid); | 63 | put_user_ex(from->si_pid, &to->si_pid); |
| 66 | err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); | 64 | put_user_ex(from->si_uid, &to->si_uid); |
| 67 | } else { | 65 | put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr); |
| 68 | /* | 66 | } else { |
| 69 | * First 32bits of unions are always present: | 67 | /* |
| 70 | * si_pid === si_band === si_tid === si_addr(LS half) | 68 | * First 32bits of unions are always present: |
| 71 | */ | 69 | * si_pid === si_band === si_tid === si_addr(LS half) |
| 72 | err |= __put_user(from->_sifields._pad[0], | 70 | */ |
| 73 | &to->_sifields._pad[0]); | 71 | put_user_ex(from->_sifields._pad[0], |
| 74 | switch (from->si_code >> 16) { | 72 | &to->_sifields._pad[0]); |
| 75 | case __SI_FAULT >> 16: | 73 | switch (from->si_code >> 16) { |
| 76 | break; | 74 | case __SI_FAULT >> 16: |
| 77 | case __SI_CHLD >> 16: | 75 | break; |
| 78 | err |= __put_user(from->si_utime, &to->si_utime); | 76 | case __SI_CHLD >> 16: |
| 79 | err |= __put_user(from->si_stime, &to->si_stime); | 77 | put_user_ex(from->si_utime, &to->si_utime); |
| 80 | err |= __put_user(from->si_status, &to->si_status); | 78 | put_user_ex(from->si_stime, &to->si_stime); |
| 81 | /* FALL THROUGH */ | 79 | put_user_ex(from->si_status, &to->si_status); |
| 82 | default: | 80 | /* FALL THROUGH */ |
| 83 | case __SI_KILL >> 16: | 81 | default: |
| 84 | err |= __put_user(from->si_uid, &to->si_uid); | 82 | case __SI_KILL >> 16: |
| 85 | break; | 83 | put_user_ex(from->si_uid, &to->si_uid); |
| 86 | case __SI_POLL >> 16: | 84 | break; |
| 87 | err |= __put_user(from->si_fd, &to->si_fd); | 85 | case __SI_POLL >> 16: |
| 88 | break; | 86 | put_user_ex(from->si_fd, &to->si_fd); |
| 89 | case __SI_TIMER >> 16: | 87 | break; |
| 90 | err |= __put_user(from->si_overrun, &to->si_overrun); | 88 | case __SI_TIMER >> 16: |
| 91 | err |= __put_user(ptr_to_compat(from->si_ptr), | 89 | put_user_ex(from->si_overrun, &to->si_overrun); |
| 92 | &to->si_ptr); | 90 | put_user_ex(ptr_to_compat(from->si_ptr), |
| 93 | break; | 91 | &to->si_ptr); |
| 94 | /* This is not generated by the kernel as of now. */ | 92 | break; |
| 95 | case __SI_RT >> 16: | 93 | /* This is not generated by the kernel as of now. */ |
| 96 | case __SI_MESGQ >> 16: | 94 | case __SI_RT >> 16: |
| 97 | err |= __put_user(from->si_uid, &to->si_uid); | 95 | case __SI_MESGQ >> 16: |
| 98 | err |= __put_user(from->si_int, &to->si_int); | 96 | put_user_ex(from->si_uid, &to->si_uid); |
| 99 | break; | 97 | put_user_ex(from->si_int, &to->si_int); |
| 98 | break; | ||
| 99 | } | ||
| 100 | } | 100 | } |
| 101 | } | 101 | } put_user_catch(err); |
| 102 | |||
| 102 | return err; | 103 | return err; |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | 106 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) |
| 106 | { | 107 | { |
| 107 | int err; | 108 | int err = 0; |
| 108 | u32 ptr32; | 109 | u32 ptr32; |
| 109 | 110 | ||
| 110 | if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) | 111 | if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) |
| 111 | return -EFAULT; | 112 | return -EFAULT; |
| 112 | 113 | ||
| 113 | err = __get_user(to->si_signo, &from->si_signo); | 114 | get_user_try { |
| 114 | err |= __get_user(to->si_errno, &from->si_errno); | 115 | get_user_ex(to->si_signo, &from->si_signo); |
| 115 | err |= __get_user(to->si_code, &from->si_code); | 116 | get_user_ex(to->si_errno, &from->si_errno); |
| 117 | get_user_ex(to->si_code, &from->si_code); | ||
| 116 | 118 | ||
| 117 | err |= __get_user(to->si_pid, &from->si_pid); | 119 | get_user_ex(to->si_pid, &from->si_pid); |
| 118 | err |= __get_user(to->si_uid, &from->si_uid); | 120 | get_user_ex(to->si_uid, &from->si_uid); |
| 119 | err |= __get_user(ptr32, &from->si_ptr); | 121 | get_user_ex(ptr32, &from->si_ptr); |
| 120 | to->si_ptr = compat_ptr(ptr32); | 122 | to->si_ptr = compat_ptr(ptr32); |
| 123 | } get_user_catch(err); | ||
| 121 | 124 | ||
| 122 | return err; | 125 | return err; |
| 123 | } | 126 | } |
| @@ -142,17 +145,23 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | |||
| 142 | struct pt_regs *regs) | 145 | struct pt_regs *regs) |
| 143 | { | 146 | { |
| 144 | stack_t uss, uoss; | 147 | stack_t uss, uoss; |
| 145 | int ret; | 148 | int ret, err = 0; |
| 146 | mm_segment_t seg; | 149 | mm_segment_t seg; |
| 147 | 150 | ||
| 148 | if (uss_ptr) { | 151 | if (uss_ptr) { |
| 149 | u32 ptr; | 152 | u32 ptr; |
| 150 | 153 | ||
| 151 | memset(&uss, 0, sizeof(stack_t)); | 154 | memset(&uss, 0, sizeof(stack_t)); |
| 152 | if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) || | 155 | if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t))) |
| 153 | __get_user(ptr, &uss_ptr->ss_sp) || | 156 | return -EFAULT; |
| 154 | __get_user(uss.ss_flags, &uss_ptr->ss_flags) || | 157 | |
| 155 | __get_user(uss.ss_size, &uss_ptr->ss_size)) | 158 | get_user_try { |
| 159 | get_user_ex(ptr, &uss_ptr->ss_sp); | ||
| 160 | get_user_ex(uss.ss_flags, &uss_ptr->ss_flags); | ||
| 161 | get_user_ex(uss.ss_size, &uss_ptr->ss_size); | ||
| 162 | } get_user_catch(err); | ||
| 163 | |||
| 164 | if (err) | ||
| 156 | return -EFAULT; | 165 | return -EFAULT; |
| 157 | uss.ss_sp = compat_ptr(ptr); | 166 | uss.ss_sp = compat_ptr(ptr); |
| 158 | } | 167 | } |
| @@ -161,10 +170,16 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | |||
| 161 | ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); | 170 | ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); |
| 162 | set_fs(seg); | 171 | set_fs(seg); |
| 163 | if (ret >= 0 && uoss_ptr) { | 172 | if (ret >= 0 && uoss_ptr) { |
| 164 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) || | 173 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) |
| 165 | __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || | 174 | return -EFAULT; |
| 166 | __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || | 175 | |
| 167 | __put_user(uoss.ss_size, &uoss_ptr->ss_size)) | 176 | put_user_try { |
| 177 | put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp); | ||
| 178 | put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags); | ||
| 179 | put_user_ex(uoss.ss_size, &uoss_ptr->ss_size); | ||
| 180 | } put_user_catch(err); | ||
| 181 | |||
| 182 | if (err) | ||
| 168 | ret = -EFAULT; | 183 | ret = -EFAULT; |
| 169 | } | 184 | } |
| 170 | return ret; | 185 | return ret; |
| @@ -173,75 +188,78 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | |||
| 173 | /* | 188 | /* |
| 174 | * Do a signal return; undo the signal stack. | 189 | * Do a signal return; undo the signal stack. |
| 175 | */ | 190 | */ |
| 191 | #define loadsegment_gs(v) load_gs_index(v) | ||
| 192 | #define loadsegment_fs(v) loadsegment(fs, v) | ||
| 193 | #define loadsegment_ds(v) loadsegment(ds, v) | ||
| 194 | #define loadsegment_es(v) loadsegment(es, v) | ||
| 195 | |||
| 196 | #define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; }) | ||
| 197 | #define set_user_seg(seg, v) loadsegment_##seg(v) | ||
| 198 | |||
| 176 | #define COPY(x) { \ | 199 | #define COPY(x) { \ |
| 177 | err |= __get_user(regs->x, &sc->x); \ | 200 | get_user_ex(regs->x, &sc->x); \ |
| 178 | } | 201 | } |
| 179 | 202 | ||
| 180 | #define COPY_SEG_CPL3(seg) { \ | 203 | #define GET_SEG(seg) ({ \ |
| 181 | unsigned short tmp; \ | 204 | unsigned short tmp; \ |
| 182 | err |= __get_user(tmp, &sc->seg); \ | 205 | get_user_ex(tmp, &sc->seg); \ |
| 183 | regs->seg = tmp | 3; \ | 206 | tmp; \ |
| 184 | } | 207 | }) |
| 208 | |||
| 209 | #define COPY_SEG_CPL3(seg) do { \ | ||
| 210 | regs->seg = GET_SEG(seg) | 3; \ | ||
| 211 | } while (0) | ||
| 185 | 212 | ||
| 186 | #define RELOAD_SEG(seg) { \ | 213 | #define RELOAD_SEG(seg) { \ |
| 187 | unsigned int cur, pre; \ | 214 | unsigned int pre = GET_SEG(seg); \ |
| 188 | err |= __get_user(pre, &sc->seg); \ | 215 | unsigned int cur = get_user_seg(seg); \ |
| 189 | savesegment(seg, cur); \ | ||
| 190 | pre |= 3; \ | 216 | pre |= 3; \ |
| 191 | if (pre != cur) \ | 217 | if (pre != cur) \ |
| 192 | loadsegment(seg, pre); \ | 218 | set_user_seg(seg, pre); \ |
| 193 | } | 219 | } |
| 194 | 220 | ||
| 195 | static int ia32_restore_sigcontext(struct pt_regs *regs, | 221 | static int ia32_restore_sigcontext(struct pt_regs *regs, |
| 196 | struct sigcontext_ia32 __user *sc, | 222 | struct sigcontext_ia32 __user *sc, |
| 197 | unsigned int *pax) | 223 | unsigned int *pax) |
| 198 | { | 224 | { |
| 199 | unsigned int tmpflags, gs, oldgs, err = 0; | 225 | unsigned int tmpflags, err = 0; |
| 200 | void __user *buf; | 226 | void __user *buf; |
| 201 | u32 tmp; | 227 | u32 tmp; |
| 202 | 228 | ||
| 203 | /* Always make any pending restarted system calls return -EINTR */ | 229 | /* Always make any pending restarted system calls return -EINTR */ |
| 204 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 230 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 205 | 231 | ||
| 206 | #if DEBUG_SIG | 232 | get_user_try { |
| 207 | printk(KERN_DEBUG "SIG restore_sigcontext: " | 233 | /* |
| 208 | "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n", | 234 | * Reload fs and gs if they have changed in the signal |
| 209 | sc, sc->err, sc->ip, sc->cs, sc->flags); | 235 | * handler. This does not handle long fs/gs base changes in |
| 210 | #endif | 236 | * the handler, but does not clobber them at least in the |
| 211 | 237 | * normal case. | |
| 212 | /* | 238 | */ |
| 213 | * Reload fs and gs if they have changed in the signal | 239 | RELOAD_SEG(gs); |
| 214 | * handler. This does not handle long fs/gs base changes in | 240 | RELOAD_SEG(fs); |
| 215 | * the handler, but does not clobber them at least in the | 241 | RELOAD_SEG(ds); |
| 216 | * normal case. | 242 | RELOAD_SEG(es); |
| 217 | */ | 243 | |
| 218 | err |= __get_user(gs, &sc->gs); | 244 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
| 219 | gs |= 3; | 245 | COPY(dx); COPY(cx); COPY(ip); |
| 220 | savesegment(gs, oldgs); | 246 | /* Don't touch extended registers */ |
| 221 | if (gs != oldgs) | 247 | |
| 222 | load_gs_index(gs); | 248 | COPY_SEG_CPL3(cs); |
| 223 | 249 | COPY_SEG_CPL3(ss); | |
| 224 | RELOAD_SEG(fs); | 250 | |
| 225 | RELOAD_SEG(ds); | 251 | get_user_ex(tmpflags, &sc->flags); |
| 226 | RELOAD_SEG(es); | 252 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
| 227 | 253 | /* disable syscall checks */ | |
| 228 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 254 | regs->orig_ax = -1; |
| 229 | COPY(dx); COPY(cx); COPY(ip); | 255 | |
| 230 | /* Don't touch extended registers */ | 256 | get_user_ex(tmp, &sc->fpstate); |
| 231 | 257 | buf = compat_ptr(tmp); | |
| 232 | COPY_SEG_CPL3(cs); | 258 | err |= restore_i387_xstate_ia32(buf); |
| 233 | COPY_SEG_CPL3(ss); | 259 | |
| 234 | 260 | get_user_ex(*pax, &sc->ax); | |
| 235 | err |= __get_user(tmpflags, &sc->flags); | 261 | } get_user_catch(err); |
| 236 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); | 262 | |
| 237 | /* disable syscall checks */ | ||
| 238 | regs->orig_ax = -1; | ||
| 239 | |||
| 240 | err |= __get_user(tmp, &sc->fpstate); | ||
| 241 | buf = compat_ptr(tmp); | ||
| 242 | err |= restore_i387_xstate_ia32(buf); | ||
| 243 | |||
| 244 | err |= __get_user(*pax, &sc->ax); | ||
| 245 | return err; | 263 | return err; |
| 246 | } | 264 | } |
| 247 | 265 | ||
| @@ -317,38 +335,36 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, | |||
| 317 | void __user *fpstate, | 335 | void __user *fpstate, |
| 318 | struct pt_regs *regs, unsigned int mask) | 336 | struct pt_regs *regs, unsigned int mask) |
| 319 | { | 337 | { |
| 320 | int tmp, err = 0; | 338 | int err = 0; |
| 321 | 339 | ||
| 322 | savesegment(gs, tmp); | 340 | put_user_try { |
| 323 | err |= __put_user(tmp, (unsigned int __user *)&sc->gs); | 341 | put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs); |
| 324 | savesegment(fs, tmp); | 342 | put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs); |
| 325 | err |= __put_user(tmp, (unsigned int __user *)&sc->fs); | 343 | put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds); |
| 326 | savesegment(ds, tmp); | 344 | put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es); |
| 327 | err |= __put_user(tmp, (unsigned int __user *)&sc->ds); | 345 | |
| 328 | savesegment(es, tmp); | 346 | put_user_ex(regs->di, &sc->di); |
| 329 | err |= __put_user(tmp, (unsigned int __user *)&sc->es); | 347 | put_user_ex(regs->si, &sc->si); |
| 330 | 348 | put_user_ex(regs->bp, &sc->bp); | |
| 331 | err |= __put_user(regs->di, &sc->di); | 349 | put_user_ex(regs->sp, &sc->sp); |
| 332 | err |= __put_user(regs->si, &sc->si); | 350 | put_user_ex(regs->bx, &sc->bx); |
| 333 | err |= __put_user(regs->bp, &sc->bp); | 351 | put_user_ex(regs->dx, &sc->dx); |
| 334 | err |= __put_user(regs->sp, &sc->sp); | 352 | put_user_ex(regs->cx, &sc->cx); |
| 335 | err |= __put_user(regs->bx, &sc->bx); | 353 | put_user_ex(regs->ax, &sc->ax); |
| 336 | err |= __put_user(regs->dx, &sc->dx); | 354 | put_user_ex(current->thread.trap_no, &sc->trapno); |
| 337 | err |= __put_user(regs->cx, &sc->cx); | 355 | put_user_ex(current->thread.error_code, &sc->err); |
| 338 | err |= __put_user(regs->ax, &sc->ax); | 356 | put_user_ex(regs->ip, &sc->ip); |
| 339 | err |= __put_user(current->thread.trap_no, &sc->trapno); | 357 | put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); |
| 340 | err |= __put_user(current->thread.error_code, &sc->err); | 358 | put_user_ex(regs->flags, &sc->flags); |
| 341 | err |= __put_user(regs->ip, &sc->ip); | 359 | put_user_ex(regs->sp, &sc->sp_at_signal); |
| 342 | err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); | 360 | put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); |
| 343 | err |= __put_user(regs->flags, &sc->flags); | 361 | |
| 344 | err |= __put_user(regs->sp, &sc->sp_at_signal); | 362 | put_user_ex(ptr_to_compat(fpstate), &sc->fpstate); |
| 345 | err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); | 363 | |
| 346 | 364 | /* non-iBCS2 extensions.. */ | |
| 347 | err |= __put_user(ptr_to_compat(fpstate), &sc->fpstate); | 365 | put_user_ex(mask, &sc->oldmask); |
| 348 | 366 | put_user_ex(current->thread.cr2, &sc->cr2); | |
| 349 | /* non-iBCS2 extensions.. */ | 367 | } put_user_catch(err); |
| 350 | err |= __put_user(mask, &sc->oldmask); | ||
| 351 | err |= __put_user(current->thread.cr2, &sc->cr2); | ||
| 352 | 368 | ||
| 353 | return err; | 369 | return err; |
| 354 | } | 370 | } |
| @@ -437,13 +453,17 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
| 437 | else | 453 | else |
| 438 | restorer = &frame->retcode; | 454 | restorer = &frame->retcode; |
| 439 | } | 455 | } |
| 440 | err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); | ||
| 441 | 456 | ||
| 442 | /* | 457 | put_user_try { |
| 443 | * These are actually not used anymore, but left because some | 458 | put_user_ex(ptr_to_compat(restorer), &frame->pretcode); |
| 444 | * gdb versions depend on them as a marker. | 459 | |
| 445 | */ | 460 | /* |
| 446 | err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode); | 461 | * These are actually not used anymore, but left because some |
| 462 | * gdb versions depend on them as a marker. | ||
| 463 | */ | ||
| 464 | put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); | ||
| 465 | } put_user_catch(err); | ||
| 466 | |||
| 447 | if (err) | 467 | if (err) |
| 448 | return -EFAULT; | 468 | return -EFAULT; |
| 449 | 469 | ||
| @@ -462,11 +482,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
| 462 | regs->cs = __USER32_CS; | 482 | regs->cs = __USER32_CS; |
| 463 | regs->ss = __USER32_DS; | 483 | regs->ss = __USER32_DS; |
| 464 | 484 | ||
| 465 | #if DEBUG_SIG | ||
| 466 | printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", | ||
| 467 | current->comm, current->pid, frame, regs->ip, frame->pretcode); | ||
| 468 | #endif | ||
| 469 | |||
| 470 | return 0; | 485 | return 0; |
| 471 | } | 486 | } |
| 472 | 487 | ||
| @@ -496,41 +511,40 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 496 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 511 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 497 | return -EFAULT; | 512 | return -EFAULT; |
| 498 | 513 | ||
| 499 | err |= __put_user(sig, &frame->sig); | 514 | put_user_try { |
| 500 | err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); | 515 | put_user_ex(sig, &frame->sig); |
| 501 | err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); | 516 | put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo); |
| 502 | err |= copy_siginfo_to_user32(&frame->info, info); | 517 | put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); |
| 503 | if (err) | 518 | err |= copy_siginfo_to_user32(&frame->info, info); |
| 504 | return -EFAULT; | ||
| 505 | 519 | ||
| 506 | /* Create the ucontext. */ | 520 | /* Create the ucontext. */ |
| 507 | if (cpu_has_xsave) | 521 | if (cpu_has_xsave) |
| 508 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | 522 | put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); |
| 509 | else | 523 | else |
| 510 | err |= __put_user(0, &frame->uc.uc_flags); | 524 | put_user_ex(0, &frame->uc.uc_flags); |
| 511 | err |= __put_user(0, &frame->uc.uc_link); | 525 | put_user_ex(0, &frame->uc.uc_link); |
| 512 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 526 | put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
| 513 | err |= __put_user(sas_ss_flags(regs->sp), | 527 | put_user_ex(sas_ss_flags(regs->sp), |
| 514 | &frame->uc.uc_stack.ss_flags); | 528 | &frame->uc.uc_stack.ss_flags); |
| 515 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 529 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
| 516 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | 530 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
| 517 | regs, set->sig[0]); | 531 | regs, set->sig[0]); |
| 518 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 532 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
| 519 | if (err) | 533 | |
| 520 | return -EFAULT; | 534 | if (ka->sa.sa_flags & SA_RESTORER) |
| 535 | restorer = ka->sa.sa_restorer; | ||
| 536 | else | ||
| 537 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, | ||
| 538 | rt_sigreturn); | ||
| 539 | put_user_ex(ptr_to_compat(restorer), &frame->pretcode); | ||
| 540 | |||
| 541 | /* | ||
| 542 | * Not actually used anymore, but left because some gdb | ||
| 543 | * versions need it. | ||
| 544 | */ | ||
| 545 | put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); | ||
| 546 | } put_user_catch(err); | ||
| 521 | 547 | ||
| 522 | if (ka->sa.sa_flags & SA_RESTORER) | ||
| 523 | restorer = ka->sa.sa_restorer; | ||
| 524 | else | ||
| 525 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, | ||
| 526 | rt_sigreturn); | ||
| 527 | err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); | ||
| 528 | |||
| 529 | /* | ||
| 530 | * Not actually used anymore, but left because some gdb | ||
| 531 | * versions need it. | ||
| 532 | */ | ||
| 533 | err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode); | ||
| 534 | if (err) | 548 | if (err) |
| 535 | return -EFAULT; | 549 | return -EFAULT; |
| 536 | 550 | ||
| @@ -549,10 +563,5 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 549 | regs->cs = __USER32_CS; | 563 | regs->cs = __USER32_CS; |
| 550 | regs->ss = __USER32_DS; | 564 | regs->ss = __USER32_DS; |
| 551 | 565 | ||
| 552 | #if DEBUG_SIG | ||
| 553 | printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", | ||
| 554 | current->comm, current->pid, frame, regs->ip, frame->pretcode); | ||
| 555 | #endif | ||
| 556 | |||
| 557 | return 0; | 566 | return 0; |
| 558 | } | 567 | } |
