]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: Revert "net: optimize the sockptr_t for unified kernel/user address spaces"
authorChristoph Hellwig <hch@lst.de>
Mon, 10 Aug 2020 16:42:14 +0000 (18:42 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 10 Aug 2020 19:06:44 +0000 (12:06 -0700)
This reverts commits 073369af28ce37693900f39eb6111eaada5459c3 and
aac6d22d4167727c1107a0b7a856eedb2db30f76.

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: 073369af28ce ("net: optimize the sockptr_t for unified kernel/user address spaces")
Reported-by: Eric Dumazet <edumazet@google.com>
Reported-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/sockptr.h
net/ipv4/bpfilter/sockopt.c
net/socket.c

index 96840def9d69ccd0473a510ed62c21e0c3ccac42..ea193414298b7f9fe24906a4c5ae57cde6e6af19 100644 (file)
@@ -8,26 +8,9 @@
 #ifndef _LINUX_SOCKPTR_H
 #define _LINUX_SOCKPTR_H
 
-#include <linux/compiler.h>
 #include <linux/slab.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 {
        union {
                void            *kernel;
@@ -45,15 +28,10 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
 {
        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,
-               size_t size)
+static inline sockptr_t USER_SOCKPTR(void __user *p)
 {
-       if (!access_ok(p, size))
-               return -EFAULT;
-       *sp = (sockptr_t) { .user = p };
-       return 0;
+       return (sockptr_t) { .user = p };
 }
 
 static inline bool sockptr_is_null(sockptr_t sockptr)
index 545b2640f0194d2c76b26de9e2d3706d02390bf2..1b34cb9a7708ecf8c40eeb138223e090a9e27bc7 100644 (file)
@@ -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);
 }
 
-int bpfilter_ip_get_sockopt(struct sock *sk, int optname,
-                           char __user *user_optval, int __user *optlen)
+int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
+                           int __user *optlen)
 {
-       sockptr_t optval;
-       int err, len;
+       int len;
 
        if (get_user(len, optlen))
                return -EFAULT;
-       err = init_user_sockptr(&optval, user_optval, len);
-       if (err)
-               return err;
-       return bpfilter_mbox_request(sk, optname, optval, len, false);
+
+       return bpfilter_mbox_request(sk, optname, USER_SOCKPTR(optval), len,
+                                    false);
 }
 
 static int __init bpfilter_sockopt_init(void)
index f4d5998bdcbad6936b290844fc69e399b547a16f..dbbe8ea7d395dadf690a4c2dfdf60ed40c49df6d 100644 (file)
@@ -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 optlen)
 {
-       sockptr_t optval;
+       sockptr_t optval = USER_SOCKPTR(user_optval);
        char *kernel_optval = NULL;
        int err, fput_needed;
        struct socket *sock;
@@ -2103,10 +2103,6 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
        if (optlen < 0)
                return -EINVAL;
 
-       err = init_user_sockptr(&optval, user_optval, optlen);
-       if (err)
-               return err;
-
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                return err;