Module Name: src Committed By: maxv Date: Sat Nov 24 16:41:48 UTC 2018
Modified Files: src/sys/kern: kern_descrip.c Log Message: Fix kernel pointer leaks in the kern.file sysctl, same as kern.file2. To generate a diff of this commit: cvs rdiff -u -r1.240 -r1.241 src/sys/kern/kern_descrip.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_descrip.c diff -u src/sys/kern/kern_descrip.c:1.240 src/sys/kern/kern_descrip.c:1.241 --- src/sys/kern/kern_descrip.c:1.240 Sat Nov 24 16:25:20 2018 +++ src/sys/kern/kern_descrip.c Sat Nov 24 16:41:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_descrip.c,v 1.240 2018/11/24 16:25:20 maxv Exp $ */ +/* $NetBSD: kern_descrip.c,v 1.241 2018/11/24 16:41:48 maxv Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.240 2018/11/24 16:25:20 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.241 2018/11/24 16:41:48 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -118,6 +118,7 @@ static int filedescopen(dev_t, int, int, static int sysctl_kern_file(SYSCTLFN_PROTO); static int sysctl_kern_file2(SYSCTLFN_PROTO); +static void fill_file(struct file *, const struct file *); static void fill_file2(struct kinfo_file *, const file_t *, const fdfile_t *, int, pid_t); @@ -1990,6 +1991,8 @@ sysctl_file_marker_reset(void) static int sysctl_kern_file(SYSCTLFN_ARGS) { + const bool allowaddr = get_expose_address(curproc); + struct filelist flist; int error; size_t buflen; struct file *fp, fbuf; @@ -2016,13 +2019,18 @@ sysctl_kern_file(SYSCTLFN_ARGS) return 0; } sysctl_unlock(); - error = sysctl_copyout(l, &filehead, where, sizeof(filehead)); + if (allowaddr) { + memcpy(&flist, &filehead, sizeof(flist)); + } else { + memset(&flist, 0, sizeof(flist)); + } + error = sysctl_copyout(l, &flist, where, sizeof(flist)); if (error) { sysctl_relock(); return error; } - buflen -= sizeof(filehead); - where += sizeof(filehead); + buflen -= sizeof(flist); + where += sizeof(flist); /* * followed by an array of file structures @@ -2090,7 +2098,7 @@ sysctl_kern_file(SYSCTLFN_ARGS) break; } - memcpy(&fbuf, fp, sizeof(fbuf)); + fill_file(&fbuf, fp); mutex_exit(&fp->f_lock); error = sysctl_copyout(l, &fbuf, where, sizeof(fbuf)); if (error) { @@ -2286,6 +2294,29 @@ sysctl_kern_file2(SYSCTLFN_ARGS) } static void +fill_file(struct file *fp, const struct file *fpsrc) +{ + const bool allowaddr = get_expose_address(curproc); + + memset(fp, 0, sizeof(*fp)); + + fp->f_offset = fpsrc->f_offset; + COND_SET_VALUE(fp->f_cred, fpsrc->f_cred, allowaddr); + COND_SET_VALUE(fp->f_ops, fpsrc->f_ops, allowaddr); + COND_SET_VALUE(fp->f_undata, fpsrc->f_undata, allowaddr); + COND_SET_VALUE(fp->f_list, fpsrc->f_list, allowaddr); + COND_SET_VALUE(fp->f_lock, fpsrc->f_lock, allowaddr); + fp->f_flag = fpsrc->f_flag; + fp->f_marker = fpsrc->f_marker; + fp->f_type = fpsrc->f_type; + fp->f_advice = fpsrc->f_advice; + fp->f_count = fpsrc->f_count; + fp->f_msgcount = fpsrc->f_msgcount; + fp->f_unpcount = fpsrc->f_unpcount; + COND_SET_VALUE(fp->f_unplist, fpsrc->f_unplist, allowaddr); +} + +static void fill_file2(struct kinfo_file *kp, const file_t *fp, const fdfile_t *ff, int i, pid_t pid) {