diff options
-rw-r--r-- | runtime/ChangeLog | 5 | ||||
-rw-r--r-- | runtime/copy.c | 32 | ||||
-rw-r--r-- | runtime/stack-i386.c | 4 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 2 | ||||
-rw-r--r-- | runtime/stack.c | 2 | ||||
-rw-r--r-- | runtime/unwind.c | 17 |
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; |