mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 23:27:06 +00:00
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: Roland McGrath <roland@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
a267c0a887
commit
29eb51101c
2 changed files with 31 additions and 14 deletions
|
@ -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;
|
||||||
|
|
||||||
down(&child->mm->context.sem);
|
seg &= ~7UL;
|
||||||
desc = child->mm->context.ldt + (seg & ~7);
|
|
||||||
base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
|
|
||||||
|
|
||||||
/* 16-bit code segment? */
|
down(&child->mm->context.sem);
|
||||||
if (!((desc[1] >> 22) & 1))
|
if (unlikely((seg >> 3) >= child->mm->context.size))
|
||||||
addr &= 0xffff;
|
addr = -1L; /* bogus selector, access would fault */
|
||||||
addr += base;
|
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);
|
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
|
||||||
u32 *desc;
|
u32 *desc;
|
||||||
unsigned long base;
|
unsigned long base;
|
||||||
|
|
||||||
down(&child->mm->context.sem);
|
seg &= ~7UL;
|
||||||
desc = child->mm->context.ldt + (seg & ~7);
|
|
||||||
base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
|
|
||||||
|
|
||||||
/* 16-bit code segment? */
|
down(&child->mm->context.sem);
|
||||||
if (!((desc[1] >> 22) & 1))
|
if (unlikely((seg >> 3) >= child->mm->context.size))
|
||||||
addr &= 0xffff;
|
addr = -1L; /* bogus selector, access would fault */
|
||||||
addr += base;
|
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);
|
up(&child->mm->context.sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue