untrusted comment: verify with openbsd-63-base.pub RWRxzbLwAd76ZRZO7L3jxI8xEVYew/QHUfjM/xlUGo1LaT9JHaX7vRMNhGfE6OgQNJ7Wr0Pl+wLvb/TsiokOilVlv5sbklIXUA0= OpenBSD 6.3 errata 025, 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-63-base.pub -x 025_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.218 diff -u -p -r1.218 uipc_socket.c --- sys/kern/uipc_socket.c 1 Mar 2018 14:11:11 -0000 1.218 +++ sys/kern/uipc_socket.c 21 Nov 2018 18:29:48 -0000 @@ -648,9 +648,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 @@ -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)))