diff options
Diffstat (limited to 'arch/x86/kernel/signal_32.c')
-rw-r--r-- | arch/x86/kernel/signal_32.c | 225 |
1 files changed, 117 insertions, 108 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 20f29e4c1d33..caee1f002fed 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/ucontext.h> | 23 | #include <asm/ucontext.h> |
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/i387.h> | 25 | #include <asm/i387.h> |
26 | #include <asm/vdso.h> | ||
26 | #include "sigframe_32.h" | 27 | #include "sigframe_32.h" |
27 | 28 | ||
28 | #define DEBUG_SIG 0 | 29 | #define DEBUG_SIG 0 |
@@ -81,14 +82,14 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
81 | } | 82 | } |
82 | 83 | ||
83 | asmlinkage int | 84 | asmlinkage int |
84 | sys_sigaltstack(unsigned long ebx) | 85 | sys_sigaltstack(unsigned long bx) |
85 | { | 86 | { |
86 | /* This is needed to make gcc realize it doesn't own the "struct pt_regs" */ | 87 | /* This is needed to make gcc realize it doesn't own the "struct pt_regs" */ |
87 | struct pt_regs *regs = (struct pt_regs *)&ebx; | 88 | struct pt_regs *regs = (struct pt_regs *)&bx; |
88 | const stack_t __user *uss = (const stack_t __user *)ebx; | 89 | const stack_t __user *uss = (const stack_t __user *)bx; |
89 | stack_t __user *uoss = (stack_t __user *)regs->ecx; | 90 | stack_t __user *uoss = (stack_t __user *)regs->cx; |
90 | 91 | ||
91 | return do_sigaltstack(uss, uoss, regs->esp); | 92 | return do_sigaltstack(uss, uoss, regs->sp); |
92 | } | 93 | } |
93 | 94 | ||
94 | 95 | ||
@@ -109,12 +110,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax | |||
109 | #define COPY_SEG(seg) \ | 110 | #define COPY_SEG(seg) \ |
110 | { unsigned short tmp; \ | 111 | { unsigned short tmp; \ |
111 | err |= __get_user(tmp, &sc->seg); \ | 112 | err |= __get_user(tmp, &sc->seg); \ |
112 | regs->x##seg = tmp; } | 113 | regs->seg = tmp; } |
113 | 114 | ||
114 | #define COPY_SEG_STRICT(seg) \ | 115 | #define COPY_SEG_STRICT(seg) \ |
115 | { unsigned short tmp; \ | 116 | { unsigned short tmp; \ |
116 | err |= __get_user(tmp, &sc->seg); \ | 117 | err |= __get_user(tmp, &sc->seg); \ |
117 | regs->x##seg = tmp|3; } | 118 | regs->seg = tmp|3; } |
118 | 119 | ||
119 | #define GET_SEG(seg) \ | 120 | #define GET_SEG(seg) \ |
120 | { unsigned short tmp; \ | 121 | { unsigned short tmp; \ |
@@ -130,22 +131,22 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax | |||
130 | COPY_SEG(fs); | 131 | COPY_SEG(fs); |
131 | COPY_SEG(es); | 132 | COPY_SEG(es); |
132 | COPY_SEG(ds); | 133 | COPY_SEG(ds); |
133 | COPY(edi); | 134 | COPY(di); |
134 | COPY(esi); | 135 | COPY(si); |
135 | COPY(ebp); | 136 | COPY(bp); |
136 | COPY(esp); | 137 | COPY(sp); |
137 | COPY(ebx); | 138 | COPY(bx); |
138 | COPY(edx); | 139 | COPY(dx); |
139 | COPY(ecx); | 140 | COPY(cx); |
140 | COPY(eip); | 141 | COPY(ip); |
141 | COPY_SEG_STRICT(cs); | 142 | COPY_SEG_STRICT(cs); |
142 | COPY_SEG_STRICT(ss); | 143 | COPY_SEG_STRICT(ss); |
143 | 144 | ||
144 | { | 145 | { |
145 | unsigned int tmpflags; | 146 | unsigned int tmpflags; |
146 | err |= __get_user(tmpflags, &sc->eflags); | 147 | err |= __get_user(tmpflags, &sc->flags); |
147 | regs->eflags = (regs->eflags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); | 148 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
148 | regs->orig_eax = -1; /* disable syscall checks */ | 149 | regs->orig_ax = -1; /* disable syscall checks */ |
149 | } | 150 | } |
150 | 151 | ||
151 | { | 152 | { |
@@ -164,7 +165,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax | |||
164 | } | 165 | } |
165 | } | 166 | } |
166 | 167 | ||
167 | err |= __get_user(*peax, &sc->eax); | 168 | err |= __get_user(*peax, &sc->ax); |
168 | return err; | 169 | return err; |
169 | 170 | ||
170 | badframe: | 171 | badframe: |
@@ -174,9 +175,9 @@ badframe: | |||
174 | asmlinkage int sys_sigreturn(unsigned long __unused) | 175 | asmlinkage int sys_sigreturn(unsigned long __unused) |
175 | { | 176 | { |
176 | struct pt_regs *regs = (struct pt_regs *) &__unused; | 177 | struct pt_regs *regs = (struct pt_regs *) &__unused; |
177 | struct sigframe __user *frame = (struct sigframe __user *)(regs->esp - 8); | 178 | struct sigframe __user *frame = (struct sigframe __user *)(regs->sp - 8); |
178 | sigset_t set; | 179 | sigset_t set; |
179 | int eax; | 180 | int ax; |
180 | 181 | ||
181 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 182 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
182 | goto badframe; | 183 | goto badframe; |
@@ -192,17 +193,20 @@ asmlinkage int sys_sigreturn(unsigned long __unused) | |||
192 | recalc_sigpending(); | 193 | recalc_sigpending(); |
193 | spin_unlock_irq(¤t->sighand->siglock); | 194 | spin_unlock_irq(¤t->sighand->siglock); |
194 | 195 | ||
195 | if (restore_sigcontext(regs, &frame->sc, &eax)) | 196 | if (restore_sigcontext(regs, &frame->sc, &ax)) |
196 | goto badframe; | 197 | goto badframe; |
197 | return eax; | 198 | return ax; |
198 | 199 | ||
199 | badframe: | 200 | badframe: |
200 | if (show_unhandled_signals && printk_ratelimit()) | 201 | if (show_unhandled_signals && printk_ratelimit()) { |
201 | printk("%s%s[%d] bad frame in sigreturn frame:%p eip:%lx" | 202 | printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx" |
202 | " esp:%lx oeax:%lx\n", | 203 | " sp:%lx oeax:%lx", |
203 | task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, | 204 | task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, |
204 | current->comm, task_pid_nr(current), frame, regs->eip, | 205 | current->comm, task_pid_nr(current), frame, regs->ip, |
205 | regs->esp, regs->orig_eax); | 206 | regs->sp, regs->orig_ax); |
207 | print_vma_addr(" in ", regs->ip); | ||
208 | printk("\n"); | ||
209 | } | ||
206 | 210 | ||
207 | force_sig(SIGSEGV, current); | 211 | force_sig(SIGSEGV, current); |
208 | return 0; | 212 | return 0; |
@@ -211,9 +215,9 @@ badframe: | |||
211 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | 215 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) |
212 | { | 216 | { |
213 | struct pt_regs *regs = (struct pt_regs *) &__unused; | 217 | struct pt_regs *regs = (struct pt_regs *) &__unused; |
214 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->esp - 4); | 218 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->sp - 4); |
215 | sigset_t set; | 219 | sigset_t set; |
216 | int eax; | 220 | int ax; |
217 | 221 | ||
218 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 222 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
219 | goto badframe; | 223 | goto badframe; |
@@ -226,13 +230,13 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) | |||
226 | recalc_sigpending(); | 230 | recalc_sigpending(); |
227 | spin_unlock_irq(¤t->sighand->siglock); | 231 | spin_unlock_irq(¤t->sighand->siglock); |
228 | 232 | ||
229 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) | 233 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) |
230 | goto badframe; | 234 | goto badframe; |
231 | 235 | ||
232 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->esp) == -EFAULT) | 236 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) |
233 | goto badframe; | 237 | goto badframe; |
234 | 238 | ||
235 | return eax; | 239 | return ax; |
236 | 240 | ||
237 | badframe: | 241 | badframe: |
238 | force_sig(SIGSEGV, current); | 242 | force_sig(SIGSEGV, current); |
@@ -249,27 +253,27 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
249 | { | 253 | { |
250 | int tmp, err = 0; | 254 | int tmp, err = 0; |
251 | 255 | ||
252 | err |= __put_user(regs->xfs, (unsigned int __user *)&sc->fs); | 256 | err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs); |
253 | savesegment(gs, tmp); | 257 | savesegment(gs, tmp); |
254 | err |= __put_user(tmp, (unsigned int __user *)&sc->gs); | 258 | err |= __put_user(tmp, (unsigned int __user *)&sc->gs); |
255 | 259 | ||
256 | err |= __put_user(regs->xes, (unsigned int __user *)&sc->es); | 260 | err |= __put_user(regs->es, (unsigned int __user *)&sc->es); |
257 | err |= __put_user(regs->xds, (unsigned int __user *)&sc->ds); | 261 | err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds); |
258 | err |= __put_user(regs->edi, &sc->edi); | 262 | err |= __put_user(regs->di, &sc->di); |
259 | err |= __put_user(regs->esi, &sc->esi); | 263 | err |= __put_user(regs->si, &sc->si); |
260 | err |= __put_user(regs->ebp, &sc->ebp); | 264 | err |= __put_user(regs->bp, &sc->bp); |
261 | err |= __put_user(regs->esp, &sc->esp); | 265 | err |= __put_user(regs->sp, &sc->sp); |
262 | err |= __put_user(regs->ebx, &sc->ebx); | 266 | err |= __put_user(regs->bx, &sc->bx); |
263 | err |= __put_user(regs->edx, &sc->edx); | 267 | err |= __put_user(regs->dx, &sc->dx); |
264 | err |= __put_user(regs->ecx, &sc->ecx); | 268 | err |= __put_user(regs->cx, &sc->cx); |
265 | err |= __put_user(regs->eax, &sc->eax); | 269 | err |= __put_user(regs->ax, &sc->ax); |
266 | err |= __put_user(current->thread.trap_no, &sc->trapno); | 270 | err |= __put_user(current->thread.trap_no, &sc->trapno); |
267 | err |= __put_user(current->thread.error_code, &sc->err); | 271 | err |= __put_user(current->thread.error_code, &sc->err); |
268 | err |= __put_user(regs->eip, &sc->eip); | 272 | err |= __put_user(regs->ip, &sc->ip); |
269 | err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs); | 273 | err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); |
270 | err |= __put_user(regs->eflags, &sc->eflags); | 274 | err |= __put_user(regs->flags, &sc->flags); |
271 | err |= __put_user(regs->esp, &sc->esp_at_signal); | 275 | err |= __put_user(regs->sp, &sc->sp_at_signal); |
272 | err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss); | 276 | err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); |
273 | 277 | ||
274 | tmp = save_i387(fpstate); | 278 | tmp = save_i387(fpstate); |
275 | if (tmp < 0) | 279 | if (tmp < 0) |
@@ -290,29 +294,36 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
290 | static inline void __user * | 294 | static inline void __user * |
291 | get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) | 295 | get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) |
292 | { | 296 | { |
293 | unsigned long esp; | 297 | unsigned long sp; |
294 | 298 | ||
295 | /* Default to using normal stack */ | 299 | /* Default to using normal stack */ |
296 | esp = regs->esp; | 300 | sp = regs->sp; |
301 | |||
302 | /* | ||
303 | * If we are on the alternate signal stack and would overflow it, don't. | ||
304 | * Return an always-bogus address instead so we will die with SIGSEGV. | ||
305 | */ | ||
306 | if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) | ||
307 | return (void __user *) -1L; | ||
297 | 308 | ||
298 | /* This is the X/Open sanctioned signal stack switching. */ | 309 | /* This is the X/Open sanctioned signal stack switching. */ |
299 | if (ka->sa.sa_flags & SA_ONSTACK) { | 310 | if (ka->sa.sa_flags & SA_ONSTACK) { |
300 | if (sas_ss_flags(esp) == 0) | 311 | if (sas_ss_flags(sp) == 0) |
301 | esp = current->sas_ss_sp + current->sas_ss_size; | 312 | sp = current->sas_ss_sp + current->sas_ss_size; |
302 | } | 313 | } |
303 | 314 | ||
304 | /* This is the legacy signal stack switching. */ | 315 | /* This is the legacy signal stack switching. */ |
305 | else if ((regs->xss & 0xffff) != __USER_DS && | 316 | else if ((regs->ss & 0xffff) != __USER_DS && |
306 | !(ka->sa.sa_flags & SA_RESTORER) && | 317 | !(ka->sa.sa_flags & SA_RESTORER) && |
307 | ka->sa.sa_restorer) { | 318 | ka->sa.sa_restorer) { |
308 | esp = (unsigned long) ka->sa.sa_restorer; | 319 | sp = (unsigned long) ka->sa.sa_restorer; |
309 | } | 320 | } |
310 | 321 | ||
311 | esp -= frame_size; | 322 | sp -= frame_size; |
312 | /* Align the stack pointer according to the i386 ABI, | 323 | /* Align the stack pointer according to the i386 ABI, |
313 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ | 324 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ |
314 | esp = ((esp + 4) & -16ul) - 4; | 325 | sp = ((sp + 4) & -16ul) - 4; |
315 | return (void __user *) esp; | 326 | return (void __user *) sp; |
316 | } | 327 | } |
317 | 328 | ||
318 | /* These symbols are defined with the addresses in the vsyscall page. | 329 | /* These symbols are defined with the addresses in the vsyscall page. |
@@ -355,9 +366,9 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
355 | } | 366 | } |
356 | 367 | ||
357 | if (current->binfmt->hasvdso) | 368 | if (current->binfmt->hasvdso) |
358 | restorer = (void *)VDSO_SYM(&__kernel_sigreturn); | 369 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); |
359 | else | 370 | else |
360 | restorer = (void *)&frame->retcode; | 371 | restorer = &frame->retcode; |
361 | if (ka->sa.sa_flags & SA_RESTORER) | 372 | if (ka->sa.sa_flags & SA_RESTORER) |
362 | restorer = ka->sa.sa_restorer; | 373 | restorer = ka->sa.sa_restorer; |
363 | 374 | ||
@@ -379,16 +390,16 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
379 | goto give_sigsegv; | 390 | goto give_sigsegv; |
380 | 391 | ||
381 | /* Set up registers for signal handler */ | 392 | /* Set up registers for signal handler */ |
382 | regs->esp = (unsigned long) frame; | 393 | regs->sp = (unsigned long) frame; |
383 | regs->eip = (unsigned long) ka->sa.sa_handler; | 394 | regs->ip = (unsigned long) ka->sa.sa_handler; |
384 | regs->eax = (unsigned long) sig; | 395 | regs->ax = (unsigned long) sig; |
385 | regs->edx = (unsigned long) 0; | 396 | regs->dx = (unsigned long) 0; |
386 | regs->ecx = (unsigned long) 0; | 397 | regs->cx = (unsigned long) 0; |
387 | 398 | ||
388 | regs->xds = __USER_DS; | 399 | regs->ds = __USER_DS; |
389 | regs->xes = __USER_DS; | 400 | regs->es = __USER_DS; |
390 | regs->xss = __USER_DS; | 401 | regs->ss = __USER_DS; |
391 | regs->xcs = __USER_CS; | 402 | regs->cs = __USER_CS; |
392 | 403 | ||
393 | /* | 404 | /* |
394 | * Clear TF when entering the signal handler, but | 405 | * Clear TF when entering the signal handler, but |
@@ -396,13 +407,13 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
396 | * The tracer may want to single-step inside the | 407 | * The tracer may want to single-step inside the |
397 | * handler too. | 408 | * handler too. |
398 | */ | 409 | */ |
399 | regs->eflags &= ~TF_MASK; | 410 | regs->flags &= ~TF_MASK; |
400 | if (test_thread_flag(TIF_SINGLESTEP)) | 411 | if (test_thread_flag(TIF_SINGLESTEP)) |
401 | ptrace_notify(SIGTRAP); | 412 | ptrace_notify(SIGTRAP); |
402 | 413 | ||
403 | #if DEBUG_SIG | 414 | #if DEBUG_SIG |
404 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", | 415 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", |
405 | current->comm, current->pid, frame, regs->eip, frame->pretcode); | 416 | current->comm, current->pid, frame, regs->ip, frame->pretcode); |
406 | #endif | 417 | #endif |
407 | 418 | ||
408 | return 0; | 419 | return 0; |
@@ -442,7 +453,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
442 | err |= __put_user(0, &frame->uc.uc_flags); | 453 | err |= __put_user(0, &frame->uc.uc_flags); |
443 | err |= __put_user(0, &frame->uc.uc_link); | 454 | err |= __put_user(0, &frame->uc.uc_link); |
444 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 455 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
445 | err |= __put_user(sas_ss_flags(regs->esp), | 456 | err |= __put_user(sas_ss_flags(regs->sp), |
446 | &frame->uc.uc_stack.ss_flags); | 457 | &frame->uc.uc_stack.ss_flags); |
447 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 458 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
448 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 459 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, |
@@ -452,13 +463,13 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
452 | goto give_sigsegv; | 463 | goto give_sigsegv; |
453 | 464 | ||
454 | /* Set up to return from userspace. */ | 465 | /* Set up to return from userspace. */ |
455 | restorer = (void *)VDSO_SYM(&__kernel_rt_sigreturn); | 466 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
456 | if (ka->sa.sa_flags & SA_RESTORER) | 467 | if (ka->sa.sa_flags & SA_RESTORER) |
457 | restorer = ka->sa.sa_restorer; | 468 | restorer = ka->sa.sa_restorer; |
458 | err |= __put_user(restorer, &frame->pretcode); | 469 | err |= __put_user(restorer, &frame->pretcode); |
459 | 470 | ||
460 | /* | 471 | /* |
461 | * This is movl $,%eax ; int $0x80 | 472 | * This is movl $,%ax ; int $0x80 |
462 | * | 473 | * |
463 | * WE DO NOT USE IT ANY MORE! It's only left here for historical | 474 | * WE DO NOT USE IT ANY MORE! It's only left here for historical |
464 | * reasons and because gdb uses it as a signature to notice | 475 | * reasons and because gdb uses it as a signature to notice |
@@ -472,16 +483,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
472 | goto give_sigsegv; | 483 | goto give_sigsegv; |
473 | 484 | ||
474 | /* Set up registers for signal handler */ | 485 | /* Set up registers for signal handler */ |
475 | regs->esp = (unsigned long) frame; | 486 | regs->sp = (unsigned long) frame; |
476 | regs->eip = (unsigned long) ka->sa.sa_handler; | 487 | regs->ip = (unsigned long) ka->sa.sa_handler; |
477 | regs->eax = (unsigned long) usig; | 488 | regs->ax = (unsigned long) usig; |
478 | regs->edx = (unsigned long) &frame->info; | 489 | regs->dx = (unsigned long) &frame->info; |
479 | regs->ecx = (unsigned long) &frame->uc; | 490 | regs->cx = (unsigned long) &frame->uc; |
480 | 491 | ||
481 | regs->xds = __USER_DS; | 492 | regs->ds = __USER_DS; |
482 | regs->xes = __USER_DS; | 493 | regs->es = __USER_DS; |
483 | regs->xss = __USER_DS; | 494 | regs->ss = __USER_DS; |
484 | regs->xcs = __USER_CS; | 495 | regs->cs = __USER_CS; |
485 | 496 | ||
486 | /* | 497 | /* |
487 | * Clear TF when entering the signal handler, but | 498 | * Clear TF when entering the signal handler, but |
@@ -489,13 +500,13 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
489 | * The tracer may want to single-step inside the | 500 | * The tracer may want to single-step inside the |
490 | * handler too. | 501 | * handler too. |
491 | */ | 502 | */ |
492 | regs->eflags &= ~TF_MASK; | 503 | regs->flags &= ~TF_MASK; |
493 | if (test_thread_flag(TIF_SINGLESTEP)) | 504 | if (test_thread_flag(TIF_SINGLESTEP)) |
494 | ptrace_notify(SIGTRAP); | 505 | ptrace_notify(SIGTRAP); |
495 | 506 | ||
496 | #if DEBUG_SIG | 507 | #if DEBUG_SIG |
497 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", | 508 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", |
498 | current->comm, current->pid, frame, regs->eip, frame->pretcode); | 509 | current->comm, current->pid, frame, regs->ip, frame->pretcode); |
499 | #endif | 510 | #endif |
500 | 511 | ||
501 | return 0; | 512 | return 0; |
@@ -516,35 +527,33 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
516 | int ret; | 527 | int ret; |
517 | 528 | ||
518 | /* Are we from a system call? */ | 529 | /* Are we from a system call? */ |
519 | if (regs->orig_eax >= 0) { | 530 | if (regs->orig_ax >= 0) { |
520 | /* If so, check system call restarting.. */ | 531 | /* If so, check system call restarting.. */ |
521 | switch (regs->eax) { | 532 | switch (regs->ax) { |
522 | case -ERESTART_RESTARTBLOCK: | 533 | case -ERESTART_RESTARTBLOCK: |
523 | case -ERESTARTNOHAND: | 534 | case -ERESTARTNOHAND: |
524 | regs->eax = -EINTR; | 535 | regs->ax = -EINTR; |
525 | break; | 536 | break; |
526 | 537 | ||
527 | case -ERESTARTSYS: | 538 | case -ERESTARTSYS: |
528 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 539 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
529 | regs->eax = -EINTR; | 540 | regs->ax = -EINTR; |
530 | break; | 541 | break; |
531 | } | 542 | } |
532 | /* fallthrough */ | 543 | /* fallthrough */ |
533 | case -ERESTARTNOINTR: | 544 | case -ERESTARTNOINTR: |
534 | regs->eax = regs->orig_eax; | 545 | regs->ax = regs->orig_ax; |
535 | regs->eip -= 2; | 546 | regs->ip -= 2; |
536 | } | 547 | } |
537 | } | 548 | } |
538 | 549 | ||
539 | /* | 550 | /* |
540 | * If TF is set due to a debugger (PT_DTRACE), clear the TF flag so | 551 | * If TF is set due to a debugger (TIF_FORCED_TF), clear the TF |
541 | * that register information in the sigcontext is correct. | 552 | * flag so that register information in the sigcontext is correct. |
542 | */ | 553 | */ |
543 | if (unlikely(regs->eflags & TF_MASK) | 554 | if (unlikely(regs->flags & X86_EFLAGS_TF) && |
544 | && likely(current->ptrace & PT_DTRACE)) { | 555 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
545 | current->ptrace &= ~PT_DTRACE; | 556 | regs->flags &= ~X86_EFLAGS_TF; |
546 | regs->eflags &= ~TF_MASK; | ||
547 | } | ||
548 | 557 | ||
549 | /* Set up the stack frame */ | 558 | /* Set up the stack frame */ |
550 | if (ka->sa.sa_flags & SA_SIGINFO) | 559 | if (ka->sa.sa_flags & SA_SIGINFO) |
@@ -569,7 +578,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
569 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 578 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
570 | * mistake. | 579 | * mistake. |
571 | */ | 580 | */ |
572 | static void fastcall do_signal(struct pt_regs *regs) | 581 | static void do_signal(struct pt_regs *regs) |
573 | { | 582 | { |
574 | siginfo_t info; | 583 | siginfo_t info; |
575 | int signr; | 584 | int signr; |
@@ -599,8 +608,8 @@ static void fastcall do_signal(struct pt_regs *regs) | |||
599 | * have been cleared if the watchpoint triggered | 608 | * have been cleared if the watchpoint triggered |
600 | * inside the kernel. | 609 | * inside the kernel. |
601 | */ | 610 | */ |
602 | if (unlikely(current->thread.debugreg[7])) | 611 | if (unlikely(current->thread.debugreg7)) |
603 | set_debugreg(current->thread.debugreg[7], 7); | 612 | set_debugreg(current->thread.debugreg7, 7); |
604 | 613 | ||
605 | /* Whee! Actually deliver the signal. */ | 614 | /* Whee! Actually deliver the signal. */ |
606 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 615 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { |
@@ -616,19 +625,19 @@ static void fastcall do_signal(struct pt_regs *regs) | |||
616 | } | 625 | } |
617 | 626 | ||
618 | /* Did we come from a system call? */ | 627 | /* Did we come from a system call? */ |
619 | if (regs->orig_eax >= 0) { | 628 | if (regs->orig_ax >= 0) { |
620 | /* Restart the system call - no handlers present */ | 629 | /* Restart the system call - no handlers present */ |
621 | switch (regs->eax) { | 630 | switch (regs->ax) { |
622 | case -ERESTARTNOHAND: | 631 | case -ERESTARTNOHAND: |
623 | case -ERESTARTSYS: | 632 | case -ERESTARTSYS: |
624 | case -ERESTARTNOINTR: | 633 | case -ERESTARTNOINTR: |
625 | regs->eax = regs->orig_eax; | 634 | regs->ax = regs->orig_ax; |
626 | regs->eip -= 2; | 635 | regs->ip -= 2; |
627 | break; | 636 | break; |
628 | 637 | ||
629 | case -ERESTART_RESTARTBLOCK: | 638 | case -ERESTART_RESTARTBLOCK: |
630 | regs->eax = __NR_restart_syscall; | 639 | regs->ax = __NR_restart_syscall; |
631 | regs->eip -= 2; | 640 | regs->ip -= 2; |
632 | break; | 641 | break; |
633 | } | 642 | } |
634 | } | 643 | } |
@@ -651,7 +660,7 @@ void do_notify_resume(struct pt_regs *regs, void *_unused, | |||
651 | { | 660 | { |
652 | /* Pending single-step? */ | 661 | /* Pending single-step? */ |
653 | if (thread_info_flags & _TIF_SINGLESTEP) { | 662 | if (thread_info_flags & _TIF_SINGLESTEP) { |
654 | regs->eflags |= TF_MASK; | 663 | regs->flags |= TF_MASK; |
655 | clear_thread_flag(TIF_SINGLESTEP); | 664 | clear_thread_flag(TIF_SINGLESTEP); |
656 | } | 665 | } |
657 | 666 | ||