Making, drinking tea and reading an opus magnum from Otto Moerbeek:
> On Mon, 2 May 2005, chefren wrote:
> 
> > On OpenBSD 3.6 i386, a mmap() call with offset near/above 4GB on a
> > regular file succeeds but, at least for writes, silently wraps around at
> > the 4GB border. Correctness of reads not tested.
> > 
> > We have taken a look at the kernel sources, but all functions/structures
> > we've found use 64-bit offset variables (off_t, voff_t).
> >  - Setup path: sys_mmap, uvm_mmap, uvm_map
> >  - Fault path: presumed uvn_get, uvm_pagelookup, uvn_io
> > 
> > (of course the vaddr_t-based "offset-within-the-mapping" calculations
> > are 32-bit, but the results get implicitly cast up to voff_t in all the
> > places we've seen).
> > 
> > Which suspects may we have missed?
> > 
> > Is this a "known can of worms", or probably a fixable issue?
> > 
> > Thanks for any help with this,
> 
> This looks like a bug on 32 bit archs, The little program below 
> demonstrates the error on i386 and macppc, but does run fine on sparc64.

and here is a fix too:


Index: uvm_fault.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
retrieving revision 1.33
diff -u -r1.33 uvm_fault.c
--- uvm_fault.c 3 Aug 2004 12:10:48 -0000       1.33
+++ uvm_fault.c 2 May 2005 22:05:55 -0000
@@ -568,7 +568,8 @@
        vm_prot_t enter_prot;
        boolean_t wired, narrow, promote, locked, shadowed;
        int npages, nback, nforw, centeridx, result, lcv, gotpages;
-       vaddr_t startva, objaddr, currva, offset, uoff;
+       vaddr_t startva, currva;
+       voff_t uoff;
        paddr_t pa; 
        struct vm_amap *amap;
        struct uvm_object *uobj;
@@ -780,10 +781,9 @@
 
                /* flush object? */
                if (uobj) {
-                       objaddr =
-                           (startva - ufi.entry->start) + ufi.entry->offset;
+                       uoff = (startva - ufi.entry->start) + ufi.entry->offset;
                        simple_lock(&uobj->vmobjlock);
-                       (void) uobj->pgops->pgo_flush(uobj, objaddr, objaddr + 
+                       (void) uobj->pgops->pgo_flush(uobj, uoff, uoff + 
                                    (nback << PAGE_SHIFT), PGO_DEACTIVATE);
                        simple_unlock(&uobj->vmobjlock);
                }
@@ -1546,7 +1546,7 @@
                                UVM_PAGE_OWN(uobjpage, NULL);
 
                                uvm_lock_pageq();
-                               offset = uobjpage->offset;
+                               uoff = uobjpage->offset;
                                /* remove old page */
                                uvm_pagerealloc(uobjpage, NULL, 0);
 
@@ -1555,7 +1555,7 @@
                                 * control over uobjpage
                                 */
                                /* install new page */
-                               uvm_pagerealloc(pg, uobj, offset);
+                               uvm_pagerealloc(pg, uobj, uoff);
                                uvm_unlock_pageq();
 
                                /*

-- 
    paranoic mickey       (my employers have changed but, the name has remained)

Reply via email to