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)