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)
 {

Reply via email to