This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug runtime/14848] New: Reading user memory fails occasionally when it shouldn't


http://sourceware.org/bugzilla/show_bug.cgi?id=14848

             Bug #: 14848
           Summary: Reading user memory fails occasionally when it
                    shouldn't
           Product: systemtap
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: runtime
        AssignedTo: systemtap@sourceware.org
        ReportedBy: dsmith@redhat.com
    Classification: Unclassified


I was looking at some failures we're seeing in the syscall/nd_syscall test
cases on RHEL6 (2.6.32-279.14.1.el6.x86_64). Note I'm seeing the exact same
failure on rawhide (3.7.0-0.rc4.git3.1.fc19.x86_64).

The 32-bit clock tests are failing, because we fail to be able to read user
memory for the 2nd parameter of clock_settime(). The 64-bit clock test passes.

Here's the syscall.clock_settime probe from syscalls.stp (the nd_syscall
variant looks very similar):

====
probe syscall.clock_settime = kernel.function("sys_clock_settime").call
{
    name = "clock_settime"
    clk_id = $which_clock
    clk_id_str = _get_wc_str($which_clock)
    tp_uaddr = $tp
    argstr = sprintf("%s, %s", clk_id_str, _struct_timespec_u($tp, 1))
}
====

The problem is that _struct_timespec_u() is failing. The code in it that reads
user memory looks like this (from aux_syscalls.stp):

====
  if(_stp_copy_from_user((char *)&ts, ptr, n*sizeof(struct compat_timespec))) 
{
    strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN);
  }
====

Here's _stp_copy_from_user() from copy.c:

====
static unsigned long _stp_copy_from_user(char *dst, const char __user *src,
unsigned long count)
{
    if (count) {
                mm_segment_t _oldfs = get_fs();
                set_fs(USER_DS);
                pagefault_disable();
        if (access_ok(VERIFY_READ, src, count))
            count = __copy_from_user_inatomic(dst, src, count);
        else
            memset(dst, 0, count);
                pagefault_enable();
                set_fs(_oldfs);
    }
    return count;
}
====

Strangely enough, if I remove the access_ok() call, __copy_from_user_inatomic()
works fine. If I move the set_fs() call after the access_ok() call (which
effectively neuters the access_ok() call for x86_64 if I'm reading
arch/x86/asm/uaccess.h correctly), __copy_from_user_inatomic() also works fine.

I don't know why access_ok() is failing in this situation on an address that is
valid.

Just for reference, here's the code from sys_clock_settime() which accesses
user memory. Note it doesn't call access_ok():

====
    if (copy_from_user(&new_tp, tp, sizeof (*tp)))
        return -EFAULT;
====

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]