summaryrefslogtreecommitdiff
path: root/net/socket.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2025-09-25 23:09:29 +0000
committerJakub Kicinski <kuba@kernel.org>2025-09-29 18:04:37 -0700
commit1fb0e471611dc6a79dee609a7e0037eb1d124400 (patch)
treec9fcdae5a6802a158e9f085e964588267c6e60a5 /net/socket.c
parent2b235765e9d4426cf56d7fd1a331f81a4dbbd85a (diff)
net: remove one stac/clac pair from move_addr_to_user()
Convert the get_user() and __put_user() code to the fast masked_user_access_begin()/unsafe_{get|put}_user() variant. This patch increases the performance of an UDP recvfrom() receiver (netserver) on 120 bytes messages by 7 % on an AMD EPYC 7B12 64-Core Processor platform. Presence of audit_sockaddr() makes difficult to avoid the stac/clac pair in the copy_to_user() call, this is left for a future patch. Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20250925230929.3727873-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/net/socket.c b/net/socket.c
index 682969deaed3..5bc4ee0bb75d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -276,28 +276,41 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *k
static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
void __user *uaddr, int __user *ulen)
{
- int err;
int len;
BUG_ON(klen > sizeof(struct sockaddr_storage));
- err = get_user(len, ulen);
- if (err)
- return err;
+
+ if (can_do_masked_user_access())
+ ulen = masked_user_access_begin(ulen);
+ else if (!user_access_begin(ulen, 4))
+ return -EFAULT;
+
+ unsafe_get_user(len, ulen, efault_end);
+
if (len > klen)
len = klen;
- if (len < 0)
- return -EINVAL;
+ /*
+ * "fromlen shall refer to the value before truncation.."
+ * 1003.1g
+ */
+ if (len >= 0)
+ unsafe_put_user(klen, ulen, efault_end);
+
+ user_access_end();
+
if (len) {
+ if (len < 0)
+ return -EINVAL;
if (audit_sockaddr(klen, kaddr))
return -ENOMEM;
if (copy_to_user(uaddr, kaddr, len))
return -EFAULT;
}
- /*
- * "fromlen shall refer to the value before truncation.."
- * 1003.1g
- */
- return __put_user(klen, ulen);
+ return 0;
+
+efault_end:
+ user_access_end();
+ return -EFAULT;
}
static struct kmem_cache *sock_inode_cachep __ro_after_init;