Skip to content

Commit 519a8a6

Browse files
Christoph Hellwigdavem330
authored andcommitted
net: Revert "net: optimize the sockptr_t for unified kernel/user address spaces"
This reverts commits 6d04fe1 and a31edb2. 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: 6d04fe1 ("net: optimize the sockptr_t for unified kernel/user address spaces") Reported-by: Eric Dumazet <[email protected]> Reported-by: John Stultz <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7c7ab58 commit 519a8a6

File tree

3 files changed

+9
-37
lines changed

3 files changed

+9
-37
lines changed

include/linux/sockptr.h

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,9 @@
88
#ifndef _LINUX_SOCKPTR_H
99
#define _LINUX_SOCKPTR_H
1010

11-
#include <linux/compiler.h>
1211
#include <linux/slab.h>
1312
#include <linux/uaccess.h>
1413

15-
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
16-
typedef union {
17-
void *kernel;
18-
void __user *user;
19-
} sockptr_t;
20-
21-
static inline bool sockptr_is_kernel(sockptr_t sockptr)
22-
{
23-
return (unsigned long)sockptr.kernel >= TASK_SIZE;
24-
}
25-
26-
static inline sockptr_t KERNEL_SOCKPTR(void *p)
27-
{
28-
return (sockptr_t) { .kernel = p };
29-
}
30-
#else /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
3114
typedef struct {
3215
union {
3316
void *kernel;
@@ -45,15 +28,10 @@ static inline sockptr_t KERNEL_SOCKPTR(void *p)
4528
{
4629
return (sockptr_t) { .kernel = p, .is_kernel = true };
4730
}
48-
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
4931

50-
static inline int __must_check init_user_sockptr(sockptr_t *sp, void __user *p,
51-
size_t size)
32+
static inline sockptr_t USER_SOCKPTR(void __user *p)
5233
{
53-
if (!access_ok(p, size))
54-
return -EFAULT;
55-
*sp = (sockptr_t) { .user = p };
56-
return 0;
34+
return (sockptr_t) { .user = p };
5735
}
5836

5937
static inline bool sockptr_is_null(sockptr_t sockptr)

net/ipv4/bpfilter/sockopt.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,16 @@ int bpfilter_ip_set_sockopt(struct sock *sk, int optname, sockptr_t optval,
5757
return bpfilter_mbox_request(sk, optname, optval, optlen, true);
5858
}
5959

60-
int bpfilter_ip_get_sockopt(struct sock *sk, int optname,
61-
char __user *user_optval, int __user *optlen)
60+
int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
61+
int __user *optlen)
6262
{
63-
sockptr_t optval;
64-
int err, len;
63+
int len;
6564

6665
if (get_user(len, optlen))
6766
return -EFAULT;
68-
err = init_user_sockptr(&optval, user_optval, len);
69-
if (err)
70-
return err;
71-
return bpfilter_mbox_request(sk, optname, optval, len, false);
67+
68+
return bpfilter_mbox_request(sk, optname, USER_SOCKPTR(optval), len,
69+
false);
7270
}
7371

7472
static int __init bpfilter_sockopt_init(void)

net/socket.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2095,18 +2095,14 @@ static bool sock_use_custom_sol_socket(const struct socket *sock)
20952095
int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
20962096
int optlen)
20972097
{
2098-
sockptr_t optval;
2098+
sockptr_t optval = USER_SOCKPTR(user_optval);
20992099
char *kernel_optval = NULL;
21002100
int err, fput_needed;
21012101
struct socket *sock;
21022102

21032103
if (optlen < 0)
21042104
return -EINVAL;
21052105

2106-
err = init_user_sockptr(&optval, user_optval, optlen);
2107-
if (err)
2108-
return err;
2109-
21102106
sock = sockfd_lookup_light(fd, &err, &fput_needed);
21112107
if (!sock)
21122108
return err;

0 commit comments

Comments
 (0)