aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/entry.S2
-rw-r--r--arch/i386/kernel/ptrace.c22
-rw-r--r--arch/i386/kernel/traps.c10
-rw-r--r--arch/x86_64/kernel/ptrace.c23
4 files changed, 37 insertions, 20 deletions
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 32980b834935..a714d6b43506 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -409,8 +409,6 @@ restore_nocheck_notrace:
4091: INTERRUPT_RETURN 4091: INTERRUPT_RETURN
410.section .fixup,"ax" 410.section .fixup,"ax"
411iret_exc: 411iret_exc:
412 TRACE_IRQS_ON
413 ENABLE_INTERRUPTS(CLBR_NONE)
414 pushl $0 # no error code 412 pushl $0 # no error code
415 pushl $do_iret_error 413 pushl $do_iret_error
416 jmp error_code 414 jmp error_code
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 1c075f58d1f9..0c8f00e69c4d 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
164 u32 *desc; 164 u32 *desc;
165 unsigned long base; 165 unsigned long base;
166 166
167 down(&child->mm->context.sem); 167 seg &= ~7UL;
168 desc = child->mm->context.ldt + (seg & ~7);
169 base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
170 168
171 /* 16-bit code segment? */ 169 down(&child->mm->context.sem);
172 if (!((desc[1] >> 22) & 1)) 170 if (unlikely((seg >> 3) >= child->mm->context.size))
173 addr &= 0xffff; 171 addr = -1L; /* bogus selector, access would fault */
174 addr += base; 172 else {
173 desc = child->mm->context.ldt + seg;
174 base = ((desc[0] >> 16) |
175 ((desc[1] & 0xff) << 16) |
176 (desc[1] & 0xff000000));
177
178 /* 16-bit code segment? */
179 if (!((desc[1] >> 22) & 1))
180 addr &= 0xffff;
181 addr += base;
182 }
175 up(&child->mm->context.sem); 183 up(&child->mm->context.sem);
176 } 184 }
177 return addr; 185 return addr;
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 18c1c285836d..d32fd4b6f78e 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -518,10 +518,12 @@ fastcall void do_##name(struct pt_regs * regs, long error_code) \
518 do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ 518 do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
519} 519}
520 520
521#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ 521#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
522fastcall void do_##name(struct pt_regs * regs, long error_code) \ 522fastcall void do_##name(struct pt_regs * regs, long error_code) \
523{ \ 523{ \
524 siginfo_t info; \ 524 siginfo_t info; \
525 if (irq) \
526 local_irq_enable(); \
525 info.si_signo = signr; \ 527 info.si_signo = signr; \
526 info.si_errno = 0; \ 528 info.si_errno = 0; \
527 info.si_code = sicode; \ 529 info.si_code = sicode; \
@@ -561,13 +563,13 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
561#endif 563#endif
562DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) 564DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
563DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) 565DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
564DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip) 566DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip, 0)
565DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) 567DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
566DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) 568DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
567DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) 569DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
568DO_ERROR(12, SIGBUS, "stack segment", stack_segment) 570DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
569DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) 571DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
570DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0) 572DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
571 573
572fastcall void __kprobes do_general_protection(struct pt_regs * regs, 574fastcall void __kprobes do_general_protection(struct pt_regs * regs,
573 long error_code) 575 long error_code)
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index fa6775ef729f..e83cc67155ac 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -102,16 +102,25 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
102 u32 *desc; 102 u32 *desc;
103 unsigned long base; 103 unsigned long base;
104 104
105 down(&child->mm->context.sem); 105 seg &= ~7UL;
106 desc = child->mm->context.ldt + (seg & ~7);
107 base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
108 106
109 /* 16-bit code segment? */ 107 down(&child->mm->context.sem);
110 if (!((desc[1] >> 22) & 1)) 108 if (unlikely((seg >> 3) >= child->mm->context.size))
111 addr &= 0xffff; 109 addr = -1L; /* bogus selector, access would fault */
112 addr += base; 110 else {
111 desc = child->mm->context.ldt + seg;
112 base = ((desc[0] >> 16) |
113 ((desc[1] & 0xff) << 16) |
114 (desc[1] & 0xff000000));
115
116 /* 16-bit code segment? */
117 if (!((desc[1] >> 22) & 1))
118 addr &= 0xffff;
119 addr += base;
120 }
113 up(&child->mm->context.sem); 121 up(&child->mm->context.sem);
114 } 122 }
123
115 return addr; 124 return addr;
116} 125}
117 126