Commit 519a8a6c authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David S. Miller

net: Revert "net: optimize the sockptr_t for unified kernel/user address spaces"

This reverts commits 6d04fe15 and
a31edb20.

It turns out the idea to share a single pointer for both kernel and user
space address causes various kinds of problems.  So use the slightly less
optimal version that uses an extra bit, but which is guaranteed to be safe
everywhere.

Fixes: 6d04fe15 ("net: optimize the sockptr_t for unified kernel/user address spaces")
Reported-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c7ab580
...@@ -8,26 +8,9 @@ ...@@ -8,26 +8,9 @@
#ifndef _LINUX_SOCKPTR_H #ifndef _LINUX_SOCKPTR_H
#define _LINUX_SOCKPTR_H #define _LINUX_SOCKPTR_H
#include <linux/compiler.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
typedef union {
void *kernel;
void __user *user;
} sockptr_t;
static inline bool sockptr_is_kernel(sockptr_t sockptr)
{
return (unsigned long)sockptr.kernel >= TASK_SIZE;
}
static inline sockptr_t KERNEL_SOCKPTR(void *p)
{
return (sockptr_t) { .kernel = p };
}
#else /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
typedef struct { typedef struct {
union { union {
void *kernel; void *kernel;
...@@ -45,15 +28,10 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p) ...@@ -45,15 +28,10 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
{ {
return (sockptr_t) { .kernel = p, .is_kernel = true }; return (sockptr_t) { .kernel = p, .is_kernel = true };
} }
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p, static inline sockptr_t USER_SOCKPTR(void __user *p)
size_t size)
{ {
if (!access_ok(p, size)) return (sockptr_t) { .user = p };
return -EFAULT;
*sp = (sockptr_t) { .user = p };
return 0;
} }
static inline bool sockptr_is_null(sockptr_t sockptr) static inline bool sockptr_is_null(sockptr_t sockptr)
......
...@@ -57,18 +57,16 @@ int bpfilter_ip_set_sockopt(struct sock *sk, int optname, sockptr_t optval, ...@@ -57,18 +57,16 @@ int bpfilter_ip_set_sockopt(struct sock *sk, int optname, sockptr_t optval,
return bpfilter_mbox_request(sk, optname, optval, optlen, true); return bpfilter_mbox_request(sk, optname, optval, optlen, true);
} }
int bpfilter_ip_get_sockopt(struct sock *sk, int optname, int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
char __user *user_optval, int __user *optlen) int __user *optlen)
{ {
sockptr_t optval; int len;
int err, len;
if (get_user(len, optlen)) if (get_user(len, optlen))
return -EFAULT; return -EFAULT;
err = init_user_sockptr(&optval, user_optval, len);
if (err) return bpfilter_mbox_request(sk, optname, USER_SOCKPTR(optval), len,
return err; false);
return bpfilter_mbox_request(sk, optname, optval, len, false);
} }
static int __init bpfilter_sockopt_init(void) static int __init bpfilter_sockopt_init(void)
......
...@@ -2095,7 +2095,7 @@ static bool sock_use_custom_sol_socket(const struct socket *sock) ...@@ -2095,7 +2095,7 @@ static bool sock_use_custom_sol_socket(const struct socket *sock)
int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval, int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
int optlen) int optlen)
{ {
sockptr_t optval; sockptr_t optval = USER_SOCKPTR(user_optval);
char *kernel_optval = NULL; char *kernel_optval = NULL;
int err, fput_needed; int err, fput_needed;
struct socket *sock; struct socket *sock;
...@@ -2103,10 +2103,6 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval, ...@@ -2103,10 +2103,6 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
if (optlen < 0) if (optlen < 0)
return -EINVAL; return -EINVAL;
err = init_user_sockptr(&optval, user_optval, optlen);
if (err)
return err;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
return err; return err;
......
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