Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Lock before calling uvm_swap_stats(). Otherwise a race c...



details:   https://anonhg.NetBSD.org/src/rev/fbb4b1f50ec9
branches:  trunk
changeset: 339611:fbb4b1f50ec9
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu Jul 30 09:55:57 2015 +0000

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

diffstat:

 sys/compat/netbsd32/netbsd32_netbsd.c |  17 ++++++++++++-----
 sys/uvm/uvm_swap.c                    |  15 +++++++++++++--
 sys/uvm/uvm_swap.h                    |   5 ++++-
 3 files changed, 29 insertions(+), 8 deletions(-)

diffs (110 lines):

diff -r 7bec83e7e3b0 -r fbb4b1f50ec9 sys/compat/netbsd32/netbsd32_netbsd.c
--- a/sys/compat/netbsd32/netbsd32_netbsd.c     Thu Jul 30 08:41:18 2015 +0000
+++ b/sys/compat/netbsd32/netbsd32_netbsd.c     Thu Jul 30 09:55:57 2015 +0000
@@ -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 @@
 
        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 @@
        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;
diff -r 7bec83e7e3b0 -r fbb4b1f50ec9 sys/uvm/uvm_swap.c
--- a/sys/uvm/uvm_swap.c        Thu Jul 30 08:41:18 2015 +0000
+++ b/sys/uvm/uvm_swap.c        Thu Jul 30 09:55:57 2015 +0000
@@ -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 @@
        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 @@
        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;
diff -r 7bec83e7e3b0 -r fbb4b1f50ec9 sys/uvm/uvm_swap.h
--- a/sys/uvm/uvm_swap.h        Thu Jul 30 08:41:18 2015 +0000
+++ b/sys/uvm/uvm_swap.h        Thu Jul 30 09:55:57 2015 +0000
@@ -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 @@
 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; }



Home | Main Index | Thread Index | Old Index