]> git.hungrycats.org Git - linux/commitdiff
[PATCH] compat_uptr_t and compat_ptr
authorStephen Rothwell <sfr@canb.auug.org.au>
Sun, 23 Mar 2003 12:59:16 +0000 (04:59 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sun, 23 Mar 2003 12:59:16 +0000 (04:59 -0800)
This creates compat_uptr_t (to represent a user mode pointer passed to
the kernel other than as a syscall parameter) and compat_ptr() to
convert it to a kernel pointer.

This fixes a couple of bugs in s390x (where the conversion of pointers
actually does something).

fs/compat.c
include/asm-parisc/compat.h
include/asm-ppc64/compat.h
include/asm-s390x/compat.h
include/asm-sparc64/compat.h
include/asm-x86_64/compat.h
net/compat.c

index 94aae781930ffc114daa2827da44f9e6a82dd336..da8c6d8ae49099969b82361d3021af4102a2ee6e 100644 (file)
@@ -191,7 +191,7 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
        case F_GETLK:
        case F_SETLK:
        case F_SETLKW:
-               ret = get_compat_flock(&f, (struct compat_flock *)arg);
+               ret = get_compat_flock(&f, compat_ptr(arg));
                if (ret != 0)
                        break;
                old_fs = get_fs();
@@ -203,15 +203,14 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
                            ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
                                ret = -EOVERFLOW;
                        if (ret == 0)
-                               ret = put_compat_flock(&f,
-                                               (struct compat_flock *)arg);
+                               ret = put_compat_flock(&f, compat_ptr(arg));
                }
                break;
 
        case F_GETLK64:
        case F_SETLK64:
        case F_SETLKW64:
-               ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+               ret = get_compat_flock64(&f, compat_ptr(arg));
                if (ret != 0)
                        break;
                old_fs = get_fs();
@@ -226,8 +225,7 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
                            ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
                                ret = -EOVERFLOW;
                        if (ret == 0)
-                               ret = put_compat_flock64(&f,
-                                               (struct compat_flock64 *)arg);
+                               ret = put_compat_flock64(&f, compat_ptr(arg));
                }
                break;
 
index 13f59a86b0fb2ccb1d6d066ac172b7f59ee05908..6275a374f08e386e0f8460c48daa6fb4305a633a 100644 (file)
@@ -104,4 +104,17 @@ typedef u32                compat_sigset_word;
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef        u32             compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+       return (void *)uptr;
+}
+
 #endif /* _ASM_PARISC_COMPAT_H */
index 75cb531ca3e3e6bdfda25b3783c69009a495911c..bfd37734504951387def3c89411d0b2a187583e5 100644 (file)
@@ -98,4 +98,17 @@ typedef u32          compat_sigset_word;
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef        u32             compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+       return (void *)uptr;
+}
+
 #endif /* _ASM_PPC64_COMPAT_H */
index 55e23c9b36fe1319aa946bf6a81000185bc96dc6..d1e948ae4bffabd550cb0a47c2ee28d51a481915 100644 (file)
@@ -101,4 +101,17 @@ typedef u32                compat_sigset_word;
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef        u32             compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+       return (void *)(uptr & 0x7fffffffUL);
+}
+
 #endif /* _ASM_S390X_COMPAT_H */
index cd8de69c701a6da1e6429410e1403781a0426f24..81620b24a1c23f344140e2ce653114f64f7373d8 100644 (file)
@@ -100,4 +100,17 @@ typedef u32                compat_sigset_word;
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef        u32             compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+       return (void *)uptr;
+}
+
 #endif /* _ASM_SPARC64_COMPAT_H */
index 36be83b589697954fc3d62cde9cdc6ccc1b59f29..86d7495d48b5034297e1bbb94acc4b2188c1ca9b 100644 (file)
@@ -107,4 +107,17 @@ typedef u32               compat_sigset_word;
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffff
 
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef        u32             compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+       return (void *)uptr;
+}
+
 #endif /* _ASM_X86_64_COMPAT_H */
index 45a4970b798fd8745b2813b548f246de2728d77c..42160f76d916edc24f676607a8feafe783b847e2 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/uaccess.h>
 #include <net/compat_socket.h>
 
