Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Mar 2017 19:20:39 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r315736 - in head/sys/compat: cloudabi cloudabi32 cloudabi64
Message-ID:  <201703221920.v2MJKdIt067568@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ed
Date: Wed Mar 22 19:20:39 2017
New Revision: 315736
URL: https://svnweb.freebsd.org/changeset/base/315736

Log:
  Make file descriptor passing for CloudABI's recvmsg() work.
  
  Similar to the change for sendmsg(), create a pointer size independent
  implementation of recvmsg() and let cloudabi32 and cloudabi64 call into
  it. In case userspace requests one or more file descriptors, call
  kern_recvit() in such a way that we get the control message headers in
  an mbuf. Iterate over all of the headers and copy the file descriptors
  to userspace.

Modified:
  head/sys/compat/cloudabi/cloudabi_sock.c
  head/sys/compat/cloudabi/cloudabi_util.h
  head/sys/compat/cloudabi32/cloudabi32_sock.c
  head/sys/compat/cloudabi64/cloudabi64_sock.c

Modified: head/sys/compat/cloudabi/cloudabi_sock.c
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_sock.c	Wed Mar 22 19:18:47 2017	(r315735)
+++ head/sys/compat/cloudabi/cloudabi_sock.c	Wed Mar 22 19:20:39 2017	(r315736)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ * Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
 #include <compat/cloudabi/cloudabi_util.h>
 
 /* Converts FreeBSD's struct sockaddr to CloudABI's cloudabi_sockaddr_t. */
