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; }