From owner-svn-src-all@freebsd.org Thu Nov 22 09:41:59 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 365AD1142ABD; Thu, 22 Nov 2018 09:41:59 +0000 (UTC) (envelope-from tijl@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id BF55F6E506; Thu, 22 Nov 2018 09:41:58 +0000 (UTC) (envelope-from tijl@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id BA2B8627E; Thu, 22 Nov 2018 09:41:54 +0000 (UTC) (envelope-from tijl@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id wAM9fsGs065990; Thu, 22 Nov 2018 09:41:54 GMT (envelope-from tijl@FreeBSD.org) Received: (from tijl@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id wAM9fs72065989; Thu, 22 Nov 2018 09:41:54 GMT (envelope-from tijl@FreeBSD.org) Message-Id: <201811220941.wAM9fs72065989@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: tijl set sender to tijl@FreeBSD.org using -f From: Tijl Coosemans Date: Thu, 22 Nov 2018 09:41:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r340756 - stable/11/sys/compat/linux X-SVN-Group: stable-11 X-SVN-Commit-Author: tijl X-SVN-Commit-Paths: stable/11/sys/compat/linux X-SVN-Commit-Revision: 340756 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: BF55F6E506 X-Spamd-Result: default: False [1.51 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_SPAM_LONG(0.41)[0.407,0]; NEURAL_SPAM_MEDIUM(0.52)[0.517,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_SPAM_SHORT(0.59)[0.589,0] X-Rspamd-Server: mx1.freebsd.org X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Nov 2018 09:41:59 -0000 Author: tijl Date: Thu Nov 22 09:41:54 2018 New Revision: 340756 URL: https://svnweb.freebsd.org/changeset/base/340756 Log: MFC r340631: Do proper copyin of control message data in the Linux sendmsg syscall. Instead of calling m_append with a user address, allocate an mbuf cluster and copy data into it using copyin. For the SCM_CREDS case, instead of zeroing a stack variable and appending that to the mbuf, zero part of the mbuf cluster directly. One mbuf cluster is also the size limit used by the FreeBSD sendmsg syscall (uipc_syscalls.c:sockargs()). PR: 217901 Reviewed by: kib Modified: stable/11/sys/compat/linux/linux_socket.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/compat/linux/linux_socket.c ============================================================================== --- stable/11/sys/compat/linux/linux_socket.c Thu Nov 22 09:41:45 2018 (r340755) +++ stable/11/sys/compat/linux/linux_socket.c Thu Nov 22 09:41:54 2018 (r340756) @@ -1088,7 +1088,6 @@ linux_sendmsg_common(struct thread *td, l_int s, struc l_uint flags) { struct cmsghdr *cmsg; - struct cmsgcred cmcred; struct mbuf *control; struct msghdr msg; struct l_cmsghdr linux_cmsg; @@ -1099,6 +1098,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struc struct sockaddr *sa; sa_family_t sa_family; void *data; + l_size_t len; int error; error = copyin(msghdr, &linux_msg, sizeof(linux_msg)); @@ -1129,7 +1129,6 @@ linux_sendmsg_common(struct thread *td, l_int s, struc return (error); control = NULL; - cmsg = NULL; if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) { error = kern_getsockname(td, s, &sa, &datalen); @@ -1139,8 +1138,10 @@ linux_sendmsg_common(struct thread *td, l_int s, struc free(sa, M_SONAME); error = ENOBUFS; - cmsg = malloc(CMSG_HDRSZ, M_LINUX, M_WAITOK|M_ZERO); control = m_get(M_WAITOK, MT_CONTROL); + MCLGET(control, M_WAITOK); + data = mtod(control, void *); + datalen = 0; do { error = copyin(ptr_cmsg, &linux_cmsg, @@ -1152,10 +1153,14 @@ linux_sendmsg_common(struct thread *td, l_int s, struc if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr)) goto bad; + if (datalen + CMSG_HDRSZ > MCLBYTES) + goto bad; + /* * Now we support only SCM_RIGHTS and SCM_CRED, * so return EINVAL in any other cmsg_type */ + cmsg = data; cmsg->cmsg_type = linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type); cmsg->cmsg_level = @@ -1173,35 +1178,34 @@ linux_sendmsg_common(struct thread *td, l_int s, struc if (sa_family != AF_UNIX) continue; - data = LINUX_CMSG_DATA(ptr_cmsg); - datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ; + if (cmsg->cmsg_type == SCM_CREDS) { + len = sizeof(struct cmsgcred); + if (datalen + CMSG_SPACE(len) > MCLBYTES) + goto bad; - switch (cmsg->cmsg_type) - { - case SCM_RIGHTS: - break; - - case SCM_CREDS: - data = &cmcred; - datalen = sizeof(cmcred); - /* * The lower levels will fill in the structure */ - bzero(data, datalen); - break; + memset(CMSG_DATA(data), 0, len); + } else { + len = linux_cmsg.cmsg_len - L_CMSG_HDRSZ; + if (datalen + CMSG_SPACE(len) < datalen || + datalen + CMSG_SPACE(len) > MCLBYTES) + goto bad; + + error = copyin(LINUX_CMSG_DATA(ptr_cmsg), + CMSG_DATA(data), len); + if (error != 0) + goto bad; } - cmsg->cmsg_len = CMSG_LEN(datalen); - - error = ENOBUFS; - if (!m_append(control, CMSG_HDRSZ, (c_caddr_t)cmsg)) - goto bad; - if (!m_append(control, datalen, (c_caddr_t)data)) - goto bad; + cmsg->cmsg_len = CMSG_LEN(len); + data = (char *)data + CMSG_SPACE(len); + datalen += CMSG_SPACE(len); } while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg))); - if (m_length(control, NULL) == 0) { + control->m_len = datalen; + if (datalen == 0) { m_freem(control); control = NULL; } @@ -1215,8 +1219,6 @@ linux_sendmsg_common(struct thread *td, l_int s, struc bad: m_freem(control); free(iov, M_IOV); - if (cmsg) - free(cmsg, M_LINUX); return (error); }