From: Mark Vitale Date: Fri, 27 May 2016 20:44:17 +0000 (-0400) Subject: SOLARIS: corrupted content of mmap'd files over 4GiB X-Git-Tag: upstream/1.6.18.3^2~3 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=30625e4c7365c03da07cec91c538ff2cd96fe0be;p=packages%2Fo%2Fopenafs.git SOLARIS: corrupted content of mmap'd files over 4GiB Many Solaris programs and utilities (notably mdb and cp) use mmap() in their implementation. When AFS files exceeding 4GiB are mmap'd, the contents of the file will be incorrectly mapped into memory. Starting at 4GiB + 1, the first 4GiB will be repeated for the remainder of the file. If the mmap'd file is written back to storage (AFS or otherwise), the newly created file will also be corrupted. This is due to a bug in the afs_map() routine that supports mmap() of AFS files on Solaris. The segvn_crarg.offset passed to the Solaris virtual memory APIs is incorrectly cast to u_int, causing it to wrap at 4GiB. Although Solaris passes the offset from fop_map() to afs_map() as type offset_t, the destination segvn_crargs.offset is actually type u_offset_t. Existing examples of other Solaris filesystems (e.g. zfs_map() ) cast the offset from offset_t to u_offset_t when assigning to segvn_crargs.offset. If it's good enough for ZFS, it's good enough for AFS. Correctly cast the offset to u_offset_t. Thanks to Robert Milkowski for the report and diagnosis. Reviewed-on: https://gerrit.openafs.org/12292 Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk (cherry picked from commit fa5af899319b69fa9542add78beca388521e3450) Change-Id: I9c00afeb88c089fe34d25015dbbe02c50b7e9437 Reviewed-on: https://gerrit.openafs.org/12350 Reviewed-by: Mark Vitale Tested-by: BuildBot Reviewed-by: Stephan Wiesand --- diff --git a/src/afs/SOLARIS/osi_vnodeops.c b/src/afs/SOLARIS/osi_vnodeops.c index a0c40a6fd..37bfd9e2c 100644 --- a/src/afs/SOLARIS/osi_vnodeops.c +++ b/src/afs/SOLARIS/osi_vnodeops.c @@ -1104,7 +1104,7 @@ afs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addr, size_t len (void)as_unmap(as, *addr, len); /* unmap old address space use */ /* setup the create parameter block for the call */ crargs.vp = AFSTOV(avc); - crargs.offset = (u_int) off; + crargs.offset = (u_offset_t)off; crargs.cred = cred; crargs.type = flags & MAP_TYPE; crargs.prot = prot;