summaryrefslogtreecommitdiffstats
path: root/runtime/uprobes
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/uprobes')
-rw-r--r--runtime/uprobes/uprobes.c5
-rw-r--r--runtime/uprobes/uprobes.h10
-rw-r--r--runtime/uprobes/uprobes_i386.c20
-rw-r--r--runtime/uprobes/uprobes_i386.h9
-rw-r--r--runtime/uprobes/uprobes_ppc64.h9
-rw-r--r--runtime/uprobes/uprobes_s390.h10
6 files changed, 42 insertions, 21 deletions
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c
index 01b40670..9f5fddd0 100644
--- a/runtime/uprobes/uprobes.c
+++ b/runtime/uprobes/uprobes.c
@@ -251,7 +251,7 @@ static void insert_bkpt(struct uprobe_probept *ppt, struct task_struct *tsk)
goto out;
}
- if ((result = arch_validate_probed_insn(ppt)) < 0) {
+ if ((result = arch_validate_probed_insn(ppt, tsk)) < 0) {
bkpt_insertion_failed(ppt, "instruction type cannot be probed");
goto out;
}
@@ -1754,7 +1754,8 @@ static int utask_quiesce_pending_sigtrap(struct uprobe_task *utask)
if (unlikely(regset == NULL))
return -EIO;
- if ((*regset->get)(utask->tsk, regset, SLOT_IP * regset->size,
+ if ((*regset->get)(utask->tsk, regset,
+ SLOT_IP(utask->tsk) * regset->size,
regset->size, &insn_ptr, NULL) != 0)
return -EIO;
diff --git a/runtime/uprobes/uprobes.h b/runtime/uprobes/uprobes.h
index 84dd0b2a..e8a06599 100644
--- a/runtime/uprobes/uprobes.h
+++ b/runtime/uprobes/uprobes.h
@@ -278,9 +278,15 @@ struct uprobe_probept {
/* Saved opcode (which has been replaced with breakpoint) */
uprobe_opcode_t opcode;
- /* Saved original instruction */
+ /*
+ * Saved original instruction. This may be modified by
+ * architecture-specific code if the original instruction
+ * can't be single-stepped out of line as-is.
+ */
uprobe_opcode_t insn[MAX_UINSN_BYTES / sizeof(uprobe_opcode_t)];
+ struct uprobe_probept_arch_info arch_info;
+
/* The parent uprobe_process */
struct uprobe_process *uproc;
@@ -359,6 +365,8 @@ struct uprobe_task {
/* Saved address of copied original instruction */
long singlestep_addr;
+ struct uprobe_task_arch_info arch_info;
+
/*
* Unexpected error in probepoint handling has left task's
* text or stack corrupted. Kill task ASAP.
diff --git a/runtime/uprobes/uprobes_i386.c b/runtime/uprobes/uprobes_i386.c
index 21420681..5fe7d781 100644
--- a/runtime/uprobes/uprobes_i386.c
+++ b/runtime/uprobes/uprobes_i386.c
@@ -69,8 +69,8 @@
W(0x80, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 80 */
W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* 90 */
W(0xa0, 1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,1)| /* a0 */
- W(0xb0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* b0 */
- W(0xc0, 1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1)| /* c0 */
+ W(0xb0, 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1), /* b0 */
+ W(0xc0, 1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1)| /* c0 */
W(0xd0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* d0 */
W(0xe0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* e0 */
W(0xf0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) /* f0 */
@@ -80,10 +80,8 @@
/*
* TODO:
- * - Allow valid 2-byte opcodes (first byte = 0x0f).
- * - Where necessary, examine the modrm byte and allow valid instructions
+ * - Where necessary, examine the modrm byte and allow only valid instructions
* in the different Groups and fpu instructions.
- * - Allow at least some instruction prefixes.
* - Note: If we go past the first byte, do we need to verify that
* subsequent bytes were actually there, rather than off the last page?
* Probably overkill. We don't verify that they specified the first byte
@@ -104,12 +102,11 @@
* fa, fb - cli, sti
*
* opcodes we may need to refine support for:
- * 0f - valid 2-byte opcodes
* 66 - data16 prefix
* 8f - Group 1 - only reg = 0 is OK
* c6-c7 - Group 11 - only reg = 0 is OK
* d9-df - fpu insns with some illegal encodings
- * fe - Group 4 - only reg = 1 or 2 is OK
+ * fe - Group 4 - only reg = 0 or 1 is OK
* ff - Group 5 - only reg = 0-6 is OK
*
* others -- Do we need to support these?
@@ -123,7 +120,8 @@
*/
static
-int arch_validate_probed_insn(struct uprobe_probept *ppt)
+int arch_validate_probed_insn(struct uprobe_probept *ppt,
+ struct task_struct *tsk)
{
uprobe_opcode_t *insn = ppt->insn;
@@ -138,9 +136,9 @@ int arch_validate_probed_insn(struct uprobe_probept *ppt)
printk(KERN_ERR "uprobes does not currently support probing "
"instructions with the 2-byte opcode 0x0f 0x%2.2x\n",
insn[1]);
- }
- printk(KERN_ERR "uprobes does not currently support probing "
- "instructions whose first byte is 0x%2.2x\n", insn[0]);
+ } else
+ printk(KERN_ERR "uprobes does not currently support probing "
+ "instructions whose first byte is 0x%2.2x\n", insn[0]);
return -EPERM;
}
diff --git a/runtime/uprobes/uprobes_i386.h b/runtime/uprobes/uprobes_i386.h
index 6e2aae70..e4376b95 100644
--- a/runtime/uprobes/uprobes_i386.h
+++ b/runtime/uprobes/uprobes_i386.h
@@ -32,17 +32,22 @@ typedef u8 uprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0xcc
#define BP_INSN_SIZE 1
#define MAX_UINSN_BYTES 16
-#define SLOT_IP 12 /* instruction pointer slot from include/asm/elf.h */
+#define SLOT_IP(tsk) 12 /* instruction pointer slot from include/asm/elf.h */
#define BREAKPOINT_SIGNAL SIGTRAP
#define SSTEP_SIGNAL SIGTRAP
+struct uprobe_probept_arch_info {};
+struct uprobe_task_arch_info {};
+
/* Architecture specific switch for where the IP points after a bp hit */
#define ARCH_BP_INST_PTR(inst_ptr) (inst_ptr - BP_INSN_SIZE)
struct uprobe_probept;
struct uprobe_task;
-static int arch_validate_probed_insn(struct uprobe_probept *ppt);
+struct task_struct;
+static int arch_validate_probed_insn(struct uprobe_probept *ppt,
+ struct task_struct *tsk);
/* On i386, the int3 traps leaves eip pointing past the int3 instruction. */
static inline unsigned long arch_get_probept(struct pt_regs *regs)
diff --git a/runtime/uprobes/uprobes_ppc64.h b/runtime/uprobes/uprobes_ppc64.h
index 619ba324..16e11975 100644
--- a/runtime/uprobes/uprobes_ppc64.h
+++ b/runtime/uprobes/uprobes_ppc64.h
@@ -34,15 +34,20 @@ typedef unsigned int uprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
#define BP_INSN_SIZE 4
#define MAX_UINSN_BYTES 4
-#define SLOT_IP 32 /* instruction pointer slot from include/asm/elf.h */
+#define SLOT_IP(tsk) 32 /* instruction pointer slot from include/asm/elf.h */
+
+struct uprobe_probept_arch_info {};
+struct uprobe_task_arch_info {};
/* Architecture specific switch for where the IP points after a bp hit */
#define ARCH_BP_INST_PTR(inst_ptr) (inst_ptr)
struct uprobe_probept;
struct uprobe_task;
+struct task_struct;
-static inline int arch_validate_probed_insn(struct uprobe_probept *ppt)
+static inline int arch_validate_probed_insn(struct uprobe_probept *ppt,
+ struct task_struct *tsk);
{
return 0;
}
diff --git a/runtime/uprobes/uprobes_s390.h b/runtime/uprobes/uprobes_s390.h
index 4f3a8187..5c711275 100644
--- a/runtime/uprobes/uprobes_s390.h
+++ b/runtime/uprobes/uprobes_s390.h
@@ -40,9 +40,9 @@ typedef u16 uprobe_opcode_t;
#define SSTEP_SIGNAL SIGTRAP
#ifdef CONFIG_COMPAT
-#define SLOT_IP (test_tsk_thread_flag(current, TIF_31BIT) ? 0x04 : 0x08)
+#define SLOT_IP(tsk) (test_tsk_thread_flag(tsk, TIF_31BIT) ? 0x04 : 0x08)
#else
-#define SLOT_IP 0x08
+#define SLOT_IP(tsk) 0x08
#endif
#define FIXUP_PSW_NORMAL 0x08
@@ -50,12 +50,16 @@ typedef u16 uprobe_opcode_t;
#define FIXUP_RETURN_REGISTER 0x02
#define FIXUP_NOT_REQUIRED 0x01
+struct uprobe_probept_arch_info {};
+struct uprobe_task_arch_info {};
+
/* Architecture specific switch for where the IP points after a bp hit */
#define ARCH_BP_INST_PTR(inst_ptr) (inst_ptr - BP_INSN_SIZE)
struct uprobe_probept;
struct uprobe_task;
-static int arch_validate_probed_insn(struct uprobe_probept *ppt);
+static int arch_validate_probed_insn(struct uprobe_probept *ppt,
+ struct task_struct *tsk);
/*
* On s390, a trap leaves the instruction pointer pointing past the