Module Name:    src
Committed By:   maxv
Date:           Thu Jul 30 09:55:57 UTC 2015

Modified Files:
        src/sys/compat/netbsd32: netbsd32_netbsd.c
        src/sys/uvm: uvm_swap.c uvm_swap.h

Log Message:
Lock before calling uvm_swap_stats(). Otherwise a race condition could
corrupt memory.


To generate a diff of this commit:
cvs rdiff -u -r1.196 -r1.197 src/sys/compat/netbsd32/netbsd32_netbsd.c
cvs rdiff -u -r1.172 -r1.173 src/sys/uvm/uvm_swap.c
cvs rdiff -u -r1.20 -r1.21 src/sys/uvm/uvm_swap.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/compat/netbsd32/netbsd32_netbsd.c
diff -u src/sys/compat/netbsd32/netbsd32_netbsd.c:1.196 src/sys/compat/netbsd32/netbsd32_netbsd.c:1.197
--- src/sys/compat/netbsd32/netbsd32_netbsd.c:1.196	Sun Jun 21 12:54:33 2015
+++ src/sys/compat/netbsd32/netbsd32_netbsd.c	Thu Jul 30 09:55:57 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_netbsd.c,v 1.196 2015/06/21 12:54:33 martin Exp $	*/
+/*	$NetBSD: netbsd32_netbsd.c,v 1.197 2015/07/30 09:55:57 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001, 2008 Matthew R. Green
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.196 2015/06/21 12:54:33 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.197 2015/07/30 09:55:57 maxv Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ddb.h"
@@ -1747,11 +1747,16 @@ netbsd32_swapctl_stats(struct lwp *l, st
 
 	if (count < 0)
 		return EINVAL;
-	if (count == 0 || uvmexp.nswapdev == 0)
-		return 0;
-	/* Make sure userland cannot exhaust kernel memory */
+
+	swapsys_lock(RW_WRITER);
+
 	if ((size_t)count > (size_t)uvmexp.nswapdev)
 		count = uvmexp.nswapdev;
+	if (count == 0) {
+		/* No swap device */
+		swapsys_unlock();
+		return 0;
+	}
 
 	ksep_len = sizeof(*ksep) * count;
 	ksep = kmem_alloc(ksep_len, KM_SLEEP);
@@ -1760,6 +1765,8 @@ netbsd32_swapctl_stats(struct lwp *l, st
 	uvm_swap_stats(SWAP_STATS, ksep, count, retval);
 	count = *retval;
 
+	swapsys_unlock();
+
 	for (i = 0; i < count; i++) {
 		se32.se_dev = ksep[i].se_dev;
 		se32.se_flags = ksep[i].se_flags;

Index: src/sys/uvm/uvm_swap.c
diff -u src/sys/uvm/uvm_swap.c:1.172 src/sys/uvm/uvm_swap.c:1.173
--- src/sys/uvm/uvm_swap.c:1.172	Fri Jul 25 08:10:40 2014
+++ src/sys/uvm/uvm_swap.c	Thu Jul 30 09:55:57 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_swap.c,v 1.172 2014/07/25 08:10:40 dholland Exp $	*/
+/*	$NetBSD: uvm_swap.c,v 1.173 2015/07/30 09:55:57 maxv Exp $	*/
 
 /*
  * Copyright (c) 1995, 1996, 1997, 2009 Matthew R. Green
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.172 2014/07/25 08:10:40 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.173 2015/07/30 09:55:57 maxv Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_compat_netbsd.h"
@@ -430,6 +430,15 @@ swapdrum_getsdp(int pgno)
 	return NULL;
 }
 
+void swapsys_lock(krw_t op)
+{
+	rw_enter(&swap_syscall_lock, op);
+}
+
+void swapsys_unlock(void)
+{
+	rw_exit(&swap_syscall_lock);
+}
 
 /*
  * sys_swapctl: main entry point for swapctl(2) system call
@@ -741,6 +750,8 @@ uvm_swap_stats(int cmd, struct swapent *
 	struct swapdev *sdp;
 	int count = 0;
 
+	KASSERT(rw_lock_held(&swap_syscall_lock));
+
 	LIST_FOREACH(spp, &swap_priority, spi_swappri) {
 		TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) {
 			int inuse;

Index: src/sys/uvm/uvm_swap.h
diff -u src/sys/uvm/uvm_swap.h:1.20 src/sys/uvm/uvm_swap.h:1.21
--- src/sys/uvm/uvm_swap.h:1.20	Mon Feb  3 13:20:21 2014
+++ src/sys/uvm/uvm_swap.h	Thu Jul 30 09:55:57 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_swap.h,v 1.20 2014/02/03 13:20:21 manu Exp $	*/
+/*	$NetBSD: uvm_swap.h,v 1.21 2015/07/30 09:55:57 maxv Exp $	*/
 
 /*
  * Copyright (c) 1997 Matthew R. Green
@@ -48,7 +48,10 @@ int	uvm_swap_alloc(int *, bool);
 void	uvm_swap_free(int, int);
 void	uvm_swap_markbad(int, int);
 bool	uvm_swapisfull(void);
+void	swapsys_lock(krw_t);
+void	swapsys_unlock(void);
 void	uvm_swap_stats(int, struct swapent *, int, register_t *);
+
 #else /* defined(VMSWAP) */
 #define	uvm_swapisfull()	true
 #define uvm_swap_stats(c, sep, count, retval) { *retval = 0; }

Reply via email to