• Harshula Jayasuriya's avatar
    nfsd: nfsd_open: when dentry_open returns an error do not propagate as struct file · 4834ca94
    Harshula Jayasuriya authored
    commit e4daf1ff upstream.
    
    The following call chain:
    ------------------------------------------------------------
    nfs4_get_vfs_file
    - nfsd_open
      - dentry_open
        - do_dentry_open
          - __get_file_write_access
            - get_write_access
              - return atomic_inc_unless_negative(&inode->i_writecount) ? 0 : -ETXTBSY;
    ------------------------------------------------------------
    
    can result in the following state:
    ------------------------------------------------------------
    struct nfs4_file {
    ...
      fi_fds = {0xffff880c1fa65c80, 0xffffffffffffffe6, 0x0},
      fi_access = {{
          counter = 0x1
        }, {
          counter = 0x0
        }},
    ...
    ------------------------------------------------------------
    
    1) First time around, in nfs4_get_vfs_file() fp->fi_fds[O_WRONLY] is
    NULL, hence nfsd_open() is called where we get status set to an error
    and fp->fi_fds[O_WRONLY] to -ETXTBSY. Thus we do not reach
    nfs4_file_get_access() and fi_access[O_WRONLY] is not incremented.
    
    2) Second time around, in nfs4_get_vfs_file() fp->fi_fds[O_WRONLY] is
    NOT NULL (-ETXTBSY), so nfsd_open() is NOT called, but
    nfs4_file_get_access() IS called and fi_access[O_WRONLY] is incremented.
    Thus we leave a landmine in the form of the nfs4_file data structure in
    an incorrect state.
    
    3) Eventually, when __nfs4_file_put_access() is called it finds
    fi_access[O_WRONLY] being non-zero, it decrements it and calls
    nfs4_file_put_fd() which tries to fput -ETXTBSY.
    ------------------------------------------------------------
    ...
         [exception RIP: fput+0x9]
         RIP: ffffffff81177fa9  RSP: ffff88062e365c90  RFLAGS: 00010282
         RAX: ffff880c2b3d99cc  RBX: ffff880c2b3d9978  RCX: 0000000000000002
         RDX: dead000000100101  RSI: 0000000000000001  RDI: ffffffffffffffe6
         RBP: ffff88062e365c90   R8: ffff88041fe797d8   R9: ffff88062e365d58
         R10: 0000000000000008  R11: 0000000000000000  R12: 0000000000000001
         R13: 0000000000000007  R14: 0000000000000000  R15: 0000000000000000
         ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0018
      #9 [ffff88062e365c98] __nfs4_file_put_access at ffffffffa0562334 [nfsd]
     #10 [ffff88062e365cc8] nfs4_file_put_access at ffffffffa05623ab [nfsd]
     #11 [ffff88062e365ce8] free_generic_stateid at ffffffffa056634d [nfsd]
     #12 [ffff88062e365d18] release_open_stateid at ffffffffa0566e4b [nfsd]
     #13 [ffff88062e365d38] nfsd4_close at ffffffffa0567401 [nfsd]
     #14 [ffff88062e365d88] nfsd4_proc_compound at ffffffffa0557f28 [nfsd]
     #15 [ffff88062e365dd8] nfsd_dispatch at ffffffffa054543e [nfsd]
     #16 [ffff88062e365e18] svc_process_common at ffffffffa04ba5a4 [sunrpc]
     #17 [ffff88062e365e98] svc_process at ffffffffa04babe0 [sunrpc]
     #18 [ffff88062e365eb8] nfsd at ffffffffa0545b62 [nfsd]
     #19 [ffff88062e365ee8] kthread at ffffffff81090886
     #20 [ffff88062e365f48] kernel_thread at ffffffff8100c14a
    ------------------------------------------------------------
    Signed-off-by: default avatarHarshula Jayasuriya <harshula@redhat.com>
    Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
    [xr: Backported to 3.4: adjust context]
    Signed-off-by: default avatarRui Xiang <rui.xiang@huawei.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    4834ca94
vfs.c 55.1 KB