aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Ebbert <76306.1226@compuserve.com>2006-09-26 04:52:33 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:33 -0400
commit2ade2920dcefdf5595c6380ebed131c964190855 (patch)
tree053542af977e5c402633771bb737f3d8a0efef33
parent91cd444e56ebe0c2acd9576a045d77490b26f607 (diff)
[PATCH] i386/x86-64: rename is_at_popf(), add iret to tests and fix
is_at_popf() needs to test for the iret instruction as well as popf. So add that test and rename it to is_setting_trap_flag(). Also change max insn length from 16 to 15 to match reality. LAHF / SAHF can't affect TF, so the comment in x86_64 is removed. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andi Kleen <ak@suse.de>
-rw-r--r--arch/i386/kernel/ptrace.c10
-rw-r--r--arch/x86_64/kernel/ptrace.c12
2 files changed, 10 insertions, 12 deletions
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index d3db03f4085d..775f50e9395b 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -185,17 +185,17 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
185 return addr; 185 return addr;
186} 186}
187 187
188static inline int is_at_popf(struct task_struct *child, struct pt_regs *regs) 188static inline int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
189{ 189{
190 int i, copied; 190 int i, copied;
191 unsigned char opcode[16]; 191 unsigned char opcode[15];
192 unsigned long addr = convert_eip_to_linear(child, regs); 192 unsigned long addr = convert_eip_to_linear(child, regs);
193 193
194 copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0); 194 copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
195 for (i = 0; i < copied; i++) { 195 for (i = 0; i < copied; i++) {
196 switch (opcode[i]) { 196 switch (opcode[i]) {
197 /* popf */ 197 /* popf and iret */
198 case 0x9d: 198 case 0x9d: case 0xcf:
199 return 1; 199 return 1;
200 /* opcode and address size prefixes */ 200 /* opcode and address size prefixes */
201 case 0x66: case 0x67: 201 case 0x66: case 0x67:
@@ -247,7 +247,7 @@ static void set_singlestep(struct task_struct *child)
247 * don't mark it as being "us" that set it, so that we 247 * don't mark it as being "us" that set it, so that we
248 * won't clear it by hand later. 248 * won't clear it by hand later.
249 */ 249 */
250 if (is_at_popf(child, regs)) 250 if (is_setting_trap_flag(child, regs))
251 return; 251 return;
252 252
253 child->ptrace |= PT_DTRACE; 253 child->ptrace |= PT_DTRACE;
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 412c6a8bf906..addc14af0c56 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -116,17 +116,17 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
116 return addr; 116 return addr;
117} 117}
118 118
119static int is_at_popf(struct task_struct *child, struct pt_regs *regs) 119static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
120{ 120{
121 int i, copied; 121 int i, copied;
122 unsigned char opcode[16]; 122 unsigned char opcode[15];
123 unsigned long addr = convert_rip_to_linear(child, regs); 123 unsigned long addr = convert_rip_to_linear(child, regs);
124 124
125 copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0); 125 copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
126 for (i = 0; i < copied; i++) { 126 for (i = 0; i < copied; i++) {
127 switch (opcode[i]) { 127 switch (opcode[i]) {
128 /* popf */ 128 /* popf and iret */
129 case 0x9d: 129 case 0x9d: case 0xcf:
130 return 1; 130 return 1;
131 131
132 /* CHECKME: 64 65 */ 132 /* CHECKME: 64 65 */
@@ -189,10 +189,8 @@ static void set_singlestep(struct task_struct *child)
189 * ..but if TF is changed by the instruction we will trace, 189 * ..but if TF is changed by the instruction we will trace,
190 * don't mark it as being "us" that set it, so that we 190 * don't mark it as being "us" that set it, so that we
191 * won't clear it by hand later. 191 * won't clear it by hand later.
192 *
193 * AK: this is not enough, LAHF and IRET can change TF in user space too.
194 */ 192 */
195 if (is_at_popf(child, regs)) 193 if (is_setting_trap_flag(child, regs))
196 return; 194 return;
197 195
198 child->ptrace |= PT_DTRACE; 196 child->ptrace |= PT_DTRACE;