]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: remove one stac/clac pair from move_addr_to_user()
authorEric Dumazet <edumazet@google.com>
Thu, 25 Sep 2025 23:09:29 +0000 (23:09 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 30 Sep 2025 01:04:37 +0000 (18:04 -0700)
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>
net/socket.c

index 682969deaed35df05666cc7711e5e29f7a445c07..5bc4ee0bb75d64039a2259ef01ab811b1d20034b 100644 (file)
@@ -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;