Module Name: src Committed By: maxv Date: Tue Apr 22 19:01:47 UTC 2014
Modified Files: src/sys/kern: kern_core.c Log Message: Fix a read-beyond-end string read. coredump_buildname() copies 'pattern' into 'name', and handles special characters such as "%n". "%n", if present, will be replaced by p->p_comm. error = coredump_buildname(p, name, pattern, MAXPATHLEN); This function handles overflows, and returns an error when 'name' becomes larger than MAXPATHLEN. However, when coredump() calls it, 'name' is used before the error check, with: lastslash = strrchr(name, '/'); 'name' is not guaranteed to be NUL-terminated, because of the *d = *s in coredump_buildname(). This strrchr will read a string which is not NUL- terminated (ie. until finding a '\0' in memory). 'pattern' can't be higher than MAXPATHLEN. A user can fill it in via a PT_DUMPCORE ptrace call, given the input is not longer than MAXPATHLEN. Since the 2-bytes-sized "%n"s will be replaced by p->p_comm (which is user-settable, like a 10-bytes-sized "0123456789"), 'name' can become longer than 'pattern' (and thus longer than MAXPATHLEN). Some 'a's at the end of the buffer will make sure 'name' is not NUL-terminated. pattern: "%n%n%naaaaaaaaaaaaaaaaaaaaaaaaaaaa\0" | | | ||||||||||||||||||||||||||||| -> name: "012345678901234567890123456789aaaaa" [no \0] | | | |||||MAXPATHLEN Fix it by checking 'error' before calling strrchr. To generate a diff of this commit: cvs rdiff -u -r1.22 -r1.23 src/sys/kern/kern_core.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/kern_core.c diff -u src/sys/kern/kern_core.c:1.22 src/sys/kern/kern_core.c:1.23 --- src/sys/kern/kern_core.c:1.22 Fri Jan 3 20:52:47 2014 +++ src/sys/kern/kern_core.c Tue Apr 22 19:01:47 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_core.c,v 1.22 2014/01/03 20:52:47 dsl Exp $ */ +/* $NetBSD: kern_core.c,v 1.23 2014/04/22 19:01:47 maxv Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_core.c,v 1.22 2014/01/03 20:52:47 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_core.c,v 1.23 2014/04/22 19:01:47 maxv Exp $"); #include <sys/param.h> #include <sys/vnode.h> @@ -155,6 +155,12 @@ coredump(struct lwp *l, const char *patt error = coredump_buildname(p, name, pattern, MAXPATHLEN); mutex_exit(&lim->pl_lock); + if (error) { + mutex_exit(p->p_lock); + mutex_exit(proc_lock); + goto done; + } + /* * On a simple filename, see if the filesystem allow us to write * core dumps there.