Commit 99447171 authored by Stephen Rothwell's avatar Stephen Rothwell Committed by Linus Torvalds

[PATCH] compat_uptr_t and compat_ptr

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). 
parent bfdb07ae
...@@ -191,7 +191,7 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, ...@@ -191,7 +191,7 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
case F_GETLK: case F_GETLK:
case F_SETLK: case F_SETLK:
case F_SETLKW: case F_SETLKW:
ret = get_compat_flock(&f, (struct compat_flock *)arg); ret = get_compat_flock(&f, compat_ptr(arg));
if (ret != 0) if (ret != 0)
break; break;
old_fs = get_fs(); old_fs = get_fs();
...@@ -203,15 +203,14 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, ...@@ -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)) ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
ret = -EOVERFLOW; ret = -EOVERFLOW;
if (ret == 0) if (ret == 0)
ret = put_compat_flock(&f, ret = put_compat_flock(&f, compat_ptr(arg));
(struct compat_flock *)arg);
} }
break; break;
case F_GETLK64: case F_GETLK64:
case F_SETLK64: case F_SETLK64:
case F_SETLKW64: case F_SETLKW64:
ret = get_compat_flock64(&f, (struct compat_flock64 *)arg); ret = get_compat_flock64(&f, compat_ptr(arg));
if (ret != 0) if (ret != 0)
break; break;
old_fs = get_fs(); old_fs = get_fs();
...@@ -226,8 +225,7 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, ...@@ -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)) ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
ret = -EOVERFLOW; ret = -EOVERFLOW;
if (ret == 0) if (ret == 0)
ret = put_compat_flock64(&f, ret = put_compat_flock64(&f, compat_ptr(arg));
(struct compat_flock64 *)arg);
} }
break; break;
......
...@@ -104,4 +104,17 @@ typedef u32 compat_sigset_word; ...@@ -104,4 +104,17 @@ typedef u32 compat_sigset_word;
#define COMPAT_OFF_T_MAX 0x7fffffff #define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL #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 */ #endif /* _ASM_PARISC_COMPAT_H */
...@@ -98,4 +98,17 @@ typedef u32 compat_sigset_word; ...@@ -98,4 +98,17 @@ typedef u32 compat_sigset_word;
#define COMPAT_OFF_T_MAX 0x7fffffff #define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL #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 */ #endif /* _ASM_PPC64_COMPAT_H */
...@@ -101,4 +101,17 @@ typedef u32 compat_sigset_word; ...@@ -101,4 +101,17 @@ typedef u32 compat_sigset_word;
#define COMPAT_OFF_T_MAX 0x7fffffff #define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL #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 */ #endif /* _ASM_S390X_COMPAT_H */
...@@ -100,4 +100,17 @@ typedef u32 compat_sigset_word; ...@@ -100,4 +100,17 @@ typedef u32 compat_sigset_word;
#define COMPAT_OFF_T_MAX 0x7fffffff #define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL #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 */ #endif /* _ASM_SPARC64_COMPAT_H */
...@@ -107,4 +107,17 @@ typedef u32 compat_sigset_word; ...@@ -107,4 +107,17 @@ typedef u32 compat_sigset_word;
#define COMPAT_OFF_T_MAX 0x7fffffff #define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffff #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 */ #endif /* _ASM_X86_64_COMPAT_H */
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <net/compat_socket.h> #include <net/compat_socket.h>
#define A(__x) ((unsigned long)(__x))
#define AA(__x) ((unsigned long)(__x)) #define AA(__x) ((unsigned long)(__x))
extern asmlinkage long sys_getsockopt(int fd, int level, int optname, 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, ...@@ -49,7 +48,7 @@ static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
break; break;
} }
tot_len += len; tot_len += len;
kiov->iov_base = (void *)A(buf); kiov->iov_base = compat_ptr(buf);
kiov->iov_len = (__kernel_size_t) len; kiov->iov_len = (__kernel_size_t) len;
uiov32++; uiov32++;
kiov++; kiov++;
...@@ -60,7 +59,7 @@ static inline int iov_from_user_compat_to_kern(struct iovec *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) 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; int err;
err = get_user(tmp1, &umsg->msg_name); 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 ...@@ -69,9 +68,9 @@ int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *u
if (err) if (err)
return -EFAULT; return -EFAULT;
kmsg->msg_name = (void *)A(tmp1); kmsg->msg_name = compat_ptr(tmp1);
kmsg->msg_iov = (struct iovec *)A(tmp2); kmsg->msg_iov = compat_ptr(tmp2);
kmsg->msg_control = (void *)A(tmp3); kmsg->msg_control = compat_ptr(tmp3);
err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); 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, ...@@ -451,14 +450,14 @@ static int do_set_attach_filter(int fd, int level, int optname,
struct sock_filter *kfilter; struct sock_filter *kfilter;
unsigned int fsize; unsigned int fsize;
mm_segment_t old_fs; mm_segment_t old_fs;
__u32 uptr; compat_uptr_t uptr;
int ret; int ret;
if (get_user(kfprog.len, &fprog32->len) || if (get_user(kfprog.len, &fprog32->len) ||
__get_user(uptr, &fprog32->filter)) __get_user(uptr, &fprog32->filter))
return -EFAULT; return -EFAULT;
kfprog.filter = (struct sock_filter *)A(uptr); kfprog.filter = compat_ptr(uptr);
fsize = kfprog.len * sizeof(struct sock_filter); fsize = kfprog.len * sizeof(struct sock_filter);
kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
...@@ -639,36 +638,34 @@ asmlinkage long compat_sys_socketcall(int call, u32 *args) ...@@ -639,36 +638,34 @@ asmlinkage long compat_sys_socketcall(int call, u32 *args)
ret = sys_socket(a0, a1, a[2]); ret = sys_socket(a0, a1, a[2]);
break; break;
case SYS_BIND: case SYS_BIND:
ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); ret = sys_bind(a0, compat_ptr(a1), a[2]);
break; break;
case SYS_CONNECT: case SYS_CONNECT:
ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); ret = sys_connect(a0, compat_ptr(a1), a[2]);
break; break;
case SYS_LISTEN: case SYS_LISTEN:
ret = sys_listen(a0, a1); ret = sys_listen(a0, a1);
break; break;
case SYS_ACCEPT: 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; break;
case SYS_GETSOCKNAME: case SYS_GETSOCKNAME:
ret = sys_getsockname(a0, (struct sockaddr *)A(a1), ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
(int *)A(a[2]));
break; break;
case SYS_GETPEERNAME: case SYS_GETPEERNAME:
ret = sys_getpeername(a0, (struct sockaddr *)A(a1), ret = sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2]));
(int *)A(a[2]));
break; break;
case SYS_SOCKETPAIR: 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; break;
case SYS_SEND: 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; break;
case SYS_SENDTO: case SYS_SENDTO:
ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
break; break;
case SYS_RECV: 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; break;
case SYS_RECVFROM: case SYS_RECVFROM:
ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); 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) ...@@ -677,20 +674,18 @@ asmlinkage long compat_sys_socketcall(int call, u32 *args)
ret = sys_shutdown(a0,a1); ret = sys_shutdown(a0,a1);
break; break;
case SYS_SETSOCKOPT: case SYS_SETSOCKOPT:
ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), ret = compat_sys_setsockopt(a0, a1, a[2],
a[4]); compat_ptr(a[3]), a[4]);
break; break;
case SYS_GETSOCKOPT: case SYS_GETSOCKOPT:
ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3], ret = compat_sys_getsockopt(a0, a1, a[2],
(int *)(u64)a[4]); compat_ptr(a[3]), compat_ptr(a[4]));
break; break;
case SYS_SENDMSG: case SYS_SENDMSG:
ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1), ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]);
a[2]);
break; break;
case SYS_RECVMSG: case SYS_RECVMSG:
ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1), ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
a[2]);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment