05 Mar, 2020

1 commit


24 Feb, 2020

4 commits

  • [ Upstream commit d6fd41905ec577851734623fb905b1763801f5ef ]

    We ran into a confusing problem where an application wasn't checking
    return code on close and so user didn't realize that the application
    ran out of disk space. log a warning message (once) in these
    cases. For example:

    [ 8407.391909] Out of space writing to \\oleg-server\small-share

    Signed-off-by: Steve French
    Reported-by: Oleg Kravtsov
    Reviewed-by: Ronnie Sahlberg
    Reviewed-by: Pavel Shilovsky
    Signed-off-by: Sasha Levin

    Steve French
     
  • [ Upstream commit fe1292686333d1dadaf84091f585ee903b9ddb84 ]

    RHBZ: 1760879

    Fix an oops in match_prepath() by making sure that the prepath string is not
    NULL before we pass it into strcmp().

    This is similar to other checks we make for example in cifs_root_iget()

    Signed-off-by: Ronnie Sahlberg
    Signed-off-by: Steve French
    Signed-off-by: Sasha Levin

    Ronnie Sahlberg
     
  • [ Upstream commit 5739375ee4230980166807d347cc21c305532bbc ]

    Starting from 4a367dc04435, we must set the mount options based on the
    DFS full path rather than the resolved target, that is, cifs_mount()
    will be responsible for resolving the DFS link (cached) as well as
    performing failover to any other targets in the referral.

    Signed-off-by: Paulo Alcantara (SUSE)
    Reported-by: Martijn de Gouw
    Fixes: 4a367dc04435 ("cifs: Add support for failover in cifs_mount()")
    Link: https://lore.kernel.org/linux-cifs/39643d7d-2abb-14d3-ced6-c394fab9a777@prodrive-technologies.com
    Tested-by: Martijn de Gouw
    Signed-off-by: Steve French
    Signed-off-by: Sasha Levin

    Paulo Alcantara (SUSE)
     
  • [ Upstream commit 463a7b457c02250a84faa1d23c52da9e3364aed2 ]

    static analysis with Coverity detected an issue with the following
    commit:

    Author: Paulo Alcantara (SUSE)
    Date: Wed Dec 4 17:38:03 2019 -0300

    cifs: Avoid doing network I/O while holding cache lock

    Addresses-Coverity: ("Uninitialized pointer read")
    Reported-by: Colin Ian King
    Signed-off-by: Paulo Alcantara (SUSE)
    Signed-off-by: Steve French
    Signed-off-by: Sasha Levin

    Steve French
     

20 Feb, 2020

2 commits

  • commit 3f6166aaf19902f2f3124b5426405e292e8974dd upstream.

    Fix display for sec=krb5i which was wrongly interleaved by cruid,
    resulting in string "sec=krb5,cruid=i" instead of
    "sec=krb5i,cruid=".

    Fixes: 96281b9e46eb ("smb3: for kerberos mounts display the credential uid used")
    Signed-off-by: Petr Pavlu
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Petr Pavlu
     
  • commit 85db6b7ae65f33be4bb44f1c28261a3faa126437 upstream.

    RHBZ: 1752437

    Before we add a new EA we should check that this will not overflow
    the maximum buffer we have available to read the EAs back.
    Otherwise we can get into a situation where the EAs are so big that
    we can not read them back to the client and thus we can not list EAs
    anymore or delete them.

    Signed-off-by: Ronnie Sahlberg
    Signed-off-by: Steve French
    CC: Stable
    Signed-off-by: Greg Kroah-Hartman

    Ronnie Sahlberg
     

11 Feb, 2020

1 commit

  • commit b0dd940e582b6a60296b9847a54012a4b080dc72 upstream.

    RHBZ: 1579050

    If we have a soft mount we should fail commands for session-setup
    failures (such as the password having changed/ account being deleted/ ...)
    and return an error back to the application.

    Signed-off-by: Ronnie Sahlberg
    Signed-off-by: Steve French
    CC: Stable
    Signed-off-by: Greg Kroah-Hartman

    Ronnie Sahlberg
     

06 Feb, 2020

1 commit

  • commit c54849ddd832ae0a45cab16bcd1ed2db7da090d7 upstream.

    RHBZ: 1795429

    In recent DFS updates we have a new variable controlling how many times we will
    retry to reconnect the share.
    If DFS is not used, then this variable is initialized to 0 in:

    static inline int
    dfs_cache_get_nr_tgts(const struct dfs_cache_tgt_list *tl)
    {
    return tl ? tl->tl_numtgts : 0;
    }

    This means that in the reconnect loop in smb2_reconnect() we will immediately wrap retries to -1
    and never actually get to pass this conditional:

    if (--retries)
    continue;

    The effect is that we no longer reach the point where we fail the commands with -EHOSTDOWN
    and basically the kernel threads are virtually hung and unkillable.

    Fixes: a3a53b7603798fd8 (cifs: Add support for failover in smb2_reconnect())
    Signed-off-by: Ronnie Sahlberg
    Signed-off-by: Steve French
    Reviewed-by: Paulo Alcantara (SUSE)
    CC: Stable
    Signed-off-by: Greg Kroah-Hartman

    Ronnie Sahlberg
     

01 Feb, 2020

3 commits

  • commit 0a5a98863c9debc02387b3d23c46d187756f5e2b upstream.

    __smb2_handle_cancelled_cmd() is called under a spin lock held in
    cifs_mid_q_entry_release(), so make its memory allocation GFP_ATOMIC.

    This issue was observed when running xfstests generic/028:

    [ 1722.589204] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72064 cmd: 5
    [ 1722.590687] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72065 cmd: 17
    [ 1722.593529] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72066 cmd: 6
    [ 1723.039014] BUG: sleeping function called from invalid context at mm/slab.h:565
    [ 1723.040710] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 30877, name: cifsd
    [ 1723.045098] CPU: 3 PID: 30877 Comm: cifsd Not tainted 5.5.0-rc4+ #313
    [ 1723.046256] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014
    [ 1723.048221] Call Trace:
    [ 1723.048689] dump_stack+0x97/0xe0
    [ 1723.049268] ___might_sleep.cold+0xd1/0xe1
    [ 1723.050069] kmem_cache_alloc_trace+0x204/0x2b0
    [ 1723.051051] __smb2_handle_cancelled_cmd+0x40/0x140 [cifs]
    [ 1723.052137] smb2_handle_cancelled_mid+0xf6/0x120 [cifs]
    [ 1723.053247] cifs_mid_q_entry_release+0x44d/0x630 [cifs]
    [ 1723.054351] ? cifs_reconnect+0x26a/0x1620 [cifs]
    [ 1723.055325] cifs_demultiplex_thread+0xad4/0x14a0 [cifs]
    [ 1723.056458] ? cifs_handle_standard+0x2c0/0x2c0 [cifs]
    [ 1723.057365] ? kvm_sched_clock_read+0x14/0x30
    [ 1723.058197] ? sched_clock+0x5/0x10
    [ 1723.058838] ? sched_clock_cpu+0x18/0x110
    [ 1723.059629] ? lockdep_hardirqs_on+0x17d/0x250
    [ 1723.060456] kthread+0x1ab/0x200
    [ 1723.061149] ? cifs_handle_standard+0x2c0/0x2c0 [cifs]
    [ 1723.062078] ? kthread_create_on_node+0xd0/0xd0
    [ 1723.062897] ret_from_fork+0x3a/0x50

    Signed-off-by: Paulo Alcantara (SUSE)
    Fixes: 9150c3adbf24 ("CIFS: Close open handle after interrupted close")
    Cc: Stable
    Signed-off-by: Steve French
    Reviewed-by: Pavel Shilovsky
    Signed-off-by: Greg Kroah-Hartman

    Paulo Alcantara (SUSE)
     
  • commit 731b82bb1750a906c1e7f070aedf5505995ebea7 upstream.

    Fix two places where we need to adjust down the max response size for
    ioctl when it is used together with compounding.

    Signed-off-by: Ronnie Sahlberg
    Signed-off-by: Steve French
    Reviewed-by: Pavel Shilovsky
    CC: Stable
    Signed-off-by: Greg Kroah-Hartman

    Ronnie Sahlberg
     
  • commit f1f27ad74557e39f67a8331a808b860f89254f2d upstream.

    The task which created the MID may be gone by the time cifsd attempts to
    call the callbacks on MIDs from cifs_reconnect().

    This leads to a use-after-free of the task struct in cifs_wake_up_task:

    ==================================================================
    BUG: KASAN: use-after-free in __lock_acquire+0x31a0/0x3270
    Read of size 8 at addr ffff8880103e3a68 by task cifsd/630

    CPU: 0 PID: 630 Comm: cifsd Not tainted 5.5.0-rc6+ #119
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
    Call Trace:
    dump_stack+0x8e/0xcb
    print_address_description.constprop.5+0x1d3/0x3c0
    ? __lock_acquire+0x31a0/0x3270
    __kasan_report+0x152/0x1aa
    ? __lock_acquire+0x31a0/0x3270
    ? __lock_acquire+0x31a0/0x3270
    kasan_report+0xe/0x20
    __lock_acquire+0x31a0/0x3270
    ? __wake_up_common+0x1dc/0x630
    ? _raw_spin_unlock_irqrestore+0x4c/0x60
    ? mark_held_locks+0xf0/0xf0
    ? _raw_spin_unlock_irqrestore+0x39/0x60
    ? __wake_up_common_lock+0xd5/0x130
    ? __wake_up_common+0x630/0x630
    lock_acquire+0x13f/0x330
    ? try_to_wake_up+0xa3/0x19e0
    _raw_spin_lock_irqsave+0x38/0x50
    ? try_to_wake_up+0xa3/0x19e0
    try_to_wake_up+0xa3/0x19e0
    ? cifs_compound_callback+0x178/0x210
    ? set_cpus_allowed_ptr+0x10/0x10
    cifs_reconnect+0xa1c/0x15d0
    ? generic_ip_connect+0x1860/0x1860
    ? rwlock_bug.part.0+0x90/0x90
    cifs_readv_from_socket+0x479/0x690
    cifs_read_from_socket+0x9d/0xe0
    ? cifs_readv_from_socket+0x690/0x690
    ? mempool_resize+0x690/0x690
    ? rwlock_bug.part.0+0x90/0x90
    ? memset+0x1f/0x40
    ? allocate_buffers+0xff/0x340
    cifs_demultiplex_thread+0x388/0x2a50
    ? cifs_handle_standard+0x610/0x610
    ? rcu_read_lock_held_common+0x120/0x120
    ? mark_lock+0x11b/0xc00
    ? __lock_acquire+0x14ed/0x3270
    ? __kthread_parkme+0x78/0x100
    ? lockdep_hardirqs_on+0x3e8/0x560
    ? lock_downgrade+0x6a0/0x6a0
    ? lockdep_hardirqs_on+0x3e8/0x560
    ? _raw_spin_unlock_irqrestore+0x39/0x60
    ? cifs_handle_standard+0x610/0x610
    kthread+0x2bb/0x3a0
    ? kthread_create_worker_on_cpu+0xc0/0xc0
    ret_from_fork+0x3a/0x50

    Allocated by task 649:
    save_stack+0x19/0x70
    __kasan_kmalloc.constprop.5+0xa6/0xf0
    kmem_cache_alloc+0x107/0x320
    copy_process+0x17bc/0x5370
    _do_fork+0x103/0xbf0
    __x64_sys_clone+0x168/0x1e0
    do_syscall_64+0x9b/0xec0
    entry_SYSCALL_64_after_hwframe+0x49/0xbe

    Freed by task 0:
    save_stack+0x19/0x70
    __kasan_slab_free+0x11d/0x160
    kmem_cache_free+0xb5/0x3d0
    rcu_core+0x52f/0x1230
    __do_softirq+0x24d/0x962

    The buggy address belongs to the object at ffff8880103e32c0
    which belongs to the cache task_struct of size 6016
    The buggy address is located 1960 bytes inside of
    6016-byte region [ffff8880103e32c0, ffff8880103e4a40)
    The buggy address belongs to the page:
    page:ffffea000040f800 refcount:1 mapcount:0 mapping:ffff8880108da5c0
    index:0xffff8880103e4c00 compound_mapcount: 0
    raw: 4000000000010200 ffffea00001f2208 ffffea00001e3408 ffff8880108da5c0
    raw: ffff8880103e4c00 0000000000050003 00000001ffffffff 0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
    ffff8880103e3900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ffff8880103e3980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    >ffff8880103e3a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ^
    ffff8880103e3a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ffff8880103e3b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ==================================================================

    This can be reliably reproduced by adding the below delay to
    cifs_reconnect(), running find(1) on the mount, restarting the samba
    server while find is running, and killing find during the delay:

    spin_unlock(&GlobalMid_Lock);
    mutex_unlock(&server->srv_mutex);

    + msleep(10000);
    +
    cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
    list_for_each_safe(tmp, tmp2, &retry_list) {
    mid_entry = list_entry(tmp, struct mid_q_entry, qhead);

    Fix this by holding a reference to the task struct until the MID is
    freed.

    Signed-off-by: Vincent Whitchurch
    Signed-off-by: Steve French
    CC: Stable
    Reviewed-by: Paulo Alcantara (SUSE)
    Reviewed-by: Pavel Shilovsky
    Signed-off-by: Greg Kroah-Hartman

    Vincent Whitchurch
     

18 Jan, 2020

1 commit

  • commit 7935799e041ae10d380d04ea23868240f082bd11 upstream.

    Clang warns:

    ../fs/cifs/smb2file.c:70:3: warning: misleading indentation; statement
    is not part of the previous 'if' [-Wmisleading-indentation]
    if (oparms->tcon->use_resilient) {
    ^
    ../fs/cifs/smb2file.c:66:2: note: previous statement is here
    if (rc)
    ^
    1 warning generated.

    This warning occurs because there is a space after the tab on this line.
    Remove it so that the indentation is consistent with the Linux kernel
    coding style and clang no longer warns.

    Fixes: 592fafe644bf ("Add resilienthandles mount parm")
    Link: https://github.com/ClangBuiltLinux/linux/issues/826
    Signed-off-by: Nathan Chancellor
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Nathan Chancellor
     

09 Jan, 2020

3 commits

  • commit 69738cfdfa7032f45d9e7462d24490e61cf163dd upstream.

    According to the comment in the code and commit log, some apps
    expect atime >= mtime; but the introduced code results in
    atime==mtime. Fix the comparison to guard against atime
    Cc: stfrench@microsoft.com
    Cc: linux-cifs@vger.kernel.org
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Deepa Dinamani
     
  • commit df3df923b31d298c3d3653a0380202b9f2df9864 upstream.

    We don't care about module aliasing validation in
    cifs_compose_mount_options(..., is_smb3) when finding the root SMB
    session of an DFS namespace in order to refresh DFS referral cache.

    The following issue has been observed when mounting with '-t smb3' and
    then specifying 'vers=2.0':

    ...
    Nov 08 15:27:08 tw kernel: address conversion returned 0 for FS0.WIN.LOCAL
    Nov 08 15:27:08 tw kernel: [kworke] ==> dns_query((null),FS0.WIN.LOCAL,13,(null))
    Nov 08 15:27:08 tw kernel: [kworke] call request_key(,FS0.WIN.LOCAL,)
    Nov 08 15:27:08 tw kernel: [kworke] ==> dns_resolver_cmp(FS0.WIN.LOCAL,FS0.WIN.LOCAL)
    Nov 08 15:27:08 tw kernel: [kworke] Nov 08 15:27:08 tw kernel: CIFS VFS: vers=2.0 not permitted when mounting with smb3
    Nov 08 15:27:08 tw kernel: fs/cifs/dfs_cache.c: CIFS VFS: leaving refresh_tcon (xid = 26) rc = -22
    ...

    Fixes: 5072010ccf05 ("cifs: Fix DFS cache refresher for DFS links")
    Signed-off-by: Paulo Alcantara (SUSE)
    Reviewed-by: Aurelien Aptel
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Paulo Alcantara (SUSE)
     
  • commit 84a1f5b1cc6fd7f6cd99fc5630c36f631b19fa60 upstream.

    We used to skip reconnects on all SMB2_IOCTL commands due to SMB3+
    FSCTL_VALIDATE_NEGOTIATE_INFO - which made sense since we're still
    establishing a SMB session.

    However, when refresh_cache_worker() calls smb2_get_dfs_refer() and
    we're under reconnect, SMB2_ioctl() will not be able to get a proper
    status error (e.g. -EHOSTDOWN in case we failed to reconnect) but an
    -EAGAIN from cifs_send_recv() thus looping forever in
    refresh_cache_worker().

    Fixes: e99c63e4d86d ("SMB3: Fix deadlock in validate negotiate hits reconnect")
    Signed-off-by: Paulo Alcantara (SUSE)
    Suggested-by: Aurelien Aptel
    Reviewed-by: Aurelien Aptel
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Paulo Alcantara (SUSE)
     

05 Jan, 2020

2 commits

  • [ Upstream commit 32546a9586aa4565035bb557e191648e022b29e8 ]

    This patch moves the final part of the cifsFileInfo_put() logic where we
    need a write lock on lock_sem to be processed in a separate thread that
    holds no other locks.
    This is to prevent deadlocks like the one below:

    > there are 6 processes looping to while trying to down_write
    > cinode->lock_sem, 5 of them from _cifsFileInfo_put, and one from
    > cifs_new_fileinfo
    >
    > and there are 5 other processes which are blocked, several of them
    > waiting on either PG_writeback or PG_locked (which are both set), all
    > for the same page of the file
    >
    > 2 inode_lock() (inode->i_rwsem) for the file
    > 1 wait_on_page_writeback() for the page
    > 1 down_read(inode->i_rwsem) for the inode of the directory
    > 1 inode_lock()(inode->i_rwsem) for the inode of the directory
    > 1 __lock_page
    >
    >
    > so processes are blocked waiting on:
    > page flags PG_locked and PG_writeback for one specific page
    > inode->i_rwsem for the directory
    > inode->i_rwsem for the file
    > cifsInodeInflock_sem
    >
    >
    >
    > here are the more gory details (let me know if I need to provide
    > anything more/better):
    >
    > [0 00:48:22.765] [UN] PID: 8863 TASK: ffff8c691547c5c0 CPU: 3
    > COMMAND: "reopen_file"
    > #0 [ffff9965007e3ba8] __schedule at ffffffff9b6e6095
    > #1 [ffff9965007e3c38] schedule at ffffffff9b6e64df
    > #2 [ffff9965007e3c48] rwsem_down_write_slowpath at ffffffff9af283d7
    > #3 [ffff9965007e3cb8] legitimize_path at ffffffff9b0f975d
    > #4 [ffff9965007e3d08] path_openat at ffffffff9b0fe55d
    > #5 [ffff9965007e3dd8] do_filp_open at ffffffff9b100a33
    > #6 [ffff9965007e3ee0] do_sys_open at ffffffff9b0eb2d6
    > #7 [ffff9965007e3f38] do_syscall_64 at ffffffff9ae04315
    > * (I think legitimize_path is bogus)
    >
    > in path_openat
    > } else {
    > const char *s = path_init(nd, flags);
    > while (!(error = link_path_walk(s, nd)) &&
    > (error = do_last(nd, file, op)) > 0) { <<<<
    >
    > do_last:
    > if (open_flag & O_CREAT)
    > inode_lock(dir->d_inode); <<<<
    > else
    > so it's trying to take inode->i_rwsem for the directory
    >
    > DENTRY INODE SUPERBLK TYPE PATH
    > ffff8c68bb8e79c0 ffff8c691158ef20 ffff8c6915bf9000 DIR /mnt/vm1_smb/
    > inode.i_rwsem is ffff8c691158efc0
    >
    > :
    > owner: (UN - 8856 -
    > reopen_file), counter: 0x0000000000000003
    > waitlist: 2
    > 0xffff9965007e3c90 8863 reopen_file UN 0 1:29:22.926
    > RWSEM_WAITING_FOR_WRITE
    > 0xffff996500393e00 9802 ls UN 0 1:17:26.700
    > RWSEM_WAITING_FOR_READ
    >
    >
    > the owner of the inode.i_rwsem of the directory is:
    >
    > [0 00:00:00.109] [UN] PID: 8856 TASK: ffff8c6914275d00 CPU: 3
    > COMMAND: "reopen_file"
    > #0 [ffff99650065b828] __schedule at ffffffff9b6e6095
    > #1 [ffff99650065b8b8] schedule at ffffffff9b6e64df
    > #2 [ffff99650065b8c8] schedule_timeout at ffffffff9b6e9f89
    > #3 [ffff99650065b940] msleep at ffffffff9af573a9
    > #4 [ffff99650065b948] _cifsFileInfo_put.cold.63 at ffffffffc0a42dd6 [cifs]
    > #5 [ffff99650065ba38] cifs_writepage_locked at ffffffffc0a0b8f3 [cifs]
    > #6 [ffff99650065bab0] cifs_launder_page at ffffffffc0a0bb72 [cifs]
    > #7 [ffff99650065bb30] invalidate_inode_pages2_range at ffffffff9b04d4bd
    > #8 [ffff99650065bcb8] cifs_invalidate_mapping at ffffffffc0a11339 [cifs]
    > #9 [ffff99650065bcd0] cifs_revalidate_mapping at ffffffffc0a1139a [cifs]
    > #10 [ffff99650065bcf0] cifs_d_revalidate at ffffffffc0a014f6 [cifs]
    > #11 [ffff99650065bd08] path_openat at ffffffff9b0fe7f7
    > #12 [ffff99650065bdd8] do_filp_open at ffffffff9b100a33
    > #13 [ffff99650065bee0] do_sys_open at ffffffff9b0eb2d6
    > #14 [ffff99650065bf38] do_syscall_64 at ffffffff9ae04315
    >
    > cifs_launder_page is for page 0xffffd1e2c07d2480
    >
    > crash> page.index,mapping,flags 0xffffd1e2c07d2480
    > index = 0x8
    > mapping = 0xffff8c68f3cd0db0
    > flags = 0xfffffc0008095
    >
    > PAGE-FLAG BIT VALUE
    > PG_locked 0 0000001
    > PG_uptodate 2 0000004
    > PG_lru 4 0000010
    > PG_waiters 7 0000080
    > PG_writeback 15 0008000
    >
    >
    > inode is ffff8c68f3cd0c40
    > inode.i_rwsem is ffff8c68f3cd0ce0
    > DENTRY INODE SUPERBLK TYPE PATH
    > ffff8c68a1f1b480 ffff8c68f3cd0c40 ffff8c6915bf9000 REG
    > /mnt/vm1_smb/testfile.8853
    >
    >
    > this process holds the inode->i_rwsem for the parent directory, is
    > laundering a page attached to the inode of the file it's opening, and in
    > _cifsFileInfo_put is trying to down_write the cifsInodeInflock_sem
    > for the file itself.
    >
    >
    > :
    > owner: (UN - 8854 -
    > reopen_file), counter: 0x0000000000000003
    > waitlist: 1
    > 0xffff9965005dfd80 8855 reopen_file UN 0 1:29:22.912
    > RWSEM_WAITING_FOR_WRITE
    >
    > this is the inode.i_rwsem for the file
    >
    > the owner:
    >
    > [0 00:48:22.739] [UN] PID: 8854 TASK: ffff8c6914272e80 CPU: 2
    > COMMAND: "reopen_file"
    > #0 [ffff99650054fb38] __schedule at ffffffff9b6e6095
    > #1 [ffff99650054fbc8] schedule at ffffffff9b6e64df
    > #2 [ffff99650054fbd8] io_schedule at ffffffff9b6e68e2
    > #3 [ffff99650054fbe8] __lock_page at ffffffff9b03c56f
    > #4 [ffff99650054fc80] pagecache_get_page at ffffffff9b03dcdf
    > #5 [ffff99650054fcc0] grab_cache_page_write_begin at ffffffff9b03ef4c
    > #6 [ffff99650054fcd0] cifs_write_begin at ffffffffc0a064ec [cifs]
    > #7 [ffff99650054fd30] generic_perform_write at ffffffff9b03bba4
    > #8 [ffff99650054fda8] __generic_file_write_iter at ffffffff9b04060a
    > #9 [ffff99650054fdf0] cifs_strict_writev.cold.70 at ffffffffc0a4469b [cifs]
    > #10 [ffff99650054fe48] new_sync_write at ffffffff9b0ec1dd
    > #11 [ffff99650054fed0] vfs_write at ffffffff9b0eed35
    > #12 [ffff99650054ff00] ksys_write at ffffffff9b0eefd9
    > #13 [ffff99650054ff38] do_syscall_64 at ffffffff9ae04315
    >
    > the process holds the inode->i_rwsem for the file to which it's writing,
    > and is trying to __lock_page for the same page as in the other processes
    >
    >
    > the other tasks:
    > [0 00:00:00.028] [UN] PID: 8859 TASK: ffff8c6915479740 CPU: 2
    > COMMAND: "reopen_file"
    > #0 [ffff9965007b39d8] __schedule at ffffffff9b6e6095
    > #1 [ffff9965007b3a68] schedule at ffffffff9b6e64df
    > #2 [ffff9965007b3a78] schedule_timeout at ffffffff9b6e9f89
    > #3 [ffff9965007b3af0] msleep at ffffffff9af573a9
    > #4 [ffff9965007b3af8] cifs_new_fileinfo.cold.61 at ffffffffc0a42a07 [cifs]
    > #5 [ffff9965007b3b78] cifs_open at ffffffffc0a0709d [cifs]
    > #6 [ffff9965007b3cd8] do_dentry_open at ffffffff9b0e9b7a
    > #7 [ffff9965007b3d08] path_openat at ffffffff9b0fe34f
    > #8 [ffff9965007b3dd8] do_filp_open at ffffffff9b100a33
    > #9 [ffff9965007b3ee0] do_sys_open at ffffffff9b0eb2d6
    > #10 [ffff9965007b3f38] do_syscall_64 at ffffffff9ae04315
    >
    > this is opening the file, and is trying to down_write cinode->lock_sem
    >
    >
    > [0 00:00:00.041] [UN] PID: 8860 TASK: ffff8c691547ae80 CPU: 2
    > COMMAND: "reopen_file"
    > [0 00:00:00.057] [UN] PID: 8861 TASK: ffff8c6915478000 CPU: 3
    > COMMAND: "reopen_file"
    > [0 00:00:00.059] [UN] PID: 8858 TASK: ffff8c6914271740 CPU: 2
    > COMMAND: "reopen_file"
    > [0 00:00:00.109] [UN] PID: 8862 TASK: ffff8c691547dd00 CPU: 6
    > COMMAND: "reopen_file"
    > #0 [ffff9965007c3c78] __schedule at ffffffff9b6e6095
    > #1 [ffff9965007c3d08] schedule at ffffffff9b6e64df
    > #2 [ffff9965007c3d18] schedule_timeout at ffffffff9b6e9f89
    > #3 [ffff9965007c3d90] msleep at ffffffff9af573a9
    > #4 [ffff9965007c3d98] _cifsFileInfo_put.cold.63 at ffffffffc0a42dd6 [cifs]
    > #5 [ffff9965007c3e88] cifs_close at ffffffffc0a07aaf [cifs]
    > #6 [ffff9965007c3ea0] __fput at ffffffff9b0efa6e
    > #7 [ffff9965007c3ee8] task_work_run at ffffffff9aef1614
    > #8 [ffff9965007c3f20] exit_to_usermode_loop at ffffffff9ae03d6f
    > #9 [ffff9965007c3f38] do_syscall_64 at ffffffff9ae0444c
    >
    > closing the file, and trying to down_write cifsi->lock_sem
    >
    >
    > [0 00:48:22.839] [UN] PID: 8857 TASK: ffff8c6914270000 CPU: 7
    > COMMAND: "reopen_file"
    > #0 [ffff9965006a7cc8] __schedule at ffffffff9b6e6095
    > #1 [ffff9965006a7d58] schedule at ffffffff9b6e64df
    > #2 [ffff9965006a7d68] io_schedule at ffffffff9b6e68e2
    > #3 [ffff9965006a7d78] wait_on_page_bit at ffffffff9b03cac6
    > #4 [ffff9965006a7e10] __filemap_fdatawait_range at ffffffff9b03b028
    > #5 [ffff9965006a7ed8] filemap_write_and_wait at ffffffff9b040165
    > #6 [ffff9965006a7ef0] cifs_flush at ffffffffc0a0c2fa [cifs]
    > #7 [ffff9965006a7f10] filp_close at ffffffff9b0e93f1
    > #8 [ffff9965006a7f30] __x64_sys_close at ffffffff9b0e9a0e
    > #9 [ffff9965006a7f38] do_syscall_64 at ffffffff9ae04315
    >
    > in __filemap_fdatawait_range
    > wait_on_page_writeback(page);
    > for the same page of the file
    >
    >
    >
    > [0 00:48:22.718] [UN] PID: 8855 TASK: ffff8c69142745c0 CPU: 7
    > COMMAND: "reopen_file"
    > #0 [ffff9965005dfc98] __schedule at ffffffff9b6e6095
    > #1 [ffff9965005dfd28] schedule at ffffffff9b6e64df
    > #2 [ffff9965005dfd38] rwsem_down_write_slowpath at ffffffff9af283d7
    > #3 [ffff9965005dfdf0] cifs_strict_writev at ffffffffc0a0c40a [cifs]
    > #4 [ffff9965005dfe48] new_sync_write at ffffffff9b0ec1dd
    > #5 [ffff9965005dfed0] vfs_write at ffffffff9b0eed35
    > #6 [ffff9965005dff00] ksys_write at ffffffff9b0eefd9
    > #7 [ffff9965005dff38] do_syscall_64 at ffffffff9ae04315
    >
    > inode_lock(inode);
    >
    >
    > and one 'ls' later on, to see whether the rest of the mount is available
    > (the test file is in the root, so we get blocked up on the directory
    > ->i_rwsem), so the entire mount is unavailable
    >
    > [0 00:36:26.473] [UN] PID: 9802 TASK: ffff8c691436ae80 CPU: 4
    > COMMAND: "ls"
    > #0 [ffff996500393d28] __schedule at ffffffff9b6e6095
    > #1 [ffff996500393db8] schedule at ffffffff9b6e64df
    > #2 [ffff996500393dc8] rwsem_down_read_slowpath at ffffffff9b6e9421
    > #3 [ffff996500393e78] down_read_killable at ffffffff9b6e95e2
    > #4 [ffff996500393e88] iterate_dir at ffffffff9b103c56
    > #5 [ffff996500393ec8] ksys_getdents64 at ffffffff9b104b0c
    > #6 [ffff996500393f30] __x64_sys_getdents64 at ffffffff9b104bb6
    > #7 [ffff996500393f38] do_syscall_64 at ffffffff9ae04315
    >
    > in iterate_dir:
    > if (shared)
    > res = down_read_killable(&inode->i_rwsem); <<<<
    > else
    > res = down_write_killable(&inode->i_rwsem);
    >

    Reported-by: Frank Sorenson
    Reviewed-by: Pavel Shilovsky
    Signed-off-by: Ronnie Sahlberg
    Signed-off-by: Steve French
    Signed-off-by: Sasha Levin

    Ronnie Sahlberg
     
  • [ Upstream commit 8354d88efdab72b4da32fc4f032448fcef22dab4 ]

    Ensure we grab an active reference in cifs superblock while doing
    failover to prevent automounts (DFS links) of expiring and then
    destroying the superblock pointer.

    This patch fixes the following KASAN report:

    [ 464.301462] BUG: KASAN: use-after-free in
    cifs_reconnect+0x6ab/0x1350
    [ 464.303052] Read of size 8 at addr ffff888155e580d0 by task
    cifsd/1107

    [ 464.304682] CPU: 3 PID: 1107 Comm: cifsd Not tainted 5.4.0-rc4+ #13
    [ 464.305552] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009),
    BIOS rel-1.12.1-0-ga5cab58-rebuilt.opensuse.org 04/01/2014
    [ 464.307146] Call Trace:
    [ 464.307875] dump_stack+0x5b/0x90
    [ 464.308631] print_address_description.constprop.0+0x16/0x200
    [ 464.309478] ? cifs_reconnect+0x6ab/0x1350
    [ 464.310253] ? cifs_reconnect+0x6ab/0x1350
    [ 464.311040] __kasan_report.cold+0x1a/0x41
    [ 464.311811] ? cifs_reconnect+0x6ab/0x1350
    [ 464.312563] kasan_report+0xe/0x20
    [ 464.313300] cifs_reconnect+0x6ab/0x1350
    [ 464.314062] ? extract_hostname.part.0+0x90/0x90
    [ 464.314829] ? printk+0xad/0xde
    [ 464.315525] ? _raw_spin_lock+0x7c/0xd0
    [ 464.316252] ? _raw_read_lock_irq+0x40/0x40
    [ 464.316961] ? ___ratelimit+0xed/0x182
    [ 464.317655] cifs_readv_from_socket+0x289/0x3b0
    [ 464.318386] cifs_read_from_socket+0x98/0xd0
    [ 464.319078] ? cifs_readv_from_socket+0x3b0/0x3b0
    [ 464.319782] ? try_to_wake_up+0x43c/0xa90
    [ 464.320463] ? cifs_small_buf_get+0x4b/0x60
    [ 464.321173] ? allocate_buffers+0x98/0x1a0
    [ 464.321856] cifs_demultiplex_thread+0x218/0x14a0
    [ 464.322558] ? cifs_handle_standard+0x270/0x270
    [ 464.323237] ? __switch_to_asm+0x40/0x70
    [ 464.323893] ? __switch_to_asm+0x34/0x70
    [ 464.324554] ? __switch_to_asm+0x40/0x70
    [ 464.325226] ? __switch_to_asm+0x40/0x70
    [ 464.325863] ? __switch_to_asm+0x34/0x70
    [ 464.326505] ? __switch_to_asm+0x40/0x70
    [ 464.327161] ? __switch_to_asm+0x34/0x70
    [ 464.327784] ? finish_task_switch+0xa1/0x330
    [ 464.328414] ? __switch_to+0x363/0x640
    [ 464.329044] ? __schedule+0x575/0xaf0
    [ 464.329655] ? _raw_spin_lock_irqsave+0x82/0xe0
    [ 464.330301] kthread+0x1a3/0x1f0
    [ 464.330884] ? cifs_handle_standard+0x270/0x270
    [ 464.331624] ? kthread_create_on_node+0xd0/0xd0
    [ 464.332347] ret_from_fork+0x35/0x40

    [ 464.333577] Allocated by task 1110:
    [ 464.334381] save_stack+0x1b/0x80
    [ 464.335123] __kasan_kmalloc.constprop.0+0xc2/0xd0
    [ 464.335848] cifs_smb3_do_mount+0xd4/0xb00
    [ 464.336619] legacy_get_tree+0x6b/0xa0
    [ 464.337235] vfs_get_tree+0x41/0x110
    [ 464.337975] fc_mount+0xa/0x40
    [ 464.338557] vfs_kern_mount.part.0+0x6c/0x80
    [ 464.339227] cifs_dfs_d_automount+0x336/0xd29
    [ 464.339846] follow_managed+0x1b1/0x450
    [ 464.340449] lookup_fast+0x231/0x4a0
    [ 464.341039] path_openat+0x240/0x1fd0
    [ 464.341634] do_filp_open+0x126/0x1c0
    [ 464.342277] do_sys_open+0x1eb/0x2c0
    [ 464.342957] do_syscall_64+0x5e/0x190
    [ 464.343555] entry_SYSCALL_64_after_hwframe+0x44/0xa9

    [ 464.344772] Freed by task 0:
    [ 464.345347] save_stack+0x1b/0x80
    [ 464.345966] __kasan_slab_free+0x12c/0x170
    [ 464.346576] kfree+0xa6/0x270
    [ 464.347211] rcu_core+0x39c/0xc80
    [ 464.347800] __do_softirq+0x10d/0x3da

    [ 464.348919] The buggy address belongs to the object at
    ffff888155e58000
    which belongs to the cache kmalloc-256 of size 256
    [ 464.350222] The buggy address is located 208 bytes inside of
    256-byte region [ffff888155e58000, ffff888155e58100)
    [ 464.351575] The buggy address belongs to the page:
    [ 464.352333] page:ffffea0005579600 refcount:1 mapcount:0
    mapping:ffff88815a803400 index:0x0 compound_mapcount: 0
    [ 464.353583] flags: 0x200000000010200(slab|head)
    [ 464.354209] raw: 0200000000010200 ffffea0005576200 0000000400000004
    ffff88815a803400
    [ 464.355353] raw: 0000000000000000 0000000080100010 00000001ffffffff
    0000000000000000
    [ 464.356458] page dumped because: kasan: bad access detected

    [ 464.367005] Memory state around the buggy address:
    [ 464.367787] ffff888155e57f80: fc fc fc fc fc fc fc fc fc fc fc fc
    fc fc fc fc
    [ 464.368877] ffff888155e58000: fb fb fb fb fb fb fb fb fb fb fb fb
    fb fb fb fb
    [ 464.369967] >ffff888155e58080: fb fb fb fb fb fb fb fb fb fb fb fb
    fb fb fb fb
    [ 464.371111] ^
    [ 464.371775] ffff888155e58100: fc fc fc fc fc fc fc fc fc fc fc fc
    fc fc fc fc
    [ 464.372893] ffff888155e58180: fc fc fc fc fc fc fc fc fc fc fc fc
    fc fc fc fc
    [ 464.373983] ==================================================================

    Signed-off-by: Paulo Alcantara (SUSE)
    Reviewed-by: Aurelien Aptel
    Signed-off-by: Steve French
    Signed-off-by: Sasha Levin

    Paulo Alcantara (SUSE)
     

21 Dec, 2019

11 commits

  • commit 5bb30a4dd60e2a10a4de9932daff23e503f1dd2b upstream.

    Make sure that DFS referrals are sent to newly resolved root targets
    as in a multi tier DFS setup.

    Signed-off-by: Paulo Alcantara (SUSE)
    Link: https://lkml.kernel.org/r/05aa2995-e85e-0ff4-d003-5bb08bd17a22@canonical.com
    Cc: stable@vger.kernel.org
    Tested-by: Matthew Ruffell
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Paulo Alcantara (SUSE)
     
  • commit 86a7964be7afaf3df6b64faaa10a7032d2444e51 upstream.

    There is a race between a system call processing thread
    and the demultiplex thread when mid->resp_buf becomes NULL
    and later is being accessed to get credits. It happens when
    the 1st thread wakes up before a mid callback is called in
    the 2nd one but the mid state has already been set to
    MID_RESPONSE_RECEIVED. This causes NULL pointer dereference
    in mid callback.

    Fix this by saving credits from the response before we
    update the mid state and then use this value in the mid
    callback rather then accessing a response buffer.

    Cc: Stable
    Fixes: ee258d79159afed5 ("CIFS: Move credit processing to mid callbacks for SMB3")
    Tested-by: Frank Sorenson
    Reviewed-by: Ronnie Sahlberg
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Pavel Shilovsky
     
  • commit 7b71843fa7028475b052107664cbe120156a2cfc upstream.

    When an OPEN command is cancelled we mark a mid as
    cancelled and let the demultiplex thread process it
    by closing an open handle. The problem is there is
    a race between a system call thread and the demultiplex
    thread and there may be a situation when the mid has
    been already processed before it is set as cancelled.

    Fix this by processing cancelled requests when mids
    are being destroyed which means that there is only
    one thread referencing a particular mid. Also set
    mids as cancelled unconditionally on their state.

    Cc: Stable
    Tested-by: Frank Sorenson
    Reviewed-by: Ronnie Sahlberg
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Pavel Shilovsky
     
  • commit 9150c3adbf24d77cfba37f03639d4a908ca4ac25 upstream.

    If Close command is interrupted before sending a request
    to the server the client ends up leaking an open file
    handle. This wastes server resources and can potentially
    block applications that try to remove the file or any
    directory containing this file.

    Fix this by putting the close command into a worker queue,
    so another thread retries it later.

    Cc: Stable
    Tested-by: Frank Sorenson
    Reviewed-by: Ronnie Sahlberg
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Pavel Shilovsky
     
  • commit 44805b0e62f15e90d233485420e1847133716bdc upstream.

    Currently the client translates O_SYNC and O_DIRECT flags
    into corresponding SMB create options when openning a file.
    The problem is that on reconnect when the file is being
    re-opened the client doesn't set those flags and it causes
    a server to reject re-open requests because create options
    don't match. The latter means that any subsequent system
    call against that open file fail until a share is re-mounted.

    Fix this by properly setting SMB create options when
    re-openning files after reconnects.

    Fixes: 1013e760d10e6: ("SMB3: Don't ignore O_SYNC/O_DSYNC and O_DIRECT flags")
    Cc: Stable
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Pavel Shilovsky
     
  • commit 14cc639c17ab0b6671526a7459087352507609e4 upstream.

    On reconnect, the transport data structure is NULL and its information is not
    available.

    Signed-off-by: Long Li
    Cc: stable@vger.kernel.org
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Long Li
     
  • commit acd4680e2bef2405a0e1ef2149fbb01cce7e116c upstream.

    The transport should return this error so the upper layer will reconnect.

    Signed-off-by: Long Li
    Cc: stable@vger.kernel.org
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Long Li
     
  • commit 37941ea17d3f8eb2f5ac2f59346fab9e8439271a upstream.

    While it's not friendly to fail user processes that issue more iovs
    than we support, at least we should return the correct error code so the
    user process gets a chance to retry with smaller number of iovs.

    Signed-off-by: Long Li
    Cc: stable@vger.kernel.org
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Long Li
     
  • commit d63cdbae60ac6fbb2864bd3d8df7404f12b7407d upstream.

    Log these activities to help production support.

    Signed-off-by: Long Li
    Cc: stable@vger.kernel.org
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Long Li
     
  • commit c21ce58eab1eda4c66507897207e20c82e62a5ac upstream.

    It's not necessary to queue invalidated memory registration to work queue, as
    all we need to do is to unmap the SG and make it usable again. This can save
    CPU cycles in normal data paths as memory registration errors are rare and
    normally only happens during reconnection.

    Signed-off-by: Long Li
    Cc: stable@vger.kernel.org
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Long Li
     
  • commit 4357d45f50e58672e1d17648d792f27df01dfccd upstream.

    During reconnecting, the transport may have already been destroyed and is in
    the process being reconnected. In this case, return -EAGAIN to not fail and
    to retry this I/O.

    Signed-off-by: Long Li
    Cc: stable@vger.kernel.org
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Long Li
     

13 Dec, 2019

2 commits

  • commit fa9c2362497fbd64788063288dc4e74daf977ebb upstream.

    Even when mounting modern protocol version the server may be
    configured without supporting SMB2.1 leases and the client
    uses SMB2 oplock to optimize IO performance through local caching.

    However there is a problem in oplock break handling that leads
    to missing a break notification on the client who has a file
    opened. It latter causes big latencies to other clients that
    are trying to open the same file.

    The problem reproduces when there are multiple shares from the
    same server mounted on the client. The processing code tries to
    match persistent and volatile file ids from the break notification
    with an open file but it skips all share besides the first one.
    Fix this by looking up in all shares belonging to the server that
    issued the oplock break.

    Cc: Stable
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Pavel Shilovsky
     
  • commit 6f582b273ec23332074d970a7fb25bef835df71f upstream.

    Currently when the client creates a cifsFileInfo structure for
    a newly opened file, it allocates a list of byte-range locks
    with a pointer to the new cfile and attaches this list to the
    inode's lock list. The latter happens before initializing all
    other fields, e.g. cfile->tlink. Thus a partially initialized
    cifsFileInfo structure becomes available to other threads that
    walk through the inode's lock list. One example of such a thread
    may be an oplock break worker thread that tries to push all
    cached byte-range locks. This causes NULL-pointer dereference
    in smb2_push_mandatory_locks() when accessing cfile->tlink:

    [598428.945633] BUG: kernel NULL pointer dereference, address: 0000000000000038
    ...
    [598428.945749] Workqueue: cifsoplockd cifs_oplock_break [cifs]
    [598428.945793] RIP: 0010:smb2_push_mandatory_locks+0xd6/0x5a0 [cifs]
    ...
    [598428.945834] Call Trace:
    [598428.945870] ? cifs_revalidate_mapping+0x45/0x90 [cifs]
    [598428.945901] cifs_oplock_break+0x13d/0x450 [cifs]
    [598428.945909] process_one_work+0x1db/0x380
    [598428.945914] worker_thread+0x4d/0x400
    [598428.945921] kthread+0x104/0x140
    [598428.945925] ? process_one_work+0x380/0x380
    [598428.945931] ? kthread_park+0x80/0x80
    [598428.945937] ret_from_fork+0x35/0x40

    Fix this by reordering initialization steps of the cifsFileInfo
    structure: initialize all the fields first and then add the new
    byte-range lock list to the inode's lock list.

    Cc: Stable
    Signed-off-by: Pavel Shilovsky
    Reviewed-by: Aurelien Aptel
    Signed-off-by: Steve French
    Signed-off-by: Greg Kroah-Hartman

    Pavel Shilovsky
     

07 Nov, 2019

1 commit

  • When the client hits a network reconnect, it re-opens every open
    file with a create context to reconnect a persistent handle. All
    create context types should be 8-bytes aligned but the padding
    was missed for that one. As a result, some servers don't allow
    us to reconnect handles and return an error. The problem occurs
    when the problematic context is not at the end of the create
    request packet. Fix this by adding a proper padding at the end
    of the reconnect persistent handle context.

    Cc: Stable # 4.19.x
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French

    Pavel Shilovsky
     

28 Oct, 2019

1 commit


25 Oct, 2019

3 commits

  • There's a deadlock that is possible and can easily be seen with
    a test where multiple readers open/read/close of the same file
    and a disruption occurs causing reconnect. The deadlock is due
    a reader thread inside cifs_strict_readv calling down_read and
    obtaining lock_sem, and then after reconnect inside
    cifs_reopen_file calling down_read a second time. If in
    between the two down_read calls, a down_write comes from
    another process, deadlock occurs.

    CPU0 CPU1
    ---- ----
    cifs_strict_readv()
    down_read(&cifsi->lock_sem);
    _cifsFileInfo_put
    OR
    cifs_new_fileinfo
    down_write(&cifsi->lock_sem);
    cifs_reopen_file()
    down_read(&cifsi->lock_sem);

    Fix the above by changing all down_write(lock_sem) calls to
    down_write_trylock(lock_sem)/msleep() loop, which in turn
    makes the second down_read call benign since it will never
    block behind the writer while holding lock_sem.

    Signed-off-by: Dave Wysochanski
    Suggested-by: Ronnie Sahlberg
    Reviewed--by: Ronnie Sahlberg
    Reviewed-by: Pavel Shilovsky

    Dave Wysochanski
     
  • Currently the code assumes that if a file info entry belongs
    to lists of open file handles of an inode and a tcon then
    it has non-zero reference. The recent changes broke that
    assumption when putting the last reference of the file info.
    There may be a situation when a file is being deleted but
    nothing prevents another thread to reference it again
    and start using it. This happens because we do not hold
    the inode list lock while checking the number of references
    of the file info structure. Fix this by doing the proper
    locking when doing the check.

    Fixes: 487317c99477d ("cifs: add spinlock for the openFileList to cifsInodeInfo")
    Fixes: cb248819d209d ("cifs: use cifsInodeInfo->open_file_lock while iterating to avoid a panic")
    Cc: Stable
    Reviewed-by: Ronnie Sahlberg
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French

    Pavel Shilovsky
     
  • When the client hits reconnect it iterates over the mid
    pending queue marking entries for retry and moving them
    to a temporary list to issue callbacks later without holding
    GlobalMid_Lock. In the same time there is no guarantee that
    mids can't be removed from the temporary list or even
    freed completely by another thread. It may cause a temporary
    list corruption:

    [ 430.454897] list_del corruption. prev->next should be ffff98d3a8f316c0, but was 2e885cb266355469
    [ 430.464668] ------------[ cut here ]------------
    [ 430.466569] kernel BUG at lib/list_debug.c:51!
    [ 430.468476] invalid opcode: 0000 [#1] SMP PTI
    [ 430.470286] CPU: 0 PID: 13267 Comm: cifsd Kdump: loaded Not tainted 5.4.0-rc3+ #19
    [ 430.473472] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
    [ 430.475872] RIP: 0010:__list_del_entry_valid.cold+0x31/0x55
    ...
    [ 430.510426] Call Trace:
    [ 430.511500] cifs_reconnect+0x25e/0x610 [cifs]
    [ 430.513350] cifs_readv_from_socket+0x220/0x250 [cifs]
    [ 430.515464] cifs_read_from_socket+0x4a/0x70 [cifs]
    [ 430.517452] ? try_to_wake_up+0x212/0x650
    [ 430.519122] ? cifs_small_buf_get+0x16/0x30 [cifs]
    [ 430.521086] ? allocate_buffers+0x66/0x120 [cifs]
    [ 430.523019] cifs_demultiplex_thread+0xdc/0xc30 [cifs]
    [ 430.525116] kthread+0xfb/0x130
    [ 430.526421] ? cifs_handle_standard+0x190/0x190 [cifs]
    [ 430.528514] ? kthread_park+0x90/0x90
    [ 430.530019] ret_from_fork+0x35/0x40

    Fix this by obtaining extra references for mids being retried
    and marking them as MID_DELETED which indicates that such a mid
    has been dequeued from the pending list.

    Also move mid cleanup logic from DeleteMidQEntry to
    _cifs_mid_q_entry_release which is called when the last reference
    to a particular mid is put. This allows to avoid any use-after-free
    of response buffers.

    The patch needs to be backported to stable kernels. A stable tag
    is not mentioned below because the patch doesn't apply cleanly
    to any actively maintained stable kernel.

    Reviewed-by: Ronnie Sahlberg
    Reviewed-and-tested-by: David Wysochanski
    Signed-off-by: Pavel Shilovsky
    Signed-off-by: Steve French

    Pavel Shilovsky
     

21 Oct, 2019

4 commits

  • cifs_setattr_nounix has two paths which miss free operations
    for xid and fullpath.
    Use goto cifs_setattr_exit like other paths to fix them.

    CC: Stable
    Fixes: aa081859b10c ("cifs: flush before set-info if we have writeable handles")
    Signed-off-by: Chuhong Yuan
    Signed-off-by: Steve French
    Reviewed-by: Pavel Shilovsky

    Chuhong Yuan
     
  • According to MS-CIFS specification MID 0xFFFF should not be used by the
    CIFS client, but we actually do. Besides, this has proven to cause races
    leading to oops between SendReceive2/cifs_demultiplex_thread. On SMB1,
    MID is a 2 byte value easy to reach in CurrentMid which may conflict with
    an oplock break notification request coming from server

    Signed-off-by: Roberto Bergantinos Corpas
    Reviewed-by: Ronnie Sahlberg
    Reviewed-by: Aurelien Aptel
    Signed-off-by: Steve French
    CC: Stable

    Roberto Bergantinos Corpas
     
  • It could be confusing why we set granularity to 1 seconds rather
    than 2 seconds (1 second is the max the VFS allows) for these
    mounts to very old servers ...

    Signed-off-by: Steve French

    Steve French
     
  • We only want to avoid blocking in connect when mounting SMB root
    filesystems, otherwise bail out from generic_ip_connect() so cifs.ko
    can perform any reconnect failover appropriately.

    This fixes DFS failover/reconnection tests in upstream buildbot.

    Fixes: 8eecd1c2e5bc ("cifs: Add support for root file systems")
    Signed-off-by: Paulo Alcantara (SUSE)
    Signed-off-by: Steve French

    Paulo Alcantara (SUSE)