summaryrefslogtreecommitdiff
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c81
1 files changed, 28 insertions, 53 deletions
diff --git a/net/socket.c b/net/socket.c
index e1bf93508f05..42fc3028e891 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1863,7 +1863,7 @@ int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address,
addrlen);
if (!err)
err = READ_ONCE(sock->ops)->bind(sock,
- (struct sockaddr *)address,
+ (struct sockaddr_unsized *)address,
addrlen);
return err;
}
@@ -2077,8 +2077,8 @@ int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
if (err)
goto out;
- err = READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)address,
- addrlen, sock->file->f_flags | file_flags);
+ err = READ_ONCE(sock->ops)->connect(sock, (struct sockaddr_unsized *)address,
+ addrlen, sock->file->f_flags | file_flags);
out:
return err;
}
@@ -2105,78 +2105,53 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
return __sys_connect(fd, uservaddr, addrlen);
}
-/*
- * Get the 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 do_getsockname(struct socket *sock, int peer,
+ 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_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;
-
/* "err" is actually length in this case */
return move_addr_to_user(&address, err, usockaddr, usockaddr_len);
}
-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.
+ * Get the remote or local 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)
+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;
+ return do_getsockname(sock, peer, usockaddr, usockaddr_len);
+}
- 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);
+SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
+ int __user *, 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);
}
/*
@@ -3140,12 +3115,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]);
@@ -3561,13 +3536,13 @@ static long compat_sock_ioctl(struct file *file, unsigned int cmd,
* Returns 0 or an error.
*/
-int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
+int kernel_bind(struct socket *sock, struct sockaddr_unsized *addr, int addrlen)
{
struct sockaddr_storage address;
memcpy(&address, addr, addrlen);
- return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address,
+ return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr_unsized *)&address,
addrlen);
}
EXPORT_SYMBOL(kernel_bind);
@@ -3640,14 +3615,14 @@ EXPORT_SYMBOL(kernel_accept);
* Returns 0 or an error code.
*/
-int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
+int kernel_connect(struct socket *sock, struct sockaddr_unsized *addr, int addrlen,
int flags)
{
struct sockaddr_storage address;
memcpy(&address, addr, addrlen);
- return READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)&address,
+ return READ_ONCE(sock->ops)->connect(sock, (struct sockaddr_unsized *)&address,
addrlen, flags);
}
EXPORT_SYMBOL(kernel_connect);