And then rebuild and install a new kernel:
KK=`sysctl -n kern.osversion | cut -d# -f1`
cd /usr/src/sys/arch/`machine`/compile/$KK
make obj
make config
make
make install
mp = mp0;
if (paddr)
- *paddr = 0;
+ *paddr = NULL;
if (controlp)
- *controlp = 0;
+ *controlp = NULL;
if (flagsp)
flags = *flagsp &~ MSG_EOR;
else
@@ -799,8 +799,13 @@ dontblock:
}
}
while (m && m->m_type == MT_CONTROL && error == 0) {
+ int skip = 0;
if (flags & MSG_PEEK) {
- if (controlp)
+ if (mtod(m, struct cmsghdr *)->cmsg_type ==
+ SCM_RIGHTS) {
+ /* don't leak internalized SCM_RIGHTS msgs */
+ skip = 1;
+ } else if (controlp)
*controlp = m_copym(m, 0, m->m_len, M_NOWAIT);
m = m->m_next;
} else {
@@ -811,9 +816,7 @@ dontblock:
m = so->so_rcv.sb_mb;
sbsync(&so->so_rcv, nextrecord);
if (controlp) {
- if (pr->pr_domain->dom_externalize &&
- mtod(cm, struct cmsghdr *)->cmsg_type ==
- SCM_RIGHTS) {
+ if (pr->pr_domain->dom_externalize) {
error =
(*pr->pr_domain->dom_externalize)
(cm, controllen, flags);
@@ -824,8 +827,7 @@ dontblock:
* Dispose of any SCM_RIGHTS message that went
* through the read path rather than recv.
*/
- if (pr->pr_domain->dom_dispose &&
- mtod(cm, struct cmsghdr *)->cmsg_type == SCM_RIGHTS)
+ if (pr->pr_domain->dom_dispose)
pr->pr_domain->dom_dispose(cm);
m_free(cm);
}
@@ -834,7 +836,7 @@ dontblock:
nextrecord = so->so_rcv.sb_mb->m_nextpkt;
else
nextrecord = so->so_rcv.sb_mb;
- if (controlp) {
+ if (controlp && !skip) {
orig_resid = 0;
controlp = &(*controlp)->m_next;
}
Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.123
diff -u -p -r1.123 uipc_usrreq.c
--- sys/kern/uipc_usrreq.c 4 Jan 2018 10:45:30 -0000 1.123
+++ sys/kern/uipc_usrreq.c 21 Nov 2018 18:29:48 -0000
@@ -655,6 +655,13 @@ unp_externalize(struct mbuf *rights, soc
struct file *fp;
int nfds, error = 0;
+ /*
+ * This code only works because SCM_RIGHTS is the only supported
+ * control message type on unix sockets. Enforce this here.
+ */
+ if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET)
+ return EINVAL;
+
nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) /
sizeof(struct fdpass);
if (controllen < CMSG_ALIGN(sizeof(struct cmsghdr)))
@@ -788,6 +795,8 @@ unp_internalize(struct mbuf *control, st
* Check for two potential msg_controllen values because
* IETF stuck their nose in a place it does not belong.
*/
+ if (control->m_len < CMSG_LEN(0) || cm->cmsg_len < CMSG_LEN(0))
+ return (EINVAL);
if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
!(cm->cmsg_len == control->m_len ||
control->m_len == CMSG_ALIGN(cm->cmsg_len)))