-void
+static void
 cloudabi_convert_sockaddr(const struct sockaddr *sa, socklen_t sal,
     cloudabi_sockaddr_t *rsa)
 {
@@ -247,6 +247,81 @@ cloudabi_sys_sock_stat_get(struct thread
 }
 
 int
+cloudabi_sock_recv(struct thread *td, cloudabi_fd_t fd, struct iovec *data,
+    size_t datalen, cloudabi_fd_t *fds, size_t fdslen,
+    cloudabi_msgflags_t flags, size_t *rdatalen, size_t *rfdslen,
+    cloudabi_sockaddr_t *peername, cloudabi_msgflags_t *rflags)
+{
+	struct sockaddr_storage ss;
+	struct msghdr hdr = {
+		.msg_name = &ss,
+		.msg_namelen = sizeof(ss),
+		.msg_iov = data,
+		.msg_iovlen = datalen,
+	};
+	struct mbuf *control;
+	int error;
+
+	/* Convert flags. */
+	if (flags & CLOUDABI_MSG_PEEK)
+		hdr.msg_flags |= MSG_PEEK;
+	if (flags & CLOUDABI_MSG_WAITALL)
+		hdr.msg_flags |= MSG_WAITALL;
+
+	control = NULL;
+	error = kern_recvit(td, fd, &hdr, UIO_SYSSPACE,
+	    fdslen > 0 ? &control : NULL);
+	if (error != 0)
+		return (error);
+
+	/* Convert return values. */
+	*rdatalen = td->td_retval[0];
+	td->td_retval[0] = 0;
+	*rfdslen = 0;
+	cloudabi_convert_sockaddr((struct sockaddr *)&ss,
+	    MIN(hdr.msg_namelen, sizeof(ss)), peername);
+	*rflags = 0;
+	if (hdr.msg_flags & MSG_EOR)
+		*rflags |= CLOUDABI_MSG_EOR;
+	if (hdr.msg_flags & MSG_TRUNC)
+		*rflags |= CLOUDABI_MSG_TRUNC;
+
+	/* Extract file descriptors from SCM_RIGHTS messages. */
+	if (control != NULL) {
+		struct cmsghdr *chdr;
+
+		hdr.msg_control = mtod(control, void *);
+		hdr.msg_controllen = control->m_len;
+		for (chdr = CMSG_FIRSTHDR(&hdr); chdr != NULL;
+		    chdr = CMSG_NXTHDR(&hdr, chdr)) {
+			if (chdr->cmsg_level == SOL_SOCKET &&
+			    chdr->cmsg_type == SCM_RIGHTS) {
+				size_t nfds;
+
+				nfds = (chdr->cmsg_len - CMSG_LEN(0)) /
+				    sizeof(int);
+				if (nfds > fdslen) {
+					/* Unable to store file descriptors. */
+					nfds = fdslen;
+					*rflags |= CLOUDABI_MSG_CTRUNC;
+				}
+				error = copyout(CMSG_DATA(chdr), fds,
+				    nfds * sizeof(int));
+				if (error != 0) {
+					m_free(control);
+					return (error);
+				}
+				fds += nfds;
+				fdslen -= nfds;
+				*rfdslen += nfds;
+			}
+		}
+		m_free(control);
+	}
+	return (0);
+}
+
+int
 cloudabi_sock_send(struct thread *td, cloudabi_fd_t fd, struct iovec *data,
     size_t datalen, const cloudabi_fd_t *fds, size_t fdslen,
     cloudabi_msgflags_t flags, size_t *rdatalen)

Modified: head/sys/compat/cloudabi/cloudabi_util.h
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_util.h	Wed Mar 22 19:18:47 2017	(r315735)
+++ head/sys/compat/cloudabi/cloudabi_util.h	Wed Mar 22 19:20:39 2017	(r315736)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ * Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,10 +44,6 @@ int cloudabi_clock_time_get(struct threa
 /* Converts a FreeBSD errno to a CloudABI errno. */
 cloudabi_errno_t cloudabi_convert_errno(int);
 
-/* Converts FreeBSD's struct sockaddr to CloudABI's cloudabi_sockaddr_t. */
-void cloudabi_convert_sockaddr(const struct sockaddr *, socklen_t,
-    cloudabi_sockaddr_t *);
-
 /* Converts a file descriptor to a CloudABI file descriptor type. */
 cloudabi_filetype_t cloudabi_convert_filetype(const struct file *);
 
@@ -78,6 +74,9 @@ int cloudabi_futex_lock_wrlock(struct th
     cloudabi_timestamp_t);
 
 /* Socket operations. */
+int cloudabi_sock_recv(struct thread *, cloudabi_fd_t, struct iovec *, size_t,
+    cloudabi_fd_t *, size_t, cloudabi_msgflags_t, size_t *, size_t *,
+    cloudabi_sockaddr_t *, cloudabi_msgflags_t *);
 int cloudabi_sock_send(struct thread *, cloudabi_fd_t, struct iovec *, size_t,
     const cloudabi_fd_t *, size_t, cloudabi_msgflags_t, size_t *);
 

Modified: head/sys/compat/cloudabi32/cloudabi32_sock.c
==============================================================================
--- head/sys/compat/cloudabi32/cloudabi32_sock.c	Wed Mar 22 19:18:47 2017	(r315735)
+++ head/sys/compat/cloudabi32/cloudabi32_sock.c	Wed Mar 22 19:20:39 2017	(r315736)
@@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/syscallsubr.h>
 #include <sys/systm.h>
 #include <sys/uio.h>
 
@@ -48,53 +45,43 @@ int
 cloudabi32_sys_sock_recv(struct thread *td,
     struct cloudabi32_sys_sock_recv_args *uap)
 {
-	struct sockaddr_storage ss;
 	cloudabi32_recv_in_t ri;
 	cloudabi32_recv_out_t ro = {};
 	cloudabi32_iovec_t iovobj;
-	struct msghdr msghdr = {};
+	struct iovec *iov;
 	const cloudabi32_iovec_t *user_iov;
-	size_t i;
+	size_t i, rdatalen, rfdslen;
 	int error;
 
 	error = copyin(uap->in, &ri, sizeof(ri));
 	if (error != 0)
 		return (error);
 
-	/* Convert results in cloudabi_recv_in_t to struct msghdr. */
+	/* Convert iovecs to native format. */
 	if (ri.ri_data_len > UIO_MAXIOV)
 		return (EINVAL);
-	msghdr.msg_iovlen = ri.ri_data_len;
-	msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec),
+	iov = malloc(ri.ri_data_len * sizeof(struct iovec),
 	    M_SOCKET, M_WAITOK);
 	user_iov = TO_PTR(ri.ri_data);
-	for (i = 0; i < msghdr.msg_iovlen; i++) {
+	for (i = 0; i < ri.ri_data_len; i++) {
 		error = copyin(&user_iov[i], &iovobj, sizeof(iovobj));
 		if (error != 0) {
-			free(msghdr.msg_iov, M_SOCKET);
+			free(iov, M_SOCKET);
 			return (error);
 		}
-		msghdr.msg_iov[i].iov_base = TO_PTR(iovobj.buf);
-		msghdr.msg_iov[i].iov_len = iovobj.buf_len;
+		iov[i].iov_base = TO_PTR(iovobj.buf);
+		iov[i].iov_len = iovobj.buf_len;
 	}
-	msghdr.msg_name = &ss;
-	msghdr.msg_namelen = sizeof(ss);
-	if (ri.ri_flags & CLOUDABI_MSG_PEEK)
-		msghdr.msg_flags |= MSG_PEEK;
-	if (ri.ri_flags & CLOUDABI_MSG_WAITALL)
-		msghdr.msg_flags |= MSG_WAITALL;
-
-	/* TODO(ed): Add file descriptor passing. */
-	error = kern_recvit(td, uap->sock, &msghdr, UIO_SYSSPACE, NULL);
-	free(msghdr.msg_iov, M_SOCKET);
+
+	error = cloudabi_sock_recv(td, uap->sock, iov, ri.ri_data_len,
+	    TO_PTR(ri.ri_fds), ri.ri_fds_len, ri.ri_flags, &rdatalen,
+	    &rfdslen, &ro.ro_peername, &ro.ro_flags);
+	free(iov, M_SOCKET);
 	if (error != 0)
 		return (error);
 
-	/* Convert results in msghdr to cloudabi_recv_out_t. */
-	ro.ro_datalen = td->td_retval[0];
-	cloudabi_convert_sockaddr((struct sockaddr *)&ss,
-	    MIN(msghdr.msg_namelen, sizeof(ss)), &ro.ro_peername);
-	td->td_retval[0] = 0;
+	ro.ro_datalen = rdatalen;
+	ro.ro_fdslen = rfdslen;
 	return (copyout(&ro, uap->out, sizeof(ro)));
 }
 

Modified: head/sys/compat/cloudabi64/cloudabi64_sock.c
==============================================================================
--- head/sys/compat/cloudabi64/cloudabi64_sock.c	Wed Mar 22 19:18:47 2017	(r315735)
+++ head/sys/compat/cloudabi64/cloudabi64_sock.c	Wed Mar 22 19:20:39 2017	(r315736)
@@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/syscallsubr.h>
 #include <sys/systm.h>
 #include <sys/uio.h>
 
@@ -48,53 +45,43 @@ int
 cloudabi64_sys_sock_recv(struct thread *td,
     struct cloudabi64_sys_sock_recv_args *uap)
 {
-	struct sockaddr_storage ss;
 	cloudabi64_recv_in_t ri;
 	cloudabi64_recv_out_t ro = {};
 	cloudabi64_iovec_t iovobj;
-	struct msghdr msghdr = {};
+	struct iovec *iov;
 	const cloudabi64_iovec_t *user_iov;
-	size_t i;
+	size_t i, rdatalen, rfdslen;
 	int error;
 
 	error = copyin(uap->in, &ri, sizeof(ri));
 	if (error != 0)
 		return (error);
 
-	/* Convert results in cloudabi_recv_in_t to struct msghdr. */
+	/* Convert iovecs to native format. */
 	if (ri.ri_data_len > UIO_MAXIOV)
 		return (EINVAL);
-	msghdr.msg_iovlen = ri.ri_data_len;
-	msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec),
+	iov = malloc(ri.ri_data_len * sizeof(struct iovec),
 	    M_SOCKET, M_WAITOK);
 	user_iov = TO_PTR(ri.ri_data);
-	for (i = 0; i < msghdr.msg_iovlen; i++) {
+	for (i = 0; i < ri.ri_data_len; i++) {
 		error = copyin(&user_iov[i], &iovobj, sizeof(iovobj));
 		if (error != 0) {
-			free(msghdr.msg_iov, M_SOCKET);
+			free(iov, M_SOCKET);
 			return (error);
 		}
-		msghdr.msg_iov[i].iov_base = TO_PTR(iovobj.buf);
-		msghdr.msg_iov[i].iov_len = iovobj.buf_len;
+		iov[i].iov_base = TO_PTR(iovobj.buf);
+		iov[i].iov_len = iovobj.buf_len;
 	}
-	msghdr.msg_name = &ss;
-	msghdr.msg_namelen = sizeof(ss);
-	if (ri.ri_flags & CLOUDABI_MSG_PEEK)
-		msghdr.msg_flags |= MSG_PEEK;
-	if (ri.ri_flags & CLOUDABI_MSG_WAITALL)
-		msghdr.msg_flags |= MSG_WAITALL;
-
-	/* TODO(ed): Add file descriptor passing. */
-	error = kern_recvit(td, uap->sock, &msghdr, UIO_SYSSPACE, NULL);
-	free(msghdr.msg_iov, M_SOCKET);
+
+	error = cloudabi_sock_recv(td, uap->sock, iov, ri.ri_data_len,
+	    TO_PTR(ri.ri_fds), ri.ri_fds_len, ri.ri_flags, &rdatalen,
+	    &rfdslen, &ro.ro_peername, &ro.ro_flags);
+	free(iov, M_SOCKET);
 	if (error != 0)
 		return (error);
 
-	/* Convert results in msghdr to cloudabi_recv_out_t. */
-	ro.ro_datalen = td->td_retval[0];
-	cloudabi_convert_sockaddr((struct sockaddr *)&ss,
-	    MIN(msghdr.msg_namelen, sizeof(ss)), &ro.ro_peername);
-	td->td_retval[0] = 0;
+	ro.ro_datalen = rdatalen;
+	ro.ro_fdslen = rfdslen;
 	return (copyout(&ro, uap->out, sizeof(ro)));
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703221920.v2MJKdIt067568>