OpenAFS Master Repository branch, openafs-stable-1_6_x, updated. openafs-stable-1_6_11pre1-13-g3995ad4

Gerrit Code Review gerrit@openafs.org
Fri, 13 Feb 2015 05:06:52 -0500


The following commit has been merged in the openafs-stable-1_6_x branch:
commit 3995ad443eca54542651003d4fc5a7e594833bad
Author: Andrew Deason <adeason@sinenomine.net>
Date:   Fri Jan 30 13:29:57 2015 -0600

    afs: Zero uninitialized uio structs
    
    In several places in the code, we allocate a 'struct uio' on the
    stack, or allocate one from non-zeroed memory. In most of these
    places, we initialize the structure by assigning individual fields to
    certain values. However, this leaves any remaining fields assigned to
    random garbage, if there are any additional fields in the struct uio
    that we don't know about.
    
    One such platform is Solaris, which has a field called uio_extflg,
    which exists in Solaris 11, Solaris 10, and possibly further back.
    One of the flags defined for this field in Solaris 11 is UIO_XUIO,
    which indicates that the structure is actually an xuio_t, which is
    larger than a normal uio_t and contains additional fields. So when we
    allocate a uio on the stack without initializing it, it can randomly
    appear to be an xuio_t, depending on what garbage was on the stack at
    the time. An xuio_t is a kind of extensible structure, which is used
    for things like async I/O or DMA, that kind of thing.
    
    One of the places we make use of such a uio_t is in afs_ustrategy,
    which we go through for cache reads and writes on most Unix platforms
    (but not Linux). When handling a read (reading from the disk cache
    into a mapped page), a copy of our stack-allocated uio eventually gets
    passed to VOP_READ. So VOP_READ for the cache filesystem will randomly
    interpret our uio_t as an xuio_t.
    
    In many scenarios, this (amazingly) does not cause any problems, since
    generally, Solaris code will not notice if something is flagged as an
    xuio_t, unless it is specifically written to handle specific xuio_t
    types. ZFS is one of the apparent few filesystem implementations that
    can handle xuio_t's, and will detect and specially handle a
    UIOTYPE_ZEROCOPY xuio_t differently than a regular uio_t.
    
    If ZFS gets a UIOTYPE_ZEROCOPY xuio_t, it appears to ignore the uio
    buffers passed in, and supplies its own buffers from its cache. This
    means that our VOP_READ request will return success, and act like it
    serviced the read just fine. However, the actual buffer that we passed
    in will remain untouched, and so we will return the page to the VFS
    filled with garbage data.
    
    The way this typically manifests is that seemingly random pages will
    contain random data. This seems to happen very rarely, though it may
    not always be obvious what is going on when this occurs.
    
    It is also worth noting that the above description on Solaris only
    happens with Solaris 11 and newer, and only with a ZFS disk cache.
    Anything older than Solaris 11 does not have the xuio_t framework
    (though other uio_extflg values can cause performance degradations),
    and all known non-ZFS local disk filesystems do not interpret special
    xuio_t structures (networked filesystems might have xuio_t handling,
    but they shouldn't be used for a cache).
    
    Bugs similar to this may also exist on other Unix clients, but at
    least this specific scenario should not occur on Linux (since we don't
    use afs_ustrategy), and newer Darwin (since we get a uio allocated for
    us).
    
    To fix this, zero out the entire uio structure before we use it, for
    all instances where we allocate a uio from the stack or from
    non-zeroed memory. Also zero out the accompanying iovec in many
    places, just to be safe. Some of these may not actually need to be
    zeroed (since we do actually initialize the whole thing, or a platform
    doesn't have any additional unknown uio fields), but it seems
    worthwhile to err on the side of caution.
    
    Thanks to Oracle for their assistance on this issue, and thanks to the
    organization experiencing this issue for their patience and
    persistence.
    
    1.6 note: This differs noticeably from the master commit in two
    places:
    
     - src/afs/NBSD/osi_vnodeops.c: On master there is no stack-allocated
       uio struct here.
    
     - src/afs/VNOPS/afs_vnop_write.c and afs_vnop_read.c: On master,
       these code paths are structured quite differently, and are handled
       in afs_osi_uio.c instead.
    
    Reviewed-on: http://gerrit.openafs.org/11705
    Tested-by: BuildBot <buildbot@rampaginggeek.com>
    Reviewed-by: Perry Ruiter <pruiter@sinenomine.net>
    Reviewed-by: Daria Brashear <shadow@your-file-system.com>
    (cherry picked from commit 5ef1de5eddccce0e7b135bb9ed4decaa62fc19ce)
    
    Change-Id: I8dbf60637774dff81ff839ccd78f58b3b1e85c5b
    Reviewed-on: http://gerrit.openafs.org/11713
    Reviewed-by: Perry Ruiter <pruiter@sinenomine.net>
    Tested-by: BuildBot <buildbot@rampaginggeek.com>
    Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
    Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>

 src/afs/AIX/osi_misc.c            |    3 +++
 src/afs/AIX/osi_vnodeops.c        |    9 +++++++++
 src/afs/DARWIN/osi_vnodeops.c     |   20 +++++++++++++-------
 src/afs/FBSD/osi_vnodeops.c       |    6 ++++++
 src/afs/HPUX/osi_vnodeops.c       |   12 ++++++++++++
 src/afs/LINUX/osi_file.c          |    6 ++++++
 src/afs/LINUX/osi_vnodeops.c      |    6 ++++++
 src/afs/LINUX24/osi_file.c        |    6 ++++++
 src/afs/LINUX24/osi_vnodeops.c    |    9 +++++++++
 src/afs/NBSD/osi_vnodeops.c       |    3 +++
 src/afs/OBSD/osi_vnodeops.c       |    3 +++
 src/afs/VNOPS/afs_vnop_read.c     |   16 ++++++++++------
 src/afs/VNOPS/afs_vnop_strategy.c |    3 +++
 src/afs/VNOPS/afs_vnop_write.c    |   14 +++++++++-----
 14 files changed, 98 insertions(+), 18 deletions(-)

-- 
OpenAFS Master Repository