git: db48fa831982 - main - linux(4): Avoid EISCONN if addr is specified for sendto()

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Sat, 28 May 2022 20:53:19 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=db48fa8319825b4428795fcef9fb5458ac34c1a9

commit db48fa8319825b4428795fcef9fb5458ac34c1a9
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-28 20:42:09 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-05-28 20:42:09 +0000

    linux(4): Avoid EISCONN if addr is specified for sendto()
    
    If the socket is in a connected state, the target address should be
    ignored.
    
    MFC after:              2 weeks
---
 sys/compat/linux/linux_socket.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 1214c2e1fa24..71f958b57298 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -1238,19 +1238,29 @@ linux_sendto(struct thread *td, struct linux_sendto_args *args)
 {
 	struct msghdr msg;
 	struct iovec aiov;
+	struct socket *so;
+	struct file *fp;
+	int error;
 
 	if (linux_check_hdrincl(td, args->s) == 0)
 		/* IP_HDRINCL set, tweak the packet before sending */
 		return (linux_sendto_hdrincl(td, args));
 
-	msg.msg_name = PTRIN(args->to);
-	msg.msg_namelen = args->tolen;
+	bzero(&msg, sizeof(msg));
+	error = getsock_cap(td, args->s, &cap_send_connect_rights,
+	    &fp, NULL, NULL);
+	if (error != 0)
+		return (error);
+	so = fp->f_data;
+	if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0) {
+		msg.msg_name = PTRIN(args->to);
+		msg.msg_namelen = args->tolen;
+	}
 	msg.msg_iov = &aiov;
 	msg.msg_iovlen = 1;
-	msg.msg_control = NULL;
-	msg.msg_flags = 0;
 	aiov.iov_base = PTRIN(args->msg);
 	aiov.iov_len = args->len;
+	fdrop(fp, td);
 	return (linux_sendit(td, args->s, &msg, args->flags, NULL,
 	    UIO_USERSPACE));
 }