Commit 29eb5110 authored by Roland McGrath's avatar Roland McGrath Committed by Linus Torvalds

Handle bogus %cs selector in single-step instruction decoding

The code for LDT segment selectors was not robust in the face of a bogus
selector set in %cs via ptrace before the single-step was done.
Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a267c0a8
...@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_ ...@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
u32 *desc; u32 *desc;
unsigned long base; unsigned long base;
seg &= ~7UL;
down(&child->mm->context.sem); down(&child->mm->context.sem);
desc = child->mm->context.ldt + (seg & ~7); if (unlikely((seg >> 3) >= child->mm->context.size))
base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000); addr = -1L; /* bogus selector, access would fault */
else {
desc = child->mm->context.ldt + seg;
base = ((desc[0] >> 16) |
((desc[1] & 0xff) << 16) |
(desc[1] & 0xff000000));
/* 16-bit code segment? */ /* 16-bit code segment? */
if (!((desc[1] >> 22) & 1)) if (!((desc[1] >> 22) & 1))
addr &= 0xffff; addr &= 0xffff;
addr += base; addr += base;
}
up(&child->mm->context.sem); up(&child->mm->context.sem);
} }
return addr; return addr;
......
...@@ -102,16 +102,25 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r ...@@ -102,16 +102,25 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
u32 *desc; u32 *desc;
unsigned long base; unsigned long base;
seg &= ~7UL;
down(&child->mm->context.sem); down(&child->mm->context.sem);
desc = child->mm->context.ldt + (seg & ~7); if (unlikely((seg >> 3) >= child->mm->context.size))
base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000); addr = -1L; /* bogus selector, access would fault */
else {
desc = child->mm->context.ldt + seg;
base = ((desc[0] >> 16) |
((desc[1] & 0xff) << 16) |
(desc[1] & 0xff000000));
/* 16-bit code segment? */ /* 16-bit code segment? */
if (!((desc[1] >> 22) & 1)) if (!((desc[1] >> 22) & 1))
addr &= 0xffff; addr &= 0xffff;
addr += base; addr += base;
}
up(&child->mm->context.sem); up(&child->mm->context.sem);
} }
return addr; return addr;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment