Source-Changes-HG archive

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

[src/trunk]: src/sys/uvm - sys_swapctl: validate the number of swap devices a...



details:   https://anonhg.NetBSD.org/src/rev/c9d0b87660d0
branches:  trunk
changeset: 773540:c9d0b87660d0
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sun Feb 05 16:08:28 2012 +0000

description:
- sys_swapctl: validate the number of swap devices argument for SWAP_STATS.
- uvm_swap_stats: fix a buffer overrun, add some asserts.

Reviewed by mrg@

diffstat:

 sys/uvm/uvm_swap.c |  68 +++++++++++++++++++++++++++++------------------------
 1 files changed, 37 insertions(+), 31 deletions(-)

diffs (162 lines):

diff -r da18e8231fb8 -r c9d0b87660d0 sys/uvm/uvm_swap.c
--- a/sys/uvm/uvm_swap.c        Sun Feb 05 14:27:08 2012 +0000
+++ b/sys/uvm/uvm_swap.c        Sun Feb 05 16:08:28 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_swap.c,v 1.160 2012/01/28 00:00:06 rmind Exp $     */
+/*     $NetBSD: uvm_swap.c,v 1.161 2012/02/05 16:08:28 rmind 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.160 2012/01/28 00:00:06 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.161 2012/02/05 16:08:28 rmind Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_compat_netbsd.h"
@@ -398,8 +398,7 @@
 {
        struct swappri *spp, *nextspp;
 
-       for (spp = LIST_FIRST(&swap_priority); spp != NULL; spp = nextspp) {
-               nextspp = LIST_NEXT(spp, spi_swappri);
+       LIST_FOREACH_SAFE(spp, &swap_priority, spi_swappri, nextspp) {
                if (CIRCLEQ_FIRST(&spp->spi_swapdev) !=
                    (void *)&spp->spi_swapdev)
                        continue;
@@ -454,20 +453,11 @@
        struct swapent *sep;
 #define SWAP_PATH_MAX (PATH_MAX + 1)
        char    *userpath;
-       size_t  len;
+       size_t  len = 0;
        int     error, misc;
        int     priority;
        UVMHIST_FUNC("sys_swapctl"); UVMHIST_CALLED(pdhist);
 
-       misc = SCARG(uap, misc);
-
-       userpath = kmem_alloc(SWAP_PATH_MAX, KM_SLEEP);
-
-       /*
-        * ensure serialized syscall access by grabbing the swap_syscall_lock
-        */
-       rw_enter(&swap_syscall_lock, RW_WRITER);
-
        /*
         * we handle the non-priv NSWAP and STATS request first.
         *
@@ -475,13 +465,20 @@
         * [can also be obtained with uvmexp sysctl]
         */
        if (SCARG(uap, cmd) == SWAP_NSWAP) {
-               UVMHIST_LOG(pdhist, "<- done SWAP_NSWAP=%d", uvmexp.nswapdev,
-                   0, 0, 0);
-               *retval = uvmexp.nswapdev;
-               error = 0;
-               goto out;
+               const int nswapdev = uvmexp.nswapdev;
+               UVMHIST_LOG(pdhist, "<- done SWAP_NSWAP=%d", nswapdev, 0, 0, 0);
+               *retval = nswapdev;
+               return 0;
        }
 
+       misc = SCARG(uap, misc);
+       userpath = kmem_alloc(SWAP_PATH_MAX, KM_SLEEP);
+
+       /*
+        * ensure serialized syscall access by grabbing the swap_syscall_lock
+        */
+       rw_enter(&swap_syscall_lock, RW_WRITER);
+
        /*
         * SWAP_STATS: get stats on current # of configured swap devs
         *
@@ -500,6 +497,12 @@
            ) {
                if ((size_t)misc > (size_t)uvmexp.nswapdev)
                        misc = uvmexp.nswapdev;
+
+               if (misc == 0) {
+                       error = EINVAL;
+                       goto out;
+               }
+               KASSERT(misc > 0);
 #if defined(COMPAT_13)
                if (SCARG(uap, cmd) == SWAP_STATS13)
                        len = sizeof(struct swapent13) * misc;
@@ -561,6 +564,7 @@
                if (SCARG(uap, cmd) == SWAP_ON &&
                    copystr("miniroot", userpath, SWAP_PATH_MAX, &len))
                        panic("swapctl: miniroot copy failed");
+               KASSERT(len > 0);
        } else {
                struct pathbuf *pb;
 
@@ -656,9 +660,10 @@
                swaplist_insert(sdp, spp, priority);
                mutex_exit(&uvm_swap_data_lock);
 
+               KASSERT(len > 0);
                sdp->swd_pathlen = len;
-               sdp->swd_path = kmem_alloc(sdp->swd_pathlen, KM_SLEEP);
-               if (copystr(userpath, sdp->swd_path, sdp->swd_pathlen, 0) != 0)
+               sdp->swd_path = kmem_alloc(len, KM_SLEEP);
+               if (copystr(userpath, sdp->swd_path, len, 0) != 0)
                        panic("swapctl: copystr");
 
                /*
@@ -737,12 +742,13 @@
        int count = 0;
 
        LIST_FOREACH(spp, &swap_priority, spi_swappri) {
-               for (sdp = CIRCLEQ_FIRST(&spp->spi_swapdev);
-                    sdp != (void *)&spp->spi_swapdev && sec-- > 0;
-                    sdp = CIRCLEQ_NEXT(sdp, swd_next)) {
+               CIRCLEQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) {
                        int inuse;
 
-                       /*
+                       if (sec-- <= 0)
+                               break;
+
+                       /*
                         * backwards compatibility for system call.
                         * For NetBSD 1.3 and 5.0, we have to use
                         * the 32 bit dev_t.  For 5.0 and -current
@@ -759,8 +765,9 @@
                                sep->se_nblks = sdp->swd_nblks;
                                sep->se_inuse = inuse;
                                sep->se_priority = sdp->swd_priority;
-                               memcpy(&sep->se_path, sdp->swd_path,
-                                      sizeof sep->se_path);
+                               KASSERT(sdp->swd_pathlen <
+                                   sizeof(sep->se_path));
+                               strcpy(sep->se_path, sdp->swd_path);
                                sep++;
 #if defined(COMPAT_13)
                        } else if (cmd == SWAP_STATS13) {
@@ -784,8 +791,9 @@
                                sep50->se50_nblks = sdp->swd_nblks;
                                sep50->se50_inuse = inuse;
                                sep50->se50_priority = sdp->swd_priority;
-                               memcpy(&sep50->se50_path, sdp->swd_path,
-                                      sizeof sep50->se50_path);
+                               KASSERT(sdp->swd_pathlen <
+                                   sizeof(sep50->se50_path));
+                               strcpy(sep50->se50_path, sdp->swd_path);
                                sep = (struct swapent *)(sep50 + 1);
 #endif
 #if defined(COMPAT_13) || defined(COMPAT_50)
@@ -794,9 +802,7 @@
                        count++;
                }
        }
-
        *retval = count;
-       return;
 }
 
 /*



Home | Main Index | Thread Index | Old Index