|
@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
|
|
|
u32 *desc;
|
|
|
unsigned long base;
|
|
|
|
|
|
- down(&child->mm->context.sem);
|
|
|
- desc = child->mm->context.ldt + (seg & ~7);
|
|
|
- base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
|
|
|
+ seg &= ~7UL;
|
|
|
|
|
|
- /* 16-bit code segment? */
|
|
|
- if (!((desc[1] >> 22) & 1))
|
|
|
- addr &= 0xffff;
|
|
|
- addr += base;
|
|
|
+ down(&child->mm->context.sem);
|
|
|
+ if (unlikely((seg >> 3) >= child->mm->context.size))
|
|
|
+ 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? */
|
|
|
+ if (!((desc[1] >> 22) & 1))
|
|
|
+ addr &= 0xffff;
|
|
|
+ addr += base;
|
|
|
+ }
|
|
|
up(&child->mm->context.sem);
|
|
|
}
|
|
|
return addr;
|