diff options
author | Christoph Hellwig <hch@lst.de> | 2020-07-23 08:09:08 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-07-25 00:41:54 +0200 |
commit | 6d04fe15f78acdf8e32329e208552e226f7a8ae6 (patch) | |
tree | 90ff9c419f8244651aa420349756cc371d539646 /net/socket.c | |
parent | net: pass a sockptr_t into ->setsockopt (diff) | |
download | linux-6d04fe15f78acdf8e32329e208552e226f7a8ae6.tar.xz linux-6d04fe15f78acdf8e32329e208552e226f7a8ae6.zip |
net: optimize the sockptr_t for unified kernel/user address spaces
For architectures like x86 and arm64 we don't need the separate bit to
indicate that a pointer is a kernel pointer as the address spaces are
unified. That way the sockptr_t can be reduced to a union of two
pointers, which leads to nicer calling conventions.
The only caveat is that we need to check that users don't pass in kernel
address and thus gain access to kernel memory. Thus the USER_SOCKPTR
helper is replaced with a init_user_sockptr function that does this check
and returns an error if it fails.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/net/socket.c b/net/socket.c index e44b8ac47f6f..94ca4547cd7c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2097,7 +2097,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 = USER_SOCKPTR(user_optval); + sockptr_t optval; char *kernel_optval = NULL; int err, fput_needed; struct socket *sock; @@ -2105,6 +2105,10 @@ 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); + if (err) + return err; + sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) return err; |