diff --git a/include/linux/socket.h b/include/linux/socket.h index 937fe331ff1e..8d580074ddea 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -453,6 +453,8 @@ extern int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen); extern int __sys_listen(int fd, int backlog); extern int __sys_listen_socket(struct socket *sock, int backlog); +extern int do_getsockname(struct socket *sock, int peer, + struct sockaddr __user *usockaddr, int __user *usockaddr_len); extern int __sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len, int peer); extern int __sys_socketpair(int family, int type, int protocol, diff --git a/net/socket.c b/net/socket.c index 208d92ccf0fb..89bac0a17e5a 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2127,6 +2127,25 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, return __sys_connect(fd, uservaddr, addrlen); } +int do_getsockname(struct socket *sock, int peer, + struct sockaddr __user *usockaddr, int __user *usockaddr_len) +{ + struct sockaddr_storage address; + int err; + + 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, peer); + if (err < 0) + return err; + /* "err" is actually length in this case */ + return move_addr_to_user(&address, err, usockaddr, usockaddr_len); +} + /* * Get the remote or local address ('name') of a socket object. Move the * obtained name to user space. @@ -2135,29 +2154,14 @@ int __sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len, int peer) { 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; - - 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, peer); - if (err < 0) - return err; - - /* "err" is actually length in this case */ - return move_addr_to_user(&address, err, usockaddr, usockaddr_len); + return do_getsockname(sock, peer, usockaddr, usockaddr_len); } SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,