Module Name: src Committed By: mlelstv Date: Sat Dec 29 10:22:40 UTC 2012
Modified Files: src/sys/kern: uipc_syscalls.c Log Message: If an untraced process sleeps in recvmsg/sendmsg, the syscall does not allocate an iov structure for ktrace. When tracing is then enabled and the process wakes up, it crashes the kernel. Undo the last commit which introduced this error path. Avoid the mentioned kmem_alloc assertion by adding a sanity check analog to similar code in sys_generic.c for I/O on file handles instead of sockets. This also causes the syscall to return EMSGSIZE if the msg_iovlen member of the msg structure is less than or equal to 0, as defined in recvmsg(2)/sendmsg(2). To generate a diff of this commit: cvs rdiff -u -r1.156 -r1.157 src/sys/kern/uipc_syscalls.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.156 src/sys/kern/uipc_syscalls.c:1.157 --- src/sys/kern/uipc_syscalls.c:1.156 Tue Jul 17 14:22:42 2012 +++ src/sys/kern/uipc_syscalls.c Sat Dec 29 10:22:40 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_syscalls.c,v 1.156 2012/07/17 14:22:42 njoly Exp $ */ +/* $NetBSD: uipc_syscalls.c,v 1.157 2012/12/29 10:22:40 mlelstv 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.156 2012/07/17 14:22:42 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.157 2012/12/29 10:22:40 mlelstv Exp $"); #include "opt_pipe.h" @@ -547,6 +547,11 @@ do_sys_sendmsg_so(struct lwp *l, int s, control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL; iovsz = mp->msg_iovlen * sizeof(struct iovec); + if (iovsz <= 0) { + error = EMSGSIZE; + goto bad; + } + if (mp->msg_flags & MSG_IOVUSRSPACE) { if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { if ((unsigned int)mp->msg_iovlen > IOV_MAX) { @@ -604,7 +609,7 @@ do_sys_sendmsg_so(struct lwp *l, int s, } } - if (ktrpoint(KTR_GENIO) && iovsz > 0) { + if (ktrpoint(KTR_GENIO)) { ktriov = kmem_alloc(iovsz, KM_SLEEP); memcpy(ktriov, auio.uio_iov, iovsz); } @@ -634,10 +639,9 @@ do_sys_sendmsg_so(struct lwp *l, int s, *retsize = len - auio.uio_resid; bad: - if (ktrpoint(KTR_GENIO)) { + if (ktriov != NULL) { ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error); - if (ktriov != NULL) - kmem_free(ktriov, iovsz); + kmem_free(ktriov, iovsz); } if (iov != aiov) @@ -911,6 +915,11 @@ do_sys_recvmsg_so(struct lwp *l, int s, iovsz = mp->msg_iovlen * sizeof(struct iovec); + if (iovsz <= 0) { + error = EMSGSIZE; + goto out; + } + if (mp->msg_flags & MSG_IOVUSRSPACE) { if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { if ((unsigned int)mp->msg_iovlen > IOV_MAX) { @@ -948,7 +957,7 @@ do_sys_recvmsg_so(struct lwp *l, int s, } } - if (ktrpoint(KTR_GENIO) && iovsz > 0) { + if (ktrpoint(KTR_GENIO)) { ktriov = kmem_alloc(iovsz, KM_SLEEP); memcpy(ktriov, auio.uio_iov, iovsz); } @@ -964,10 +973,9 @@ do_sys_recvmsg_so(struct lwp *l, int s, /* Some data transferred */ error = 0; - if (ktrpoint(KTR_GENIO)) { + if (ktriov != NULL) { ktrgeniov(s, UIO_READ, ktriov, len, error); - if (ktriov != NULL) - kmem_free(ktriov, iovsz); + kmem_free(ktriov, iovsz); } if (error != 0) {