Date: Sun, 3 Aug 2014 02:37:34 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r269455 - stable/10/sys/compat/freebsd32 Message-ID: <201408030237.s732bYAr031709@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Sun Aug 3 02:37:33 2014 New Revision: 269455 URL: http://svnweb.freebsd.org/changeset/base/269455 Log: MFC 264164: Convert while copying in control messages. Obtained from: Juniper Networks, Inc. Modified: stable/10/sys/compat/freebsd32/freebsd32_misc.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- stable/10/sys/compat/freebsd32/freebsd32_misc.c Sun Aug 3 02:24:52 2014 (r269454) +++ stable/10/sys/compat/freebsd32/freebsd32_misc.c Sun Aug 3 02:37:33 2014 (r269455) @@ -1133,47 +1133,91 @@ freebsd32_recvmsg(td, uap) return (error); } - +/* + * Copy-in the array of control messages constructed using alignment + * and padding suitable for a 32-bit environment and construct an + * mbuf using alignment and padding suitable for a 64-bit kernel. + * The alignment and padding are defined indirectly by CMSG_DATA(), + * CMSG_SPACE() and CMSG_LEN(). + */ static int -freebsd32_convert_msg_in(struct mbuf **controlp) +freebsd32_copyin_control(struct mbuf **mp, caddr_t buf, u_int buflen) { - struct mbuf *control = *controlp; - struct cmsghdr *cm = mtod(control, struct cmsghdr *); - void *data; - socklen_t clen = control->m_len, datalen; + struct mbuf *m; + void *md; + u_int idx, len, msglen; int error; - error = 0; - *controlp = NULL; + buflen = FREEBSD32_ALIGN(buflen); - while (cm != NULL) { - if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) { - error = EINVAL; - break; - } + if (buflen > MCLBYTES) + return (EINVAL); - data = FREEBSD32_CMSG_DATA(cm); - datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; + /* + * Iterate over the buffer and get the length of each message + * in there. This has 32-bit alignment and padding. Use it to + * determine the length of these messages when using 64-bit + * alignment and padding. + */ + idx = 0; + len = 0; + while (idx < buflen) { + error = copyin(buf + idx, &msglen, sizeof(msglen)); + if (error) + return (error); + if (msglen < sizeof(struct cmsghdr)) + return (EINVAL); + msglen = FREEBSD32_ALIGN(msglen); + if (idx + msglen > buflen) + return (EINVAL); + idx += msglen; + msglen += CMSG_ALIGN(sizeof(struct cmsghdr)) - + FREEBSD32_ALIGN(sizeof(struct cmsghdr)); + len += CMSG_ALIGN(msglen); + } - *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type, - cm->cmsg_level); - controlp = &(*controlp)->m_next; - - if (FREEBSD32_CMSG_SPACE(datalen) < clen) { - clen -= FREEBSD32_CMSG_SPACE(datalen); - cm = (struct cmsghdr *) - ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen)); - } else { - clen = 0; - cm = NULL; + if (len > MCLBYTES) + return (EINVAL); + + m = m_get(M_WAITOK, MT_CONTROL); + if (len > MLEN) + MCLGET(m, M_WAITOK); + m->m_len = len; + + md = mtod(m, void *); + while (buflen > 0) { + error = copyin(buf, md, sizeof(struct cmsghdr)); + if (error) + break; + msglen = *(u_int *)md; + msglen = FREEBSD32_ALIGN(msglen); + + /* Modify the message length to account for alignment. */ + *(u_int *)md = msglen + CMSG_ALIGN(sizeof(struct cmsghdr)) - + FREEBSD32_ALIGN(sizeof(struct cmsghdr)); + + md = (char *)md + CMSG_ALIGN(sizeof(struct cmsghdr)); + buf += FREEBSD32_ALIGN(sizeof(struct cmsghdr)); + buflen -= FREEBSD32_ALIGN(sizeof(struct cmsghdr)); + + msglen -= FREEBSD32_ALIGN(sizeof(struct cmsghdr)); + if (msglen > 0) { + error = copyin(buf, md, msglen); + if (error) + break; + md = (char *)md + CMSG_ALIGN(msglen); + buf += msglen; + buflen -= msglen; } } - m_freem(control); + if (error) + m_free(m); + else + *mp = m; return (error); } - int freebsd32_sendmsg(struct thread *td, struct freebsd32_sendmsg_args *uap) @@ -1211,14 +1255,13 @@ freebsd32_sendmsg(struct thread *td, goto out; } - error = sockargs(&control, msg.msg_control, - msg.msg_controllen, MT_CONTROL); - if (error) - goto out; - - error = freebsd32_convert_msg_in(&control); + error = freebsd32_copyin_control(&control, msg.msg_control, + msg.msg_controllen); if (error) goto out; + + msg.msg_control = NULL; + msg.msg_controllen = 0; } error = kern_sendit(td, uap->s, &msg, uap->flags, control,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408030237.s732bYAr031709>