-#define A(__x)         ((unsigned long)(__x))
 #define AA(__x)                ((unsigned long)(__x))
 
 extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
@@ -49,7 +48,7 @@ static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
                        break;
                }
                tot_len += len;
-               kiov->iov_base = (void *)A(buf);
+               kiov->iov_base = compat_ptr(buf);
                kiov->iov_len = (__kernel_size_t) len;
                uiov32++;
                kiov++;
@@ -60,7 +59,7 @@ static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
 
 int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *umsg)
 {
-       u32 tmp1, tmp2, tmp3;
+       compat_uptr_t tmp1, tmp2, tmp3;
        int err;
 
        err = get_user(tmp1, &umsg->msg_name);
@@ -69,9 +68,9 @@ int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *u
        if (err)
                return -EFAULT;
 
-       kmsg->msg_name = (void *)A(tmp1);
-       kmsg->msg_iov = (struct iovec *)A(tmp2);
-       kmsg->msg_control = (void *)A(tmp3);
+       kmsg->msg_name = compat_ptr(tmp1);
+       kmsg->msg_iov = compat_ptr(tmp2);
+       kmsg->msg_control = compat_ptr(tmp3);
 
        err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
        err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
@@ -451,14 +450,14 @@ static int do_set_attach_filter(int fd, int level, int optname,
        struct sock_filter *kfilter;
        unsigned int fsize;
        mm_segment_t old_fs;
-       __u32 uptr;
+       compat_uptr_t uptr;
        int ret;
 
        if (get_user(kfprog.len, &fprog32->len) ||
            __get_user(uptr, &fprog32->filter))
                return -EFAULT;
 
-       kfprog.filter = (struct sock_filter *)A(uptr);
+       kfprog.filter = compat_ptr(uptr);
        fsize = kfprog.len * sizeof(struct sock_filter);
 
        kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
@@ -639,36 +638,34 @@ asmlinkage long compat_sys_socketcall(int call, u32 *args)
                ret = sys_socket(a0, a1, a[2]);
                break;
        case SYS_BIND:
-               ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
+               ret = sys_bind(a0, compat_ptr(a1), a[2]);
                break;
        case SYS_CONNECT:
-               ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
+               ret = sys_connect(a0, compat_ptr(a1), a[2]);
                break;
        case SYS_LISTEN:
                ret = sys_listen(a0, a1);
                break;
        case SYS_ACCEPT:
-               ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
+               ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2]));
                break;
        case SYS_GETSOCKNAME:
-               ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
-                                      (int *)A(a[2]));
+               ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
                break;
        case SYS_GETPEERNAME:
-               ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
-                                      (int *)A(a[2]));
+               ret = sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2]));
                break;
        case SYS_SOCKETPAIR:
-               ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+               ret = sys_socketpair(a0, a1, a[2], compat_ptr(a[3]));
                break;
        case SYS_SEND:
-               ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
+               ret = sys_send(a0, compat_ptr(a1), a[2], a[3]);
                break;
        case SYS_SENDTO:
                ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
                break;
        case SYS_RECV:
-               ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
+               ret = sys_recv(a0, compat_ptr(a1), a[2], a[3]);
                break;
        case SYS_RECVFROM:
                ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
@@ -677,20 +674,18 @@ asmlinkage long compat_sys_socketcall(int call, u32 *args)
                ret = sys_shutdown(a0,a1);
                break;
        case SYS_SETSOCKOPT:
-               ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
-                                     a[4]);
+               ret = compat_sys_setsockopt(a0, a1, a[2],
+                               compat_ptr(a[3]), a[4]);
                break;
        case SYS_GETSOCKOPT:
-               ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3],
-                                           (int *)(u64)a[4]);
+               ret = compat_sys_getsockopt(a0, a1, a[2],
+                               compat_ptr(a[3]), compat_ptr(a[4]));
                break;
        case SYS_SENDMSG:
-               ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1),
-                                        a[2]);
+               ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]);
                break;
        case SYS_RECVMSG:
-               ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1),
-                                        a[2]);
+               ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
                break;
        default:
                ret = -EINVAL;