summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-05-19 09:32:06 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-05-19 09:32:06 -0700
commita7a905fac9188df903deef4aea4a339864fdd895 (patch)
treecdf38b62aefe545977bfd5466ce1523918be6d42
parent13d6a99c44c8ff3298f4d447b321000ec4cd4d8d (diff)
[NET]: Fix sock_fprog setsockopt compat handling. Based upon patch from Andi Kleen.
-rw-r--r--arch/ppc64/kernel/ioctl32.c17
-rw-r--r--arch/sparc64/kernel/ioctl32.c15
-rw-r--r--arch/x86_64/ia32/ia32_ioctl.c10
-rw-r--r--include/asm-ppc64/compat.h15
-rw-r--r--include/asm-sparc64/compat.h11
-rw-r--r--include/asm-x86_64/compat.h6
-rw-r--r--net/compat.c28
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,