Module Name: src Committed By: riz Date: Mon Feb 18 22:00:49 UTC 2013
Modified Files: src/sys/kern [netbsd-6]: uipc_syscalls.c uipc_usrreq.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #831): sys/kern/uipc_usrreq.c: revision 1.141 sys/kern/uipc_syscalls.c: revision 1.159 Fix some screw cases in cmsg file descriptor passing. - Don't leave garbage in the control buffer if allocating file descriptors fails in unp_externalize. - Scrub the space between CMSG_LEN and CMSG_SPACE to avoid kernel memory disclosure in unp_externalize. - Don't read past cmsg_len when closing file descriptors that couldn't get delivered, in free_rights. ok christos To generate a diff of this commit: cvs rdiff -u -r1.154.2.3 -r1.154.2.4 src/sys/kern/uipc_syscalls.c cvs rdiff -u -r1.136.8.2 -r1.136.8.3 src/sys/kern/uipc_usrreq.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/uipc_syscalls.c diff -u src/sys/kern/uipc_syscalls.c:1.154.2.3 src/sys/kern/uipc_syscalls.c:1.154.2.4 --- src/sys/kern/uipc_syscalls.c:1.154.2.3 Thu Feb 14 22:13:59 2013 +++ src/sys/kern/uipc_syscalls.c Mon Feb 18 22:00:49 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_syscalls.c,v 1.154.2.3 2013/02/14 22:13:59 jdc Exp $ */ +/* $NetBSD: uipc_syscalls.c,v 1.154.2.4 2013/02/18 22:00:49 riz Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.154.2.3 2013/02/14 22:13:59 jdc Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.154.2.4 2013/02/18 22:00:49 riz Exp $"); #include "opt_pipe.h" @@ -742,17 +742,21 @@ sys_recvmsg(struct lwp *l, const struct static void free_rights(struct mbuf *m) { - int nfd; - int i; + struct cmsghdr *cm; int *fdv; + unsigned int nfds, i; - nfd = m->m_len < CMSG_SPACE(sizeof(int)) ? 0 - : (m->m_len - CMSG_SPACE(sizeof(int))) / sizeof(int) + 1; - fdv = (int *) CMSG_DATA(mtod(m,struct cmsghdr *)); - for (i = 0; i < nfd; i++) { + KASSERT(sizeof(*cm) <= m->m_len); + cm = mtod(m, struct cmsghdr *); + + KASSERT(CMSG_ALIGN(sizeof(*cm)) <= cm->cmsg_len); + KASSERT(cm->cmsg_len <= m->m_len); + nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int); + fdv = (int *)CMSG_DATA(cm); + + for (i = 0; i < nfds; i++) if (fd_getfile(fdv[i]) != NULL) (void)fd_close(fdv[i]); - } } void Index: src/sys/kern/uipc_usrreq.c diff -u src/sys/kern/uipc_usrreq.c:1.136.8.2 src/sys/kern/uipc_usrreq.c:1.136.8.3 --- src/sys/kern/uipc_usrreq.c:1.136.8.2 Tue Oct 9 23:45:21 2012 +++ src/sys/kern/uipc_usrreq.c Mon Feb 18 22:00:49 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_usrreq.c,v 1.136.8.2 2012/10/09 23:45:21 riz Exp $ */ +/* $NetBSD: uipc_usrreq.c,v 1.136.8.3 2013/02/18 22:00:49 riz Exp $ */ /*- * Copyright (c) 1998, 2000, 2004, 2008, 2009 The NetBSD Foundation, Inc. @@ -96,7 +96,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.136.8.2 2012/10/09 23:45:21 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.136.8.3 2013/02/18 22:00:49 riz Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -1336,14 +1336,24 @@ unp_externalize(struct mbuf *rights, str } out: if (__predict_false(error != 0)) { - rp = (file_t **)CMSG_DATA(cm); - for (size_t i = 0; i < nfds; i++) { - file_t * const fp = *rp; - *rp++ = 0; - unp_discard_now(fp); - } + file_t **const fpp = (file_t **)CMSG_DATA(cm); + for (size_t i = 0; i < nfds; i++) + unp_discard_now(fpp[i]); + /* + * Truncate the array so that nobody will try to interpret + * what is now garbage in it. + */ + cm->cmsg_len = CMSG_LEN(0); + rights->m_len = CMSG_SPACE(0); } + /* + * Don't disclose kernel memory in the alignment space. + */ + KASSERT(cm->cmsg_len <= rights->m_len); + memset(&mtod(rights, char *)[cm->cmsg_len], 0, rights->m_len - + cm->cmsg_len); + rw_exit(&p->p_cwdi->cwdi_lock); kmem_free(fdp, nfds * sizeof(int)); return error;