diff options
author | Chuck Ebbert <76306.1226@compuserve.com> | 2006-09-26 04:52:33 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:33 -0400 |
commit | 2ade2920dcefdf5595c6380ebed131c964190855 (patch) | |
tree | 053542af977e5c402633771bb737f3d8a0efef33 | |
parent | 91cd444e56ebe0c2acd9576a045d77490b26f607 (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.c | 10 | ||||
-rw-r--r-- | arch/x86_64/kernel/ptrace.c | 12 |
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 | ||
188 | static inline int is_at_popf(struct task_struct *child, struct pt_regs *regs) | 188 | static 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 | ||
119 | static int is_at_popf(struct task_struct *child, struct pt_regs *regs) | 119 | static 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; |