Commit a7a905fa authored by David S. Miller's avatar David S. Miller

[NET]: Fix sock_fprog setsockopt compat handling. Based upon patch from Andi Kleen.

parent 13d6a99c
......@@ -672,21 +672,6 @@ static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
return err;
}
static inline void *alloc_user_space(long len)
{
struct pt_regs *regs = current->thread.regs;
unsigned long usp = regs->gpr[1];
/*
* We cant access below the stack pointer in the 32bit ABI and
* can access 288 bytes in the 64bit ABI
*/
if (!(test_thread_flag(TIF_32BIT)))
usp -= 288;
return (void *) (usp - len);
}
int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct ifreq *u_ifreq64;
......@@ -702,7 +687,7 @@ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
return -EFAULT;
data64 = A(data32);
u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
/* Don't check these user accesses, just let that get trapped
* in the ioctl handler instead.
......
......@@ -659,17 +659,6 @@ static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
return err;
}
static __inline__ void *alloc_user_space(long len)
{
struct pt_regs *regs = current_thread_info()->kregs;
unsigned long usp = regs->u_regs[UREG_I6];
if (!(test_thread_flag(TIF_32BIT)))
usp += STACK_BIAS;
return (void *) (usp - len);
}
int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct ifreq *u_ifreq64;
......@@ -685,7 +674,7 @@ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
return -EFAULT;
data64 = A(data32);
u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
/* Don't check these user accesses, just let that get trapped
* in the ioctl handler instead.
......@@ -1701,7 +1690,7 @@ struct sock_fprog32 {
static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg;
struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog));
struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
void __user *fptr64;
u32 fptr32;
u16 flen;
......
......@@ -671,12 +671,6 @@ static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
return err;
}
static __inline__ void *alloc_user_space(long len)
{
struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs);
return (void *)regs->rsp - len;
}
int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct ifreq *u_ifreq64;
......@@ -692,7 +686,7 @@ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
return -EFAULT;
data64 = (void *) A(data32);
u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
/* Don't check these user accesses, just let that get trapped
* in the ioctl handler instead.
......@@ -1573,7 +1567,7 @@ struct sock_fprog32 {
static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg;
struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog));
struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
void *fptr64;
u32 fptr32;
u16 flen;
......
......@@ -119,4 +119,19 @@ static inline void *compat_ptr(compat_uptr_t uptr)
return (void *)(unsigned long)uptr;
}
static inline void *compat_alloc_user_space(long len)
{
struct pt_regs *regs = current->thread.regs;
unsigned long usp = regs->gpr[1];
/*
* We cant access below the stack pointer in the 32bit ABI and
* can access 288 bytes in the 64bit ABI
*/
if (!(test_thread_flag(TIF_32BIT)))
usp -= 288;
return (void *) (usp - len);
}
#endif /* _ASM_PPC64_COMPAT_H */
......@@ -120,4 +120,15 @@ static inline void *compat_ptr(compat_uptr_t uptr)
return (void *)(unsigned long)uptr;
}
static __inline__ void *compat_alloc_user_space(long len)
{
struct pt_regs *regs = current_thread_info()->kregs;
unsigned long usp = regs->u_regs[UREG_I6];
if (!(test_thread_flag(TIF_32BIT)))
usp += STACK_BIAS;
return (void *) (usp - len);
}
#endif /* _ASM_SPARC64_COMPAT_H */
......@@ -128,4 +128,10 @@ static inline void *compat_ptr(compat_uptr_t uptr)
return (void *)(unsigned long)uptr;
}
static __inline__ void *compat_alloc_user_space(long len)
{
struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs);
return (void *)regs->rsp - len;
}
#endif /* _ASM_X86_64_COMPAT_H */
......@@ -389,30 +389,20 @@ static int do_set_attach_filter(int fd, int level, int optname,
char *optval, int optlen)
{
struct compat_sock_fprog *fprog32 = (struct compat_sock_fprog *)optval;
struct sock_fprog kfprog;
mm_segment_t old_fs;
int ret;
struct sock_fprog *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
compat_uptr_t ptr;
u16 len;
if (!access_ok(VERIFY_READ, fprog32, sizeof(*fprog32)) ||
__get_user(kfprog.len, &fprog32->len) ||
__get_user(ptr, &fprog32->filter))
return -EFAULT;
kfprog.filter = compat_ptr(ptr);
if (kfprog.len * sizeof(struct sock_filter) < kfprog.len)
return -EINVAL;
if (verify_area(VERIFY_READ, kfprog.filter,
kfprog.len * sizeof(struct sock_filter)))
!access_ok(VERIFY_WRITE, kfprog, sizeof(struct sock_fprog)) ||
__get_user(len, &fprog32->len) ||
__get_user(ptr, &fprog32->filter) ||
__put_user(len, &kfprog->len) ||
__put_user(compat_ptr(ptr), &kfprog->filter))
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_setsockopt(fd, level, optname,
(char *)&kfprog, sizeof(kfprog));
set_fs(old_fs);
return ret;
return sys_setsockopt(fd, level, optname, (char *)kfprog,
sizeof(struct sock_fprog));
}
static int do_set_icmpv6_filter(int fd, int level, int optname,
......
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