Skip to content

Commit 29eb511

Browse files
Roland McGrathLinus Torvalds
authored andcommitted
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 <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent a267c0a commit 29eb511

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed

arch/i386/kernel/ptrace.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
164164
u32 *desc;
165165
unsigned long base;
166166

167-
down(&child->mm->context.sem);
168-
desc = child->mm->context.ldt + (seg & ~7);
169-
base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
167+
seg &= ~7UL;
170168

171-
/* 16-bit code segment? */
172-
if (!((desc[1] >> 22) & 1))
173-
addr &= 0xffff;
174-
addr += base;
169+
down(&child->mm->context.sem);
170+
if (unlikely((seg >> 3) >= child->mm->context.size))
171+
addr = -1L; /* bogus selector, access would fault */
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+
}
175183
up(&child->mm->context.sem);
176184
}
177185
return addr;

arch/x86_64/kernel/ptrace.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,25 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
102102
u32 *desc;
103103
unsigned long base;
104104

105-
down(&child->mm->context.sem);
106-
desc = child->mm->context.ldt + (seg & ~7);
107-
base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
105+
seg &= ~7UL;
108106

109-
/* 16-bit code segment? */
110-
if (!((desc[1] >> 22) & 1))
111-
addr &= 0xffff;
112-
addr += base;
107+
down(&child->mm->context.sem);
108+
if (unlikely((seg >> 3) >= child->mm->context.size))
109+
addr = -1L; /* bogus selector, access would fault */
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+
}
113121
up(&child->mm->context.sem);
114122
}
123+
115124
return addr;
116125
}
117126

0 commit comments

Comments
 (0)