Fix some potential integer overflows caused by converting a page number into
authorkettenis <kettenis@openbsd.org>
Thu, 8 May 2014 20:08:50 +0000 (20:08 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 8 May 2014 20:08:50 +0000 (20:08 +0000)
an offset/size/address by shifting by PAGE_SHIFT.  Make uvm_objwrire/unwire
use voff_t instead of off_t.  The former is the right type here even if it is
equivalent to the latter.

Inspired by a somewhat similar changes in Bitrig.

ok deraadt@, guenther@

sys/uvm/uvm_aobj.c
sys/uvm/uvm_fault.c
sys/uvm/uvm_object.c
sys/uvm/uvm_object.h
sys/uvm/uvm_pager.c
sys/uvm/uvm_swap.c
sys/uvm/uvm_vnode.c

index 173d469..153ca4d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_aobj.c,v 1.63 2014/04/30 19:25:14 kettenis Exp $  */
+/*     $OpenBSD: uvm_aobj.c,v 1.64 2014/05/08 20:08:50 kettenis Exp $  */
 /*     $NetBSD: uvm_aobj.c,v 1.39 2001/02/18 21:19:08 chs Exp $        */
 
 /*
@@ -422,7 +422,8 @@ uao_shrink_flush(struct uvm_object *uobj, int startpg, int endpg)
 {
        KASSERT(startpg < endpg);
        KASSERT(uobj->uo_refs == 1);
-       uao_flush(uobj, startpg << PAGE_SHIFT, endpg << PAGE_SHIFT, PGO_FREE);
+       uao_flush(uobj, (voff_t)startpg << PAGE_SHIFT,
+           (voff_t)endpg << PAGE_SHIFT, PGO_FREE);
        uao_dropswap_range(uobj, startpg, endpg);
 }
 
@@ -909,14 +910,14 @@ uao_flush(struct uvm_object *uobj, voff_t start, voff_t stop, int flags)
 
        if (flags & PGO_ALLPAGES) {
                start = 0;
-               stop = aobj->u_pages << PAGE_SHIFT;
+               stop = (voff_t)aobj->u_pages << PAGE_SHIFT;
        } else {
                start = trunc_page(start);
                stop = round_page(stop);
-               if (stop > (aobj->u_pages << PAGE_SHIFT)) {
+               if (stop > ((voff_t)aobj->u_pages << PAGE_SHIFT)) {
                        printf("uao_flush: strange, got an out of range "
                            "flush (fixed)\n");
-                       stop = aobj->u_pages << PAGE_SHIFT;
+                       stop = (voff_t)aobj->u_pages << PAGE_SHIFT;
                }
        }
 
@@ -1414,7 +1415,7 @@ uao_pagein_page(struct uvm_aobj *aobj, int pageidx)
 
        pg = NULL;
        npages = 1;
-       rv = uao_get(&aobj->u_obj, pageidx << PAGE_SHIFT,
+       rv = uao_get(&aobj->u_obj, (voff_t)pageidx << PAGE_SHIFT,
                     &pg, &npages, 0, VM_PROT_READ|VM_PROT_WRITE, 0, 0);
 
        switch (rv) {
@@ -1511,7 +1512,7 @@ uao_dropswap_range(struct uvm_object *uobj, voff_t start, voff_t end)
                                        int slot = elt->slots[j];
 
                                        KASSERT(uvm_pagelookup(&aobj->u_obj,
-                                           (UAO_SWHASH_ELT_PAGEIDX_BASE(elt)
+                                           (voff_t)(UAO_SWHASH_ELT_PAGEIDX_BASE(elt)
                                            + j) << PAGE_SHIFT) == NULL);
 
                                        if (slot > 0) {
index 98e2ad2..d739d4f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_fault.c,v 1.72 2014/04/13 23:14:15 tedu Exp $     */
+/*     $OpenBSD: uvm_fault.c,v 1.73 2014/05/08 20:08:50 kettenis Exp $ */
 /*     $NetBSD: uvm_fault.c,v 1.51 2000/08/06 00:22:53 thorpej Exp $   */
 
 /*
@@ -622,7 +622,7 @@ ReFault:
                /* wide fault (!narrow) */
                nback = min(uvmadvice[ufi.entry->advice].nback,
                            (ufi.orig_rvaddr - ufi.entry->start) >> PAGE_SHIFT);
-               startva = ufi.orig_rvaddr - (nback << PAGE_SHIFT);
+               startva = ufi.orig_rvaddr - ((vsize_t)nback << PAGE_SHIFT);
                nforw = min(uvmadvice[ufi.entry->advice].nforw,
                            ((ufi.entry->end - ufi.orig_rvaddr) >>
                             PAGE_SHIFT) - 1);
@@ -664,13 +664,13 @@ ReFault:
                if (uobj) {
                        uoff = (startva - ufi.entry->start) + ufi.entry->offset;
                        (void) uobj->pgops->pgo_flush(uobj, uoff, uoff + 
-                                   (nback << PAGE_SHIFT), PGO_DEACTIVATE);
+                           ((vsize_t)nback << PAGE_SHIFT), PGO_DEACTIVATE);
                }
 
                /* now forget about the backpages */
                if (amap)
                        anons += nback;
-               startva += (nback << PAGE_SHIFT);
+               startva += ((vsize_t)nback << PAGE_SHIFT);
                npages -= nback;
                centeridx = 0;
        }
index e6844f0..06ca765 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_object.c,v 1.7 2013/05/30 15:17:59 tedu Exp $     */
+/*     $OpenBSD: uvm_object.c,v 1.8 2014/05/08 20:08:50 kettenis Exp $ */
 
 /*
  * Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -64,12 +64,12 @@ uvm_objinit(struct uvm_object *uobj, struct uvm_pagerops *pgops, int refs)
  */
 
 int
-uvm_objwire(struct uvm_object *uobj, off_t start, off_t end,
+uvm_objwire(struct uvm_object *uobj, voff_t start, voff_t end,
     struct pglist *pageq)
 {
-       int i, npages, error;
+       int i, npages, left, error;
        struct vm_page *pgs[FETCH_PAGECOUNT];
-       off_t offset = start, left;
+       voff_t offset = start;
 
        left = (end - start) >> PAGE_SHIFT;
 
@@ -127,7 +127,7 @@ uvm_objwire(struct uvm_object *uobj, off_t start, off_t end,
                uvm_page_unbusy(pgs, npages);
 
                left -= npages;
-               offset += npages << PAGE_SHIFT;
+               offset += (voff_t)npages << PAGE_SHIFT;
        }
 
        return 0;
@@ -146,7 +146,7 @@ error:
  */
 
 void
-uvm_objunwire(struct uvm_object *uobj, off_t start, off_t end)
+uvm_objunwire(struct uvm_object *uobj, voff_t start, voff_t end)
 {
        struct vm_page *pg;
        off_t offset;
index 8308570..4b37af1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_object.h,v 1.19 2013/05/30 15:17:59 tedu Exp $    */
+/*     $OpenBSD: uvm_object.h,v 1.20 2014/05/08 20:08:50 kettenis Exp $        */
 /*     $NetBSD: uvm_object.h,v 1.11 2001/03/09 01:02:12 chs Exp $      */
 
 /*
@@ -97,8 +97,8 @@ RB_PROTOTYPE(uvm_objtree, vm_page, objt, uvm_pagecmp)
         ((struct vnode *)uobj)->v_flag & VTEXT)
 
 void   uvm_objinit(struct uvm_object *, struct uvm_pagerops *, int);
-int    uvm_objwire(struct uvm_object *, off_t, off_t, struct pglist *);
-void   uvm_objunwire(struct uvm_object *, off_t, off_t);
+int    uvm_objwire(struct uvm_object *, voff_t, voff_t, struct pglist *);
+void   uvm_objunwire(struct uvm_object *, voff_t, voff_t);
 
 #endif /* _KERNEL */
 
index 4e4918f..23b7f15 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_pager.c,v 1.65 2014/04/13 23:14:15 tedu Exp $     */
+/*     $OpenBSD: uvm_pager.c,v 1.66 2014/05/08 20:08:50 kettenis Exp $ */
 /*     $NetBSD: uvm_pager.c,v 1.36 2000/11/27 18:26:41 chs Exp $       */
 
 /*
@@ -278,7 +278,7 @@ void
 uvm_pagermapout(vaddr_t kva, int npages)
 {
 
-       pmap_remove(pmap_kernel(), kva, kva + (npages << PAGE_SHIFT));
+       pmap_remove(pmap_kernel(), kva, kva + ((vsize_t)npages << PAGE_SHIFT));
        pmap_update(pmap_kernel());
        uvm_pseg_release(kva);
 
@@ -724,7 +724,8 @@ uvm_aio_aiodone(struct buf *bp)
 
        uobj = NULL;
        for (i = 0; i < npages; i++)
-               pgs[i] = uvm_atopg((vaddr_t)bp->b_data + (i << PAGE_SHIFT));
+               pgs[i] = uvm_atopg((vaddr_t)bp->b_data +
+                   ((vsize_t)i << PAGE_SHIFT));
        uvm_pagermapout((vaddr_t)bp->b_data, npages);
 #ifdef UVM_SWAP_ENCRYPT
        /*
index 6f9b404..9929b57 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_swap.c,v 1.126 2014/04/29 09:55:28 kettenis Exp $ */
+/*     $OpenBSD: uvm_swap.c,v 1.127 2014/05/08 20:08:50 kettenis Exp $ */
 /*     $NetBSD: uvm_swap.c,v 1.40 2000/11/17 11:39:39 mrg Exp $        */
 
 /*
@@ -1780,7 +1780,7 @@ uvm_swap_io(struct vm_page **pps, int startslot, int npages, int flags)
        bp->b_vp = NULL;
        buf_replacevnode(bp, swapdev_vp);
        splx(s);
-       bp->b_bufsize = bp->b_bcount = npages << PAGE_SHIFT;
+       bp->b_bufsize = bp->b_bcount = (long)npages << PAGE_SHIFT;
 
        /*
         * for pageouts we must set "dirtyoff" [NFS client code needs it].
index a67c01e..4105d87 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_vnode.c,v 1.81 2014/04/13 23:14:15 tedu Exp $     */
+/*     $OpenBSD: uvm_vnode.c,v 1.82 2014/05/08 20:08:50 kettenis Exp $ */
 /*     $NetBSD: uvm_vnode.c,v 1.36 2000/11/24 20:34:01 chs Exp $       */
 
 /*
@@ -1159,7 +1159,7 @@ uvn_io(struct uvm_vnode *uvn, vm_page_t *pps, int npages, int flags, int rw)
         */
        /* fill out uio/iov */
        iov.iov_base = (caddr_t) kva;
-       wanted = npages << PAGE_SHIFT;
+       wanted = (size_t)npages << PAGE_SHIFT;
        if (file_offset + wanted > uvn->u_size)
                wanted = uvn->u_size - file_offset;     /* XXX: needed? */
        iov.iov_len = wanted;
@@ -1211,7 +1211,7 @@ uvn_io(struct uvm_vnode *uvn, vm_page_t *pps, int npages, int flags, int rw)
                        result = EIO;           /* XXX: error? */
                } else if (got < PAGE_SIZE * npages && rw == UIO_READ) {
                        memset((void *) (kva + got), 0,
-                              (npages << PAGE_SHIFT) - got);
+                              ((size_t)npages << PAGE_SHIFT) - got);
                }
        }