untrusted comment: verify with openbsd-64-base.pub RWQq6XmS4eDAcbOws5+4PArtEBik6T7N8BcTk0D/EDxE7HbrMjSEKp35Ah+0yDOfH9lPqS8Ed2cU33jMcBObWVuwwHlccEckGQo= OpenBSD 6.4 errata 006, November 29, 2018: UNIX domain sockets leak kernel memory with MSG_PEEK on SCM_RIGHTS, or can attempt excessive memory allocations leading to crash. Apply by doing: signify -Vep /etc/signify/openbsd-64-base.pub -x 006_uipc.patch.sig \ -m - | (cd /usr/src && patch -p0) 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 Index: sys/kern/uipc_socket.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.227 diff -u -p -r1.227 uipc_socket.c --- sys/kern/uipc_socket.c 21 Aug 2018 12:34:11 -0000 1.227 +++ sys/kern/uipc_socket.c 21 Nov 2018 17:59:15 -0000 @@ -661,9 +661,9 @@ soreceive(struct socket *so, struct mbuf mp = mp0; if (paddr) - *paddr = 0; + *paddr = NULL; if (controlp) - *controlp = 0; + *controlp = NULL; if (flagsp) flags = *flagsp &~ MSG_EOR; else @@ -810,8 +810,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 { @@ -822,9 +827,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); @@ -835,8 +838,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); } @@ -845,7 +847,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.134 diff -u -p -r1.134 uipc_usrreq.c --- sys/kern/uipc_usrreq.c 9 Jul 2018 10:58:21 -0000 1.134 +++ sys/kern/uipc_usrreq.c 21 Nov 2018 17:59:15 -0000 @@ -663,6 +663,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))) @@ -800,6 +807,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)))