diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2003-05-19 09:32:06 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2003-05-19 09:32:06 -0700 |
| commit | a7a905fac9188df903deef4aea4a339864fdd895 (patch) | |
| tree | cdf38b62aefe545977bfd5466ce1523918be6d42 | |
| parent | 13d6a99c44c8ff3298f4d447b321000ec4cd4d8d (diff) | |
[NET]: Fix sock_fprog setsockopt compat handling. Based upon patch from Andi Kleen.
| -rw-r--r-- | arch/ppc64/kernel/ioctl32.c | 17 | ||||
| -rw-r--r-- | arch/sparc64/kernel/ioctl32.c | 15 | ||||
| -rw-r--r-- | arch/x86_64/ia32/ia32_ioctl.c | 10 | ||||
| -rw-r--r-- | include/asm-ppc64/compat.h | 15 | ||||
| -rw-r--r-- | include/asm-sparc64/compat.h | 11 | ||||
| -rw-r--r-- | include/asm-x86_64/compat.h | 6 | ||||
| -rw-r--r-- | net/compat.c | 28 |
7 files changed, 46 insertions, 56 deletions
diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c index 2ec81b4ce145..b504e47bbcac 100644 --- a/arch/ppc64/kernel/ioctl32.c +++ b/arch/ppc64/kernel/ioctl32.c @@ -672,21 +672,6 @@ out: 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. diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 1cf550e6bafc..5047b4112580 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -659,17 +659,6 @@ out: 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; diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 7f00c346a5d1..bed4b95343fb 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -671,12 +671,6 @@ out: 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; diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h index 913cbd936dd9..cc54b6d83f4b 100644 --- a/include/asm-ppc64/compat.h +++ b/include/asm-ppc64/compat.h @@ -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 */ diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h index 6503e10e5a75..19fe2635d188 100644 --- a/include/asm-sparc64/compat.h +++ b/include/asm-sparc64/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 */ diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h index 90265acf71b2..b73ae6b2a85f 100644 --- a/include/asm-x86_64/compat.h +++ b/include/asm-x86_64/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 */ diff --git a/net/compat.c b/net/compat.c index 149b3db1b53d..625a95c9e6bf 100644 --- a/net/compat.c +++ b/net/compat.c @@ -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, |
