Date: Thu, 7 Sep 2017 04:29:57 +0000 (UTC) From: Maxim Sobolev <sobomax@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r323254 - head/sys/compat/freebsd32 Message-ID: <201709070429.v874Tvom033960@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sobomax Date: Thu Sep 7 04:29:57 2017 New Revision: 323254 URL: https://svnweb.freebsd.org/changeset/base/323254 Log: In the recvmsg32() system call iterate over returned structure(s) and convert any messages of types SCM_BINTIME, SCM_TIMESTAMP, SCM_REALTIME and SCM_MONOTONIC from 64-bit to its 32-bit representation. Otherwise we either run out of user-supplied buffer to copy those out resulting in the MSG_CTRUNC or simply return values that the userland 32-bit code is not going to parse correctly. This fixes at least two regression tests failing to function properly in 32-bit compat mode: tools/regression/sockets/udp_pingpong tools/regression/sockets/unix_cmsg PR: kern/222039 MFC after: 30 days Modified: head/sys/compat/freebsd32/freebsd32.h head/sys/compat/freebsd32/freebsd32_misc.c Modified: head/sys/compat/freebsd32/freebsd32.h ============================================================================== --- head/sys/compat/freebsd32/freebsd32.h Thu Sep 7 03:05:16 2017 (r323253) +++ head/sys/compat/freebsd32/freebsd32.h Thu Sep 7 04:29:57 2017 (r323254) @@ -78,6 +78,15 @@ struct itimerspec32 { TS_CP((src), (dst), it_value); \ } while (0) +struct bintime32 { + uint32_t sec; + uint32_t frac[2]; +}; +#define BT_CP(src, dst, fld) do { \ + CP((src).fld, (dst).fld, sec); \ + *(uint64_t *)&(dst).fld.frac[0] = (src).fld.frac; \ +} while (0) + struct rusage32 { struct timeval32 ru_utime; struct timeval32 ru_stime; Modified: head/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c Thu Sep 7 03:05:16 2017 (r323253) +++ head/sys/compat/freebsd32/freebsd32_misc.c Thu Sep 7 04:29:57 2017 (r323254) @@ -113,6 +113,7 @@ FEATURE(compat_freebsd_32bit, "Compatible with 32-bit CTASSERT(sizeof(struct timeval32) == 8); CTASSERT(sizeof(struct timespec32) == 8); CTASSERT(sizeof(struct itimerval32) == 16); +CTASSERT(sizeof(struct bintime32) == 12); #endif CTASSERT(sizeof(struct statfs32) == 256); #ifdef __amd64__ @@ -1035,12 +1036,67 @@ freebsd32_copyoutmsghdr(struct msghdr *msg, struct msg #define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ FREEBSD32_ALIGN(sizeof(struct cmsghdr))) + +static size_t +freebsd32_cmsg_convert(struct cmsghdr *cm, void *data, socklen_t datalen) +{ + size_t copylen; + union { + struct timespec32 ts; + struct timeval32 tv; + struct bintime32 bt; + } tmp32; + + union { + struct timespec ts; + struct timeval tv; + struct bintime bt; + } *in; + + in = data; + copylen = 0; + switch (cm->cmsg_level) { + case SOL_SOCKET: + switch (cm->cmsg_type) { + case SCM_TIMESTAMP: + TV_CP(*in, tmp32, tv); + copylen = sizeof(tmp32.tv); + break; + + case SCM_BINTIME: + BT_CP(*in, tmp32, bt); + copylen = sizeof(tmp32.bt); + break; + + case SCM_REALTIME: + case SCM_MONOTONIC: + TS_CP(*in, tmp32, ts); + copylen = sizeof(tmp32.ts); + break; + + default: + break; + } + + default: + break; + } + + if (copylen == 0) + return (datalen); + + KASSERT((datalen >= copylen), ("corrupted cmsghdr")); + + bcopy(&tmp32, data, copylen); + return (copylen); +} + static int freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) { struct cmsghdr *cm; void *data; - socklen_t clen, datalen; + socklen_t clen, datalen, datalen_out; int error; caddr_t ctlbuf; int len, maxlen, copylen; @@ -1064,16 +1120,16 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf cm->cmsg_len > clen) { error = EINVAL; break; - } + } data = CMSG_DATA(cm); datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; + datalen_out = freebsd32_cmsg_convert(cm, data, datalen); /* Adjust message length */ cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + - datalen; + datalen_out; - /* Copy cmsghdr */ copylen = sizeof(struct cmsghdr); if (len < copylen) { @@ -1081,7 +1137,7 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf copylen = len; } - error = copyout(cm,ctlbuf,copylen); + error = copyout(cm, ctlbuf, copylen); if (error) goto exit; @@ -1092,13 +1148,13 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf break; /* Copy data */ - copylen = datalen; + copylen = datalen_out; if (len < copylen) { msg->msg_flags |= MSG_CTRUNC; copylen = len; } - error = copyout(data,ctlbuf,copylen); + error = copyout(data, ctlbuf, copylen); if (error) goto exit;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201709070429.v874Tvom033960>