]> sourceware.org Git - systemtap.git/commitdiff
(PR14488 partial fix) Make memory writing more robust.
authorDavid Smith <dsmith@redhat.com>
Mon, 10 Sep 2012 21:20:16 +0000 (16:20 -0500)
committerDavid Smith <dsmith@redhat.com>
Mon, 10 Sep 2012 21:20:16 +0000 (16:20 -0500)
* runtime/dyninst/linux_defs.h (__copy_from_user): Remove unused code (and
  update comment).
  (__put_user): New macro.
  (__copy_to_user): New function.
  (__put_user_fn): Ditto.
* runtime/dyninst/loc2c-runtime.h (__get_user_asm): Fix macro to return
  error code.
  (__put_user_asm): New macro.

runtime/dyninst/linux_defs.h
runtime/dyninst/loc2c-runtime.h

index 4934f421911dd2524aebcb2932a558611e266c8b..7ccdf56d92c6157db663762f17d9470ac4a898ac 100644 (file)
@@ -160,17 +160,14 @@ static inline __must_check long __copy_from_user(void *to,
 {
        int rc = 0;
 
-       /* The pread syscall is faster than lseek()/read() (since it
-        * is only one syscall). 
+       /*
+        * The pread syscall is faster than lseek()/read() (since it
+        * is only one syscall). Also, if we used lseek()/read() we
+        * couldn't use a cached fd - since 2 threads might hit this
+        * code at the same time and the 2nd lseek() might finish
+        * before the 1st read()...
         */
-       /* FIXME _ need a pread configure test */
-#define HAVE_PREAD
-#ifdef HAVE_PREAD
-       if (pread (_stp_mem_fd, to, n, (off_t)from) != n)
-#else
-       if (lseek (_stp_mem_fd, (off_t)from, SEEK_SET) == -1
-           || read (_stp_mem_fd, to, n) != n)
-#endif
+       if (pread(_stp_mem_fd, to, n, (off_t)from) != n)
                rc = -EFAULT;
        return rc;
 }
@@ -183,6 +180,64 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 
 extern int __get_user_bad(void) __attribute__((noreturn));
 
+#define __put_user(x, ptr)                                             \
+({                                                                     \
+       int __gu_err = -EFAULT;                                         \
+       __chk_user_ptr(ptr);                                            \
+       switch (sizeof(*(ptr))) {                                       \
+       case 1: {                                                       \
+               unsigned char __x = (unsigned char)(x);                 \
+               __gu_err = __put_user_fn(sizeof (*(ptr)),               \
+                                        ptr, &__x);                    \
+               break;                                                  \
+       };                                                              \
+       case 2: {                                                       \
+               unsigned short __x = (unsigned short)(x);               \
+               __gu_err = __put_user_fn(sizeof (*(ptr)),               \
+                                        ptr, &__x);                    \
+               break;                                                  \
+       };                                                              \
+       case 4: {                                                       \
+               unsigned int __x = (unsigned int)(x);                   \
+               __gu_err = __put_user_fn(sizeof (*(ptr)),               \
+                                        ptr, &__x);                    \
+               break;                                                  \
+       };                                                              \
+       case 8: {                                                       \
+               unsigned long long __x = (unsigned long long)(x);       \
+               __gu_err = __put_user_fn(sizeof (*(ptr)),               \
+                                        ptr, &__x);                    \
+               break;                                                  \
+       };                                                              \
+       default:                                                        \
+               __put_user_bad();                                       \
+               break;                                                  \
+       }                                                               \
+       __gu_err;                                                       \
+})
+
+static inline __must_check long __copy_to_user(void *to, const void *from,
+                                              unsigned long n)
+{
+       int rc = 0;
+
+       /*
+        * The pwrite syscall is faster than lseek()/write() (since it
+        * is only one syscall).
+        */
+       if (pwrite(_stp_mem_fd, to, n, (off_t)from) != n)
+               rc = -EFAULT;
+       return rc;
+}
+
+static inline int __put_user_fn(size_t size, const void __user *ptr, void *x)
+{
+       size = __copy_to_user(x, ptr, size);
+       return size ? -EFAULT : size;
+}
+
+extern int __put_user_bad(void) __attribute__((noreturn));
+
 static inline void INIT_LIST_HEAD(struct list_head *list)
 {
        list->next = list;
index 42dd2c2181dd7a49e3b4ce799915b31cd7729921..53532ebde01eddad39f199de8cc902a3d8774a2c 100644 (file)
@@ -1,5 +1,7 @@
 #include "../loc2c-runtime.h"
 
 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)      \
-       __get_user((x), (typeof(x)*)(addr))
+       (err) = __get_user((x), (typeof(x)*)(addr))
 
+#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)      \
+       (err) = __put_user((x), (typeof(x)*)(addr))
This page took 0.031971 seconds and 5 git commands to generate.