Next try.
First the already existing check in COPY_CANON for sigreturn
wasn't correct. Replace it with a better check against TASK_SIZE.
Also add a check to sigaction which was missing it previously.
This works around a problem in handling non canonical RIPs on SYSRET on Intel
CPUs. They report the #GP on the SYSRET, not the next instruction
as Linux expects it. With these changes this path should never
see a non canonical user RIP.
I reset SIGSEGV to DFL to avoid an endless loop
Roughly based on a patch by Ernie Petrides, but redone by AK.
This is CVE-2006-0741
Cc: petrides@redhat.com
Signed-off-by: Andi Kleen <ak@suse.de>
COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx);
COPY(rdx); COPY(rcx);
COPY(rip);
- /* rsp check is not strictly needed I think -AK */
- if (regs->rip >= TASK_SIZE || regs->rsp >= TASK_SIZE) {
+ if (regs->rip >= TASK_SIZE && regs->rip < VSYSCALL_START) {
regs->rip = 0;
- regs->rsp = 0;
return -EFAULT;
}
COPY(r8);
regs->rsp = (unsigned long) frame;
regs->rip = (unsigned long) ka->sa.sa_handler;
if (regs->rip >= TASK_SIZE) {
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
regs->rip = 0;
- goto give_sigsegv;
}
regs->cs = __USER_CS;
regs->ss = __USER_DS;