]> Gentwo Git Trees - linux/.git/commitdiff
socket: Unify getsockname and getpeername implementation
authorGabriel Krisman Bertazi <krisman@suse.de>
Tue, 25 Nov 2025 21:17:59 +0000 (16:17 -0500)
committerJens Axboe <axboe@kernel.dk>
Wed, 26 Nov 2025 20:45:23 +0000 (13:45 -0700)
They are already implemented by the same get_name hook in the protocol
level.  Bring the unification one level up to reduce code duplication
in preparation to supporting these as io_uring operations.

Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/socket.h
net/compat.c
net/socket.c

index 3b262487ec06032b885cad017ec828cc6a4142db..937fe331ff1ef903c7f0bdfaa39f06fffcdcfdda 100644 (file)
@@ -454,9 +454,7 @@ extern int __sys_connect(int fd, struct sockaddr __user *uservaddr,
 extern int __sys_listen(int fd, int backlog);
 extern int __sys_listen_socket(struct socket *sock, int backlog);
 extern int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
-                            int __user *usockaddr_len);
-extern int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
-                            int __user *usockaddr_len);
+                            int __user *usockaddr_len, int peer);
 extern int __sys_socketpair(int family, int type, int protocol,
                            int __user *usockvec);
 extern int __sys_shutdown_sock(struct socket *sock, int how);
index 485db8ee9b28fd0138e37188ee063f82af54124b..2c9bd0edac997bc8c6ebd1bc8b92d8437ff32ea4 100644 (file)
@@ -460,10 +460,10 @@ COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args)
                ret = __sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
                break;
        case SYS_GETSOCKNAME:
-               ret = __sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
+               ret = __sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
                break;
        case SYS_GETPEERNAME:
-               ret = __sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2]));
+               ret = __sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]), 1);
                break;
        case SYS_SOCKETPAIR:
                ret = __sys_socketpair(a0, a1, a[2], compat_ptr(a[3]));
index e8892b2187087bafabb357b0c5a496b7ddb7475e..208d92ccf0fb9c439ebfd4df56d8cafa27dd091b 100644 (file)
@@ -2128,12 +2128,11 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
 }
 
 /*
- *     Get the local address ('name') of a socket object. Move the obtained
- *     name to user space.
+ *     Get the remote or local address ('name') of a socket object. Move the
+ *     obtained name to user space.
  */
-
 int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
-                     int __user *usockaddr_len)
+                     int __user *usockaddr_len, int peer)
 {
        struct socket *sock;
        struct sockaddr_storage address;
@@ -2146,11 +2145,14 @@ int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
        if (unlikely(!sock))
                return -ENOTSOCK;
 
-       err = security_socket_getsockname(sock);
+       if (peer)
+               err = security_socket_getpeername(sock);
+       else
+               err = security_socket_getsockname(sock);
        if (err)
                return err;
 
-       err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 0);
+       err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, peer);
        if (err < 0)
                return err;
 
@@ -2161,44 +2163,13 @@ int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
 SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
                int __user *, usockaddr_len)
 {
-       return __sys_getsockname(fd, usockaddr, usockaddr_len);
-}
-
-/*
- *     Get the remote address ('name') of a socket object. Move the obtained
- *     name to user space.
- */
-
-int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
-                     int __user *usockaddr_len)
-{
-       struct socket *sock;
-       struct sockaddr_storage address;
-       CLASS(fd, f)(fd);
-       int err;
-
-       if (fd_empty(f))
-               return -EBADF;
-       sock = sock_from_file(fd_file(f));
-       if (unlikely(!sock))
-               return -ENOTSOCK;
-
-       err = security_socket_getpeername(sock);
-       if (err)
-               return err;
-
-       err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 1);
-       if (err < 0)
-               return err;
-
-       /* "err" is actually length in this case */
-       return move_addr_to_user(&address, err, usockaddr, usockaddr_len);
+       return __sys_getsockname(fd, usockaddr, usockaddr_len, 0);
 }
 
 SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
                int __user *, usockaddr_len)
 {
-       return __sys_getpeername(fd, usockaddr, usockaddr_len);
+       return __sys_getsockname(fd, usockaddr, usockaddr_len, 1);
 }
 
 /*
@@ -3162,12 +3133,12 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
        case SYS_GETSOCKNAME:
                err =
                    __sys_getsockname(a0, (struct sockaddr __user *)a1,
-                                     (int __user *)a[2]);
+                                     (int __user *)a[2], 0);
                break;
        case SYS_GETPEERNAME:
                err =
-                   __sys_getpeername(a0, (struct sockaddr __user *)a1,
-                                     (int __user *)a[2]);
+                   __sys_getsockname(a0, (struct sockaddr __user *)a1,
+                                     (int __user *)a[2], 1);
                break;
        case SYS_SOCKETPAIR:
                err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);