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>