summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/ChangeLog5
-rw-r--r--runtime/copy.c32
-rw-r--r--runtime/stack-i386.c4
-rw-r--r--runtime/stack-x86_64.c2
-rw-r--r--runtime/stack.c2
-rw-r--r--runtime/unwind.c17
6 files changed, 38 insertions, 24 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index e56fa729..d9ea4474 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,8 @@
+2008-03-28 Martin Hunt <hunt@redhat.com>
+
+ * copy.c (_stp_read_address): New function. Safely read
+ kernel or userspace.
+
2008-03-26 Martin Hunt <hunt@redhat.com>
Fixes to get i386 working.
* unwind.c (unwind): Fix types in debug print.
diff --git a/runtime/copy.c b/runtime/copy.c
index ef3fd223..8891f171 100644
--- a/runtime/copy.c
+++ b/runtime/copy.c
@@ -9,11 +9,10 @@
* later version.
*/
-#ifndef _COPY_C_ /* -*- linux-c -*- */
+#ifndef _COPY_C_ /* -*- linux-c -*- */
#define _COPY_C_
#include "string.c"
-
/** @file copy.c
* @brief Functions to copy from user space.
*/
@@ -26,6 +25,28 @@
* @{
*/
+/** Safely read from userspace or kernelspace.
+ * On success, returns 0. Returns -EFAULT on error.
+ *
+ * This uses __get_user() to read from userspace or
+ * kernelspace. Will not sleep or cause pagefaults when
+ * called from within a kprobe context.
+ *
+ * @param segment . KERNEL_DS for kernel access
+ * USER_DS for userspace.
+ */
+
+#define _stp_read_address(x, ptr, segment) \
+ ({ \
+ long ret; \
+ mm_segment_t ofs = get_fs(); \
+ set_fs(segment); \
+ ret = __stp_get_user(x, ptr); \
+ set_fs(ofs); \
+ ret; \
+ })
+
+
long _stp_strncpy_from_user(char *dst, const char __user *src, long count);
//static long __stp_strncpy_from_user(char *dst, const char __user *src, long count);
@@ -110,8 +131,7 @@ do { \
* <i>count</i> bytes and returns <i>count</i>.
*/
-long
-_stp_strncpy_from_user(char *dst, const char __user *src, long count)
+long _stp_strncpy_from_user(char *dst, const char __user *src, long count)
{
long res = -EFAULT;
if (access_ok(VERIFY_READ, src, count))
@@ -119,7 +139,6 @@ _stp_strncpy_from_user(char *dst, const char __user *src, long count)
return res;
}
-
/** Copy a block of data from user space.
*
* If some data could not be copied, this function will pad the copied
@@ -133,8 +152,7 @@ _stp_strncpy_from_user(char *dst, const char __user *src, long count)
*
*/
-unsigned long
-_stp_copy_from_user (char *dst, const char __user *src, unsigned long count)
+unsigned long _stp_copy_from_user(char *dst, const char __user *src, unsigned long count)
{
if (count) {
if (access_ok(VERIFY_READ, src, count))
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c
index d7c2c201..c99b4a8c 100644
--- a/runtime/stack-i386.c
+++ b/runtime/stack-i386.c
@@ -18,7 +18,7 @@ static void _stp_stack_print_fallback(unsigned long context, unsigned long stack
{
unsigned long addr;
while (_stp_valid_stack_ptr(context, stack)) {
- if (unlikely(__stp_get_user(addr, (unsigned long *)stack))) {
+ if (unlikely(_stp_read_address(addr, (unsigned long *)stack, KERNEL_DS))) {
/* cannot access stack. give up. */
return;
}
@@ -43,7 +43,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
#endif /* STAPCONF_X86_UNIREGS */
while (_stp_valid_stack_ptr(context, (unsigned long)ebp)) {
- if (unlikely(__stp_get_user(addr, (unsigned long *)(ebp + 4)))) {
+ if (unlikely(_stp_read_address(addr, (unsigned long *)(ebp + 4), KERNEL_DS))) {
/* cannot access stack. give up. */
return;
}
diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c
index 846653be..96f82004 100644
--- a/runtime/stack-x86_64.c
+++ b/runtime/stack-x86_64.c
@@ -15,7 +15,7 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose)
{
unsigned long addr;
while (stack & (THREAD_SIZE - 1)) {
- if (unlikely(__stp_get_user(addr, (unsigned long *)stack))) {
+ if (unlikely(_stp_read_address(addr, (unsigned long *)stack, KERNEL_DS))) {
/* cannot access stack. give up. */
return;
}
diff --git a/runtime/stack.c b/runtime/stack.c
index eefdf715..772c5baf 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -62,7 +62,7 @@ void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instan
}
_stp_print_char('\n');
} else if (pi)
- _stp_printf("%p %p ", (int64_t) _stp_ret_addr_r(pi), (int64_t) REG_IP(regs));
+ _stp_printf("%p %p ", (int64_t)(long)_stp_ret_addr_r(pi), (int64_t) REG_IP(regs));
else
_stp_printf("%p ", (int64_t) REG_IP(regs));
diff --git a/runtime/unwind.c b/runtime/unwind.c
index e8cba72e..f0010372 100644
--- a/runtime/unwind.c
+++ b/runtime/unwind.c
@@ -321,7 +321,7 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end, signed ptrTy
return 0;
}
if ((ptrType & DW_EH_PE_indirect)
- && __stp_get_user(value, (unsigned long *)value))
+ && _stp_read_address(value, (unsigned long *)value, KERNEL_DS))
return 0;
*pLoc = ptr.p8;
@@ -676,7 +676,7 @@ int unwind(struct unwind_frame_info *frame)
#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
const u32 *fde, *cie = NULL;
const u8 *ptr = NULL, *end = NULL;
- unsigned long pc = UNW_PC(frame);
+ unsigned long pc = UNW_PC(frame) - frame->call_frame;
unsigned long tableSize, startLoc = 0, endLoc = 0, cfa;
unsigned i;
signed ptrType = -1;
@@ -684,15 +684,6 @@ int unwind(struct unwind_frame_info *frame)
struct _stp_module *m;
struct unwind_state state;
- if (pc != _stp_kretprobe_trampoline)
- pc -= frame->call_frame;
- else {
- unsigned long a1, a2, *addr = (unsigned long *)UNW_SP(frame);
- __stp_get_user(a1, addr);
- __stp_get_user(a2, addr+1);
- dbug_unwind(1, "TRAMPOLINE: SP=%lx *SP=%lx *(SP+1)=%lx\n", UNW_SP(frame), a1, a2);
- return -EINVAL;
- }
dbug_unwind(1, "pc=%lx, %lx", pc, UNW_PC(frame));
if (UNW_PC(frame) == 0)
@@ -933,7 +924,7 @@ int unwind(struct unwind_frame_info *frame)
dbug_unwind(2, "addr=%lx width=%d\n", addr, reg_info[i].width);
switch (reg_info[i].width) {
#define CASE(n) case sizeof(u##n): \
- if (unlikely(__stp_get_user(FRAME_REG(i, u##n), (u##n *)addr))) \
+ if (unlikely(_stp_read_address(FRAME_REG(i, u##n), (u##n *)addr, KERNEL_DS))) \
goto copy_failed;\
dbug_unwind(1, "set register %d to %lx\n", i, (long)FRAME_REG(i,u##n));\
break
@@ -952,7 +943,7 @@ int unwind(struct unwind_frame_info *frame)
return 0;
copy_failed:
- dbug_unwind(1, "_stp_get_user failed to access memory\n");
+ dbug_unwind(1, "_stp_read_address failed to access memory\n");
err:
read_unlock(&m->lock);
return -EIO;