aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2012-02-17 03:27:41 -0500
committerIngo Molnar <mingo@elte.hu>2012-02-17 04:18:07 -0500
commit7b2d81d48a2d8e37efb6ce7b4d5ef58822b30d89 (patch)
tree23987f194dcd91b0ba6d27f7f6e08c178797488e /arch/x86
parent2b144498350860b6ee9dc57ff27a93ad488de5dc (diff)
uprobes/core: Clean up, refactor and improve the code
Make the uprobes code readable to me: - improve the Kconfig text so that a mere mortal gets some idea what CONFIG_UPROBES=y is really about - do trivial renames to standardize around the uprobes_*() namespace - clean up and simplify various code flow details - separate basic blocks of functionality - line break artifact and white space related removal - use standard local varible definition blocks - use vertical spacing to make things more readable - remove unnecessary volatile - restructure comment blocks to make them more uniform and more readable in general Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Anton Arapov <anton@redhat.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Link: http://lkml.kernel.org/n/tip-ewbwhb8o6navvllsauu7k07p@git.kernel.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/uprobes.h17
-rw-r--r--arch/x86/kernel/uprobes.c129
2 files changed, 77 insertions, 69 deletions
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index 8208234391ff..072df3902636 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -1,7 +1,7 @@
1#ifndef _ASM_UPROBES_H 1#ifndef _ASM_UPROBES_H
2#define _ASM_UPROBES_H 2#define _ASM_UPROBES_H
3/* 3/*
4 * Userspace Probes (UProbes) for x86 4 * User-space Probes (UProbes) for x86
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -24,19 +24,20 @@
24 */ 24 */
25 25
26typedef u8 uprobe_opcode_t; 26typedef u8 uprobe_opcode_t;
27#define MAX_UINSN_BYTES 16
28#define UPROBES_XOL_SLOT_BYTES 128 /* to keep it cache aligned */
29 27
30#define UPROBES_BKPT_INSN 0xcc 28#define MAX_UINSN_BYTES 16
31#define UPROBES_BKPT_INSN_SIZE 1 29#define UPROBES_XOL_SLOT_BYTES 128 /* to keep it cache aligned */
30
31#define UPROBES_BKPT_INSN 0xcc
32#define UPROBES_BKPT_INSN_SIZE 1
32 33
33struct uprobe_arch_info { 34struct uprobe_arch_info {
34 u16 fixups; 35 u16 fixups;
35#ifdef CONFIG_X86_64 36#ifdef CONFIG_X86_64
36 unsigned long rip_rela_target_address; 37 unsigned long rip_rela_target_address;
37#endif 38#endif
38}; 39};
39 40
40struct uprobe; 41struct uprobe;
41extern int analyze_insn(struct mm_struct *mm, struct uprobe *uprobe); 42extern int arch_uprobes_analyze_insn(struct mm_struct *mm, struct uprobe *uprobe);
42#endif /* _ASM_UPROBES_H */ 43#endif /* _ASM_UPROBES_H */
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 2a301bb91bdb..cf2a18498425 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Userspace Probes (UProbes) for x86 2 * User-space Probes (UProbes) for x86
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
20 * Srikar Dronamraju 20 * Srikar Dronamraju
21 * Jim Keniston 21 * Jim Keniston
22 */ 22 */
23
24#include <linux/kernel.h> 23#include <linux/kernel.h>
25#include <linux/sched.h> 24#include <linux/sched.h>
26#include <linux/ptrace.h> 25#include <linux/ptrace.h>
@@ -42,10 +41,10 @@
42#define UPROBES_FIX_RIP_CX 0x4000 41#define UPROBES_FIX_RIP_CX 0x4000
43 42
44/* Adaptations for mhiramat x86 decoder v14. */ 43/* Adaptations for mhiramat x86 decoder v14. */
45#define OPCODE1(insn) ((insn)->opcode.bytes[0]) 44#define OPCODE1(insn) ((insn)->opcode.bytes[0])
46#define OPCODE2(insn) ((insn)->opcode.bytes[1]) 45#define OPCODE2(insn) ((insn)->opcode.bytes[1])
47#define OPCODE3(insn) ((insn)->opcode.bytes[2]) 46#define OPCODE3(insn) ((insn)->opcode.bytes[2])
48#define MODRM_REG(insn) X86_MODRM_REG(insn->modrm.value) 47#define MODRM_REG(insn) X86_MODRM_REG(insn->modrm.value)
49 48
50#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\ 49#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
51 (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ 50 (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
@@ -55,7 +54,7 @@
55 << (row % 32)) 54 << (row % 32))
56 55
57#ifdef CONFIG_X86_64 56#ifdef CONFIG_X86_64
58static volatile u32 good_insns_64[256 / 32] = { 57static u32 good_insns_64[256 / 32] = {
59 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 58 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
60 /* ---------------------------------------------- */ 59 /* ---------------------------------------------- */
61 W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 00 */ 60 W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 00 */
@@ -81,7 +80,7 @@ static volatile u32 good_insns_64[256 / 32] = {
81 80
82/* Good-instruction tables for 32-bit apps */ 81/* Good-instruction tables for 32-bit apps */
83 82
84static volatile u32 good_insns_32[256 / 32] = { 83static u32 good_insns_32[256 / 32] = {
85 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 84 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
86 /* ---------------------------------------------- */ 85 /* ---------------------------------------------- */
87 W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 00 */ 86 W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 00 */
@@ -105,7 +104,7 @@ static volatile u32 good_insns_32[256 / 32] = {
105}; 104};
106 105
107/* Using this for both 64-bit and 32-bit apps */ 106/* Using this for both 64-bit and 32-bit apps */
108static volatile u32 good_2byte_insns[256 / 32] = { 107static u32 good_2byte_insns[256 / 32] = {
109 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 108 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
110 /* ---------------------------------------------- */ 109 /* ---------------------------------------------- */
111 W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) | /* 00 */ 110 W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) | /* 00 */
@@ -132,42 +131,47 @@ static volatile u32 good_2byte_insns[256 / 32] = {
132 131
133/* 132/*
134 * opcodes we'll probably never support: 133 * opcodes we'll probably never support:
135 * 6c-6d, e4-e5, ec-ed - in 134 *
136 * 6e-6f, e6-e7, ee-ef - out 135 * 6c-6d, e4-e5, ec-ed - in
137 * cc, cd - int3, int 136 * 6e-6f, e6-e7, ee-ef - out
138 * cf - iret 137 * cc, cd - int3, int
139 * d6 - illegal instruction 138 * cf - iret
140 * f1 - int1/icebp 139 * d6 - illegal instruction
141 * f4 - hlt 140 * f1 - int1/icebp
142 * fa, fb - cli, sti 141 * f4 - hlt
143 * 0f - lar, lsl, syscall, clts, sysret, sysenter, sysexit, invd, wbinvd, ud2 142 * fa, fb - cli, sti
143 * 0f - lar, lsl, syscall, clts, sysret, sysenter, sysexit, invd, wbinvd, ud2
144 * 144 *
145 * invalid opcodes in 64-bit mode: 145 * invalid opcodes in 64-bit mode:
146 * 06, 0e, 16, 1e, 27, 2f, 37, 3f, 60-62, 82, c4-c5, d4-d5
147 * 146 *
148 * 63 - we support this opcode in x86_64 but not in i386. 147 * 06, 0e, 16, 1e, 27, 2f, 37, 3f, 60-62, 82, c4-c5, d4-d5
148 * 63 - we support this opcode in x86_64 but not in i386.
149 * 149 *
150 * opcodes we may need to refine support for: 150 * opcodes we may need to refine support for:
151 * 0f - 2-byte instructions: For many of these instructions, the validity 151 *
152 * depends on the prefix and/or the reg field. On such instructions, we 152 * 0f - 2-byte instructions: For many of these instructions, the validity
153 * just consider the opcode combination valid if it corresponds to any 153 * depends on the prefix and/or the reg field. On such instructions, we
154 * valid instruction. 154 * just consider the opcode combination valid if it corresponds to any
155 * 8f - Group 1 - only reg = 0 is OK 155 * valid instruction.
156 * c6-c7 - Group 11 - only reg = 0 is OK 156 *
157 * d9-df - fpu insns with some illegal encodings 157 * 8f - Group 1 - only reg = 0 is OK
158 * f2, f3 - repnz, repz prefixes. These are also the first byte for 158 * c6-c7 - Group 11 - only reg = 0 is OK
159 * certain floating-point instructions, such as addsd. 159 * d9-df - fpu insns with some illegal encodings
160 * fe - Group 4 - only reg = 0 or 1 is OK 160 * f2, f3 - repnz, repz prefixes. These are also the first byte for
161 * ff - Group 5 - only reg = 0-6 is OK 161 * certain floating-point instructions, such as addsd.
162 *
163 * fe - Group 4 - only reg = 0 or 1 is OK
164 * ff - Group 5 - only reg = 0-6 is OK
162 * 165 *
163 * others -- Do we need to support these? 166 * others -- Do we need to support these?
164 * 0f - (floating-point?) prefetch instructions 167 *
165 * 07, 17, 1f - pop es, pop ss, pop ds 168 * 0f - (floating-point?) prefetch instructions
166 * 26, 2e, 36, 3e - es:, cs:, ss:, ds: segment prefixes -- 169 * 07, 17, 1f - pop es, pop ss, pop ds
170 * 26, 2e, 36, 3e - es:, cs:, ss:, ds: segment prefixes --
167 * but 64 and 65 (fs: and gs:) seem to be used, so we support them 171 * but 64 and 65 (fs: and gs:) seem to be used, so we support them
168 * 67 - addr16 prefix 172 * 67 - addr16 prefix
169 * ce - into 173 * ce - into
170 * f0 - lock prefix 174 * f0 - lock prefix
171 */ 175 */
172 176
173/* 177/*
@@ -182,11 +186,11 @@ static bool is_prefix_bad(struct insn *insn)
182 186
183 for (i = 0; i < insn->prefixes.nbytes; i++) { 187 for (i = 0; i < insn->prefixes.nbytes; i++) {
184 switch (insn->prefixes.bytes[i]) { 188 switch (insn->prefixes.bytes[i]) {
185 case 0x26: /*INAT_PFX_ES */ 189 case 0x26: /* INAT_PFX_ES */
186 case 0x2E: /*INAT_PFX_CS */ 190 case 0x2E: /* INAT_PFX_CS */
187 case 0x36: /*INAT_PFX_DS */ 191 case 0x36: /* INAT_PFX_DS */
188 case 0x3E: /*INAT_PFX_SS */ 192 case 0x3E: /* INAT_PFX_SS */
189 case 0xF0: /*INAT_PFX_LOCK */ 193 case 0xF0: /* INAT_PFX_LOCK */
190 return true; 194 return true;
191 } 195 }
192 } 196 }
@@ -201,12 +205,15 @@ static int validate_insn_32bits(struct uprobe *uprobe, struct insn *insn)
201 insn_get_opcode(insn); 205 insn_get_opcode(insn);
202 if (is_prefix_bad(insn)) 206 if (is_prefix_bad(insn))
203 return -ENOTSUPP; 207 return -ENOTSUPP;
208
204 if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32)) 209 if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32))
205 return 0; 210 return 0;
211
206 if (insn->opcode.nbytes == 2) { 212 if (insn->opcode.nbytes == 2) {
207 if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) 213 if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns))
208 return 0; 214 return 0;
209 } 215 }
216
210 return -ENOTSUPP; 217 return -ENOTSUPP;
211} 218}
212 219
@@ -282,12 +289,12 @@ static void prepare_fixups(struct uprobe *uprobe, struct insn *insn)
282 * disastrous. 289 * disastrous.
283 * 290 *
284 * Some useful facts about rip-relative instructions: 291 * Some useful facts about rip-relative instructions:
285 * - There's always a modrm byte. 292 *
286 * - There's never a SIB byte. 293 * - There's always a modrm byte.
287 * - The displacement is always 4 bytes. 294 * - There's never a SIB byte.
295 * - The displacement is always 4 bytes.
288 */ 296 */
289static void handle_riprel_insn(struct mm_struct *mm, struct uprobe *uprobe, 297static void handle_riprel_insn(struct mm_struct *mm, struct uprobe *uprobe, struct insn *insn)
290 struct insn *insn)
291{ 298{
292 u8 *cursor; 299 u8 *cursor;
293 u8 reg; 300 u8 reg;
@@ -342,13 +349,12 @@ static void handle_riprel_insn(struct mm_struct *mm, struct uprobe *uprobe,
342 } 349 }
343 350
344 /* Target address = address of next instruction + (signed) offset */ 351 /* Target address = address of next instruction + (signed) offset */
345 uprobe->arch_info.rip_rela_target_address = (long)insn->length 352 uprobe->arch_info.rip_rela_target_address = (long)insn->length + insn->displacement.value;
346 + insn->displacement.value; 353
347 /* Displacement field is gone; slide immediate field (if any) over. */ 354 /* Displacement field is gone; slide immediate field (if any) over. */
348 if (insn->immediate.nbytes) { 355 if (insn->immediate.nbytes) {
349 cursor++; 356 cursor++;
350 memmove(cursor, cursor + insn->displacement.nbytes, 357 memmove(cursor, cursor + insn->displacement.nbytes, insn->immediate.nbytes);
351 insn->immediate.nbytes);
352 } 358 }
353 return; 359 return;
354} 360}
@@ -361,8 +367,10 @@ static int validate_insn_64bits(struct uprobe *uprobe, struct insn *insn)
361 insn_get_opcode(insn); 367 insn_get_opcode(insn);
362 if (is_prefix_bad(insn)) 368 if (is_prefix_bad(insn))
363 return -ENOTSUPP; 369 return -ENOTSUPP;
370
364 if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64)) 371 if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64))
365 return 0; 372 return 0;
373
366 if (insn->opcode.nbytes == 2) { 374 if (insn->opcode.nbytes == 2) {
367 if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) 375 if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns))
368 return 0; 376 return 0;
@@ -370,34 +378,31 @@ static int validate_insn_64bits(struct uprobe *uprobe, struct insn *insn)
370 return -ENOTSUPP; 378 return -ENOTSUPP;
371} 379}
372 380
373static int validate_insn_bits(struct mm_struct *mm, struct uprobe *uprobe, 381static int validate_insn_bits(struct mm_struct *mm, struct uprobe *uprobe, struct insn *insn)
374 struct insn *insn)
375{ 382{
376 if (mm->context.ia32_compat) 383 if (mm->context.ia32_compat)
377 return validate_insn_32bits(uprobe, insn); 384 return validate_insn_32bits(uprobe, insn);
378 return validate_insn_64bits(uprobe, insn); 385 return validate_insn_64bits(uprobe, insn);
379} 386}
380#else 387#else /* 32-bit: */
381static void handle_riprel_insn(struct mm_struct *mm, struct uprobe *uprobe, 388static void handle_riprel_insn(struct mm_struct *mm, struct uprobe *uprobe, struct insn *insn)
382 struct insn *insn)
383{ 389{
384 return; 390 /* No RIP-relative addressing on 32-bit */
385} 391}
386 392
387static int validate_insn_bits(struct mm_struct *mm, struct uprobe *uprobe, 393static int validate_insn_bits(struct mm_struct *mm, struct uprobe *uprobe, struct insn *insn)
388 struct insn *insn)
389{ 394{
390 return validate_insn_32bits(uprobe, insn); 395 return validate_insn_32bits(uprobe, insn);
391} 396}
392#endif /* CONFIG_X86_64 */ 397#endif /* CONFIG_X86_64 */
393 398
394/** 399/**
395 * analyze_insn - instruction analysis including validity and fixups. 400 * arch_uprobes_analyze_insn - instruction analysis including validity and fixups.
396 * @mm: the probed address space. 401 * @mm: the probed address space.
397 * @uprobe: the probepoint information. 402 * @uprobe: the probepoint information.
398 * Return 0 on success or a -ve number on error. 403 * Return 0 on success or a -ve number on error.
399 */ 404 */
400int analyze_insn(struct mm_struct *mm, struct uprobe *uprobe) 405int arch_uprobes_analyze_insn(struct mm_struct *mm, struct uprobe *uprobe)
401{ 406{
402 int ret; 407 int ret;
403 struct insn insn; 408 struct insn insn;
@@ -406,7 +411,9 @@ int analyze_insn(struct mm_struct *mm, struct uprobe *uprobe)
406 ret = validate_insn_bits(mm, uprobe, &insn); 411 ret = validate_insn_bits(mm, uprobe, &insn);
407 if (ret != 0) 412 if (ret != 0)
408 return ret; 413 return ret;
414
409 handle_riprel_insn(mm, uprobe, &insn); 415 handle_riprel_insn(mm, uprobe, &insn);
410 prepare_fixups(uprobe, &insn); 416 prepare_fixups(uprobe, &insn);
417
411 return 0; 418 return 0;
412} 419}