From: Greg Kroah-Hartman Date: Wed, 29 Aug 2018 16:54:26 +0000 (-0700) Subject: 4.14-stable patches X-Git-Tag: v3.18.121~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1318acd24c863f88b5cb737e8fe3add8fd0be833;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: btrfs-don-t-leak-ret-from-do_chunk_alloc.patch btrfs-fix-btrfs_write_inode-vs-delayed-iput-deadlock.patch btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch cifs-add-missing-debug-entries-for-kconfig-options.patch cifs-check-kmalloc-before-use.patch smb3-do-not-send-smb3-set_info-if-nothing-changed.patch smb3-don-t-request-leases-in-symlink-creation-and-query.patch smb3-enumerating-snapshots-was-leaving-part-of-the-data-off-end.patch smb3-fill-in-statfs-fsid-and-correct-namelen.patch --- diff --git a/queue-4.14/btrfs-don-t-leak-ret-from-do_chunk_alloc.patch b/queue-4.14/btrfs-don-t-leak-ret-from-do_chunk_alloc.patch new file mode 100644 index 00000000000..a7e97b76835 --- /dev/null +++ b/queue-4.14/btrfs-don-t-leak-ret-from-do_chunk_alloc.patch @@ -0,0 +1,35 @@ +From 4559b0a71749c442d34f7cfb9e72c9e58db83948 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Thu, 19 Jul 2018 10:49:51 -0400 +Subject: btrfs: don't leak ret from do_chunk_alloc + +From: Josef Bacik + +commit 4559b0a71749c442d34f7cfb9e72c9e58db83948 upstream. + +If we're trying to make a data reservation and we have to allocate a +data chunk we could leak ret == 1, as do_chunk_alloc() will return 1 if +it allocated a chunk. Since the end of the function is the success path +just return 0. + +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Josef Bacik +Reviewed-by: Nikolay Borisov +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent-tree.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4407,7 +4407,7 @@ commit_trans: + data_sinfo->flags, bytes, 1); + spin_unlock(&data_sinfo->lock); + +- return ret; ++ return 0; + } + + int btrfs_check_data_free_space(struct inode *inode, diff --git a/queue-4.14/btrfs-fix-btrfs_write_inode-vs-delayed-iput-deadlock.patch b/queue-4.14/btrfs-fix-btrfs_write_inode-vs-delayed-iput-deadlock.patch new file mode 100644 index 00000000000..603f9cd008f --- /dev/null +++ b/queue-4.14/btrfs-fix-btrfs_write_inode-vs-delayed-iput-deadlock.patch @@ -0,0 +1,112 @@ +From 3c4276936f6fbe52884b4ea4e6cc120b890a0f9f Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 20 Jul 2018 11:46:10 -0700 +Subject: Btrfs: fix btrfs_write_inode vs delayed iput deadlock + +From: Josef Bacik + +commit 3c4276936f6fbe52884b4ea4e6cc120b890a0f9f upstream. + +We recently ran into the following deadlock involving +btrfs_write_inode(): + +[ +0.005066] __schedule+0x38e/0x8c0 +[ +0.007144] schedule+0x36/0x80 +[ +0.006447] bit_wait+0x11/0x60 +[ +0.006446] __wait_on_bit+0xbe/0x110 +[ +0.007487] ? bit_wait_io+0x60/0x60 +[ +0.007319] __inode_wait_for_writeback+0x96/0xc0 +[ +0.009568] ? autoremove_wake_function+0x40/0x40 +[ +0.009565] inode_wait_for_writeback+0x21/0x30 +[ +0.009224] evict+0xb0/0x190 +[ +0.006099] iput+0x1a8/0x210 +[ +0.006103] btrfs_run_delayed_iputs+0x73/0xc0 +[ +0.009047] btrfs_commit_transaction+0x799/0x8c0 +[ +0.009567] btrfs_write_inode+0x81/0xb0 +[ +0.008008] __writeback_single_inode+0x267/0x320 +[ +0.009569] writeback_sb_inodes+0x25b/0x4e0 +[ +0.008702] wb_writeback+0x102/0x2d0 +[ +0.007487] wb_workfn+0xa4/0x310 +[ +0.006794] ? wb_workfn+0xa4/0x310 +[ +0.007143] process_one_work+0x150/0x410 +[ +0.008179] worker_thread+0x6d/0x520 +[ +0.007490] kthread+0x12c/0x160 +[ +0.006620] ? put_pwq_unlocked+0x80/0x80 +[ +0.008185] ? kthread_park+0xa0/0xa0 +[ +0.007484] ? do_syscall_64+0x53/0x150 +[ +0.007837] ret_from_fork+0x29/0x40 + +Writeback calls: + +btrfs_write_inode + btrfs_commit_transaction + btrfs_run_delayed_iputs + +If iput() is called on that same inode, evict() will wait for writeback +forever. + +btrfs_write_inode() was originally added way back in 4730a4bc5bf3 +("btrfs_dirty_inode") to support O_SYNC writes. However, ->write_inode() +hasn't been used for O_SYNC since 148f948ba877 ("vfs: Introduce new +helpers for syncing after writing to O_SYNC file or IS_SYNC inode"), so +btrfs_write_inode() is actually unnecessary (and leads to a bunch of +unnecessary commits). Get rid of it, which also gets rid of the +deadlock. + +CC: stable@vger.kernel.org # 3.2+ +Signed-off-by: Josef Bacik +[Omar: new commit message] +Signed-off-by: Omar Sandoval +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/inode.c | 26 -------------------------- + fs/btrfs/super.c | 1 - + 2 files changed, 27 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -6152,32 +6152,6 @@ err: + return ret; + } + +-int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) +-{ +- struct btrfs_root *root = BTRFS_I(inode)->root; +- struct btrfs_trans_handle *trans; +- int ret = 0; +- bool nolock = false; +- +- if (test_bit(BTRFS_INODE_DUMMY, &BTRFS_I(inode)->runtime_flags)) +- return 0; +- +- if (btrfs_fs_closing(root->fs_info) && +- btrfs_is_free_space_inode(BTRFS_I(inode))) +- nolock = true; +- +- if (wbc->sync_mode == WB_SYNC_ALL) { +- if (nolock) +- trans = btrfs_join_transaction_nolock(root); +- else +- trans = btrfs_join_transaction(root); +- if (IS_ERR(trans)) +- return PTR_ERR(trans); +- ret = btrfs_commit_transaction(trans); +- } +- return ret; +-} +- + /* + * This is somewhat expensive, updating the tree every time the + * inode changes. But, it is most likely to find the inode in cache. +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -2271,7 +2271,6 @@ static const struct super_operations btr + .sync_fs = btrfs_sync_fs, + .show_options = btrfs_show_options, + .show_devname = btrfs_show_devname, +- .write_inode = btrfs_write_inode, + .alloc_inode = btrfs_alloc_inode, + .destroy_inode = btrfs_destroy_inode, + .statfs = btrfs_statfs, diff --git a/queue-4.14/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch b/queue-4.14/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch new file mode 100644 index 00000000000..7ef2b028c9c --- /dev/null +++ b/queue-4.14/btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch @@ -0,0 +1,141 @@ +From 0d836392cadd5535f4184d46d901a82eb276ed62 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Fri, 20 Jul 2018 10:59:06 +0100 +Subject: Btrfs: fix mount failure after fsync due to hard link recreation + +From: Filipe Manana + +commit 0d836392cadd5535f4184d46d901a82eb276ed62 upstream. + +If we end up with logging an inode reference item which has the same name +but different index from the one we have persisted, we end up failing when +replaying the log with an errno value of -EEXIST. The error comes from +btrfs_add_link(), which is called from add_inode_ref(), when we are +replaying an inode reference item. + +Example scenario where this happens: + + $ mkfs.btrfs -f /dev/sdb + $ mount /dev/sdb /mnt + + $ touch /mnt/foo + $ ln /mnt/foo /mnt/bar + + $ sync + + # Rename the first hard link (foo) to a new name and rename the second + # hard link (bar) to the old name of the first hard link (foo). + $ mv /mnt/foo /mnt/qwerty + $ mv /mnt/bar /mnt/foo + + # Create a new file, in the same parent directory, with the old name of + # the second hard link (bar) and fsync this new file. + # We do this instead of calling fsync on foo/qwerty because if we did + # that the fsync resulted in a full transaction commit, not triggering + # the problem. + $ touch /mnt/bar + $ xfs_io -c "fsync" /mnt/bar + + + + $ mount /dev/sdb /mnt + mount: mount /dev/sdb on /mnt failed: File exists + +So fix this by checking if a conflicting inode reference exists (same +name, same parent but different index), removing it (and the associated +dir index entries from the parent inode) if it exists, before attempting +to add the new reference. + +A test case for fstests follows soon. + +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 66 insertions(+) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1225,6 +1225,46 @@ static int ref_get_fields(struct extent_ + return 0; + } + ++static int btrfs_inode_ref_exists(struct inode *inode, struct inode *dir, ++ const u8 ref_type, const char *name, ++ const int namelen) ++{ ++ struct btrfs_key key; ++ struct btrfs_path *path; ++ const u64 parent_id = btrfs_ino(BTRFS_I(dir)); ++ int ret; ++ ++ path = btrfs_alloc_path(); ++ if (!path) ++ return -ENOMEM; ++ ++ key.objectid = btrfs_ino(BTRFS_I(inode)); ++ key.type = ref_type; ++ if (key.type == BTRFS_INODE_REF_KEY) ++ key.offset = parent_id; ++ else ++ key.offset = btrfs_extref_hash(parent_id, name, namelen); ++ ++ ret = btrfs_search_slot(NULL, BTRFS_I(inode)->root, &key, path, 0, 0); ++ if (ret < 0) ++ goto out; ++ if (ret > 0) { ++ ret = 0; ++ goto out; ++ } ++ if (key.type == BTRFS_INODE_EXTREF_KEY) ++ ret = btrfs_find_name_in_ext_backref(path->nodes[0], ++ path->slots[0], parent_id, ++ name, namelen, NULL); ++ else ++ ret = btrfs_find_name_in_backref(path->nodes[0], path->slots[0], ++ name, namelen, NULL); ++ ++out: ++ btrfs_free_path(path); ++ return ret; ++} ++ + /* + * replay one inode back reference item found in the log tree. + * eb, slot and key refer to the buffer and key found in the log tree. +@@ -1334,6 +1374,32 @@ static noinline int add_inode_ref(struct + } + } + ++ /* ++ * If a reference item already exists for this inode ++ * with the same parent and name, but different index, ++ * drop it and the corresponding directory index entries ++ * from the parent before adding the new reference item ++ * and dir index entries, otherwise we would fail with ++ * -EEXIST returned from btrfs_add_link() below. ++ */ ++ ret = btrfs_inode_ref_exists(inode, dir, key->type, ++ name, namelen); ++ if (ret > 0) { ++ ret = btrfs_unlink_inode(trans, root, ++ BTRFS_I(dir), ++ BTRFS_I(inode), ++ name, namelen); ++ /* ++ * If we dropped the link count to 0, bump it so ++ * that later the iput() on the inode will not ++ * free it. We will fixup the link count later. ++ */ ++ if (!ret && inode->i_nlink == 0) ++ inc_nlink(inode); ++ } ++ if (ret < 0) ++ goto out; ++ + /* insert our name */ + ret = btrfs_add_link(trans, BTRFS_I(dir), + BTRFS_I(inode), diff --git a/queue-4.14/btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch b/queue-4.14/btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch new file mode 100644 index 00000000000..7b7e24dc09f --- /dev/null +++ b/queue-4.14/btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch @@ -0,0 +1,50 @@ +From d814a49198eafa6163698bdd93961302f3a877a4 Mon Sep 17 00:00:00 2001 +From: Ethan Lien +Date: Mon, 2 Jul 2018 15:44:58 +0800 +Subject: btrfs: use correct compare function of dirty_metadata_bytes + +From: Ethan Lien + +commit d814a49198eafa6163698bdd93961302f3a877a4 upstream. + +We use customized, nodesize batch value to update dirty_metadata_bytes. +We should also use batch version of compare function or we will easily +goto fast path and get false result from percpu_counter_compare(). + +Fixes: e2d845211eda ("Btrfs: use percpu counter for dirty metadata count") +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Ethan Lien +Reviewed-by: Nikolay Borisov +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/disk-io.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1098,8 +1098,9 @@ static int btree_writepages(struct addre + + fs_info = BTRFS_I(mapping->host)->root->fs_info; + /* this is a bit racy, but that's ok */ +- ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes, +- BTRFS_DIRTY_METADATA_THRESH); ++ ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes, ++ BTRFS_DIRTY_METADATA_THRESH, ++ fs_info->dirty_metadata_batch); + if (ret < 0) + return 0; + } +@@ -4030,8 +4031,9 @@ static void __btrfs_btree_balance_dirty( + if (flush_delayed) + btrfs_balance_delayed_items(fs_info); + +- ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes, +- BTRFS_DIRTY_METADATA_THRESH); ++ ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes, ++ BTRFS_DIRTY_METADATA_THRESH, ++ fs_info->dirty_metadata_batch); + if (ret > 0) { + balance_dirty_pages_ratelimited(fs_info->btree_inode->i_mapping); + } diff --git a/queue-4.14/cifs-add-missing-debug-entries-for-kconfig-options.patch b/queue-4.14/cifs-add-missing-debug-entries-for-kconfig-options.patch new file mode 100644 index 00000000000..3330cb83287 --- /dev/null +++ b/queue-4.14/cifs-add-missing-debug-entries-for-kconfig-options.patch @@ -0,0 +1,84 @@ +From 950132afd59385caf6e2b84e5235d069fa10681d Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Thu, 28 Jun 2018 18:46:40 -0500 +Subject: cifs: add missing debug entries for kconfig options + +From: Steve French + +commit 950132afd59385caf6e2b84e5235d069fa10681d upstream. + +/proc/fs/cifs/DebugData displays the features (Kconfig options) +used to build cifs.ko but it was missing some, and needed comma +separator. These can be useful in debugging certain problems +so we know which optional features were enabled in the user's build. +Also clarify them, by making them more closely match the +corresponding CONFIG_CIFS_* parm. + +Old format: +Features: dfs fscache posix spnego xattr acl + +New format: +Features: DFS,FSCACHE,SMB_DIRECT,STATS,DEBUG2,ALLOW_INSECURE_LEGACY,CIFS_POSIX,UPCALL(SPNEGO),XATTR,ACL + +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Reviewed-by: Pavel Shilovsky +Reviewed-by: Paulo Alcantara +CC: Stable +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifs_debug.c | 30 +++++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +--- a/fs/cifs/cifs_debug.c ++++ b/fs/cifs/cifs_debug.c +@@ -123,25 +123,41 @@ static int cifs_debug_data_proc_show(str + seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); + seq_printf(m, "Features:"); + #ifdef CONFIG_CIFS_DFS_UPCALL +- seq_printf(m, " dfs"); ++ seq_printf(m, " DFS"); + #endif + #ifdef CONFIG_CIFS_FSCACHE +- seq_printf(m, " fscache"); ++ seq_printf(m, ",FSCACHE"); ++#endif ++#ifdef CONFIG_CIFS_SMB_DIRECT ++ seq_printf(m, ",SMB_DIRECT"); ++#endif ++#ifdef CONFIG_CIFS_STATS2 ++ seq_printf(m, ",STATS2"); ++#elif defined(CONFIG_CIFS_STATS) ++ seq_printf(m, ",STATS"); ++#endif ++#ifdef CONFIG_CIFS_DEBUG2 ++ seq_printf(m, ",DEBUG2"); ++#elif defined(CONFIG_CIFS_DEBUG) ++ seq_printf(m, ",DEBUG"); ++#endif ++#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY ++ seq_printf(m, ",ALLOW_INSECURE_LEGACY"); + #endif + #ifdef CONFIG_CIFS_WEAK_PW_HASH +- seq_printf(m, " lanman"); ++ seq_printf(m, ",WEAK_PW_HASH"); + #endif + #ifdef CONFIG_CIFS_POSIX +- seq_printf(m, " posix"); ++ seq_printf(m, ",CIFS_POSIX"); + #endif + #ifdef CONFIG_CIFS_UPCALL +- seq_printf(m, " spnego"); ++ seq_printf(m, ",UPCALL(SPNEGO)"); + #endif + #ifdef CONFIG_CIFS_XATTR +- seq_printf(m, " xattr"); ++ seq_printf(m, ",XATTR"); + #endif + #ifdef CONFIG_CIFS_ACL +- seq_printf(m, " acl"); ++ seq_printf(m, ",ACL"); + #endif + seq_putc(m, '\n'); + seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); diff --git a/queue-4.14/cifs-check-kmalloc-before-use.patch b/queue-4.14/cifs-check-kmalloc-before-use.patch new file mode 100644 index 00000000000..0a3d8e1f248 --- /dev/null +++ b/queue-4.14/cifs-check-kmalloc-before-use.patch @@ -0,0 +1,38 @@ +From 126c97f4d0d1b5b956e8b0740c81a2b2a2ae548c Mon Sep 17 00:00:00 2001 +From: Nicholas Mc Guire +Date: Thu, 23 Aug 2018 12:24:02 +0200 +Subject: cifs: check kmalloc before use + +From: Nicholas Mc Guire + +commit 126c97f4d0d1b5b956e8b0740c81a2b2a2ae548c upstream. + +The kmalloc was not being checked - if it fails issue a warning +and return -ENOMEM to the caller. + +Signed-off-by: Nicholas Mc Guire +Fixes: b8da344b74c8 ("cifs: dynamic allocation of ntlmssp blob") +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +cc: Stable ` +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/sess.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/cifs/sess.c ++++ b/fs/cifs/sess.c +@@ -398,6 +398,12 @@ int build_ntlmssp_auth_blob(unsigned cha + goto setup_ntlmv2_ret; + } + *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL); ++ if (!*pbuffer) { ++ rc = -ENOMEM; ++ cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); ++ *buflen = 0; ++ goto setup_ntlmv2_ret; ++ } + sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer; + + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); diff --git a/queue-4.14/series b/queue-4.14/series index 1ebb7551b92..1bbfef7ca96 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -81,3 +81,13 @@ scsi-fcoe-clear-fc_rp_started-flags-when-receiving-a-logo.patch scsi-vmw_pvscsi-return-did_reset-for-status-sam_stat_command_terminated.patch mm-memory.c-check-return-value-of-ioremap_prot.patch mei-don-t-update-offset-in-write.patch +cifs-add-missing-debug-entries-for-kconfig-options.patch +cifs-check-kmalloc-before-use.patch +smb3-enumerating-snapshots-was-leaving-part-of-the-data-off-end.patch +smb3-do-not-send-smb3-set_info-if-nothing-changed.patch +smb3-don-t-request-leases-in-symlink-creation-and-query.patch +smb3-fill-in-statfs-fsid-and-correct-namelen.patch +btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch +btrfs-don-t-leak-ret-from-do_chunk_alloc.patch +btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch +btrfs-fix-btrfs_write_inode-vs-delayed-iput-deadlock.patch diff --git a/queue-4.14/smb3-do-not-send-smb3-set_info-if-nothing-changed.patch b/queue-4.14/smb3-do-not-send-smb3-set_info-if-nothing-changed.patch new file mode 100644 index 00000000000..007d5dfa92e --- /dev/null +++ b/queue-4.14/smb3-do-not-send-smb3-set_info-if-nothing-changed.patch @@ -0,0 +1,53 @@ +From fd09b7d3b352105f08b8e02f7afecf7e816380ef Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Thu, 2 Aug 2018 20:28:18 -0500 +Subject: smb3: Do not send SMB3 SET_INFO if nothing changed + +From: Steve French + +commit fd09b7d3b352105f08b8e02f7afecf7e816380ef upstream. + +An earlier commit had a typo which prevented the +optimization from working: + +commit 18dd8e1a65dd ("Do not send SMB3 SET_INFO request if nothing is changing") + +Thank you to Metze for noticing this. Also clear a +reserved field in the FILE_BASIC_INFO struct we send +that should be zero (all the other fields in that +struct were set or cleared explicitly already in +cifs_set_file_info). + +Reviewed-by: Pavel Shilovsky +CC: Stable # 4.9.x+ +Reported-by: Stefan Metzmacher +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/inode.c | 2 ++ + fs/cifs/smb2inode.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -1122,6 +1122,8 @@ cifs_set_file_info(struct inode *inode, + if (!server->ops->set_file_info) + return -ENOSYS; + ++ info_buf.Pad = 0; ++ + if (attrs->ia_valid & ATTR_ATIME) { + set_time = true; + info_buf.LastAccessTime = +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -267,7 +267,7 @@ smb2_set_file_info(struct inode *inode, + int rc; + + if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) && +- (buf->LastWriteTime == 0) && (buf->ChangeTime) && ++ (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) && + (buf->Attributes == 0)) + return 0; /* would be a no op, no sense sending this */ + diff --git a/queue-4.14/smb3-don-t-request-leases-in-symlink-creation-and-query.patch b/queue-4.14/smb3-don-t-request-leases-in-symlink-creation-and-query.patch new file mode 100644 index 00000000000..e90ece66048 --- /dev/null +++ b/queue-4.14/smb3-don-t-request-leases-in-symlink-creation-and-query.patch @@ -0,0 +1,42 @@ +From 22783155f4bf956c346a81624ec9258930a6fe06 Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Fri, 27 Jul 2018 22:01:49 -0500 +Subject: smb3: don't request leases in symlink creation and query + +From: Steve French + +commit 22783155f4bf956c346a81624ec9258930a6fe06 upstream. + +Fixes problem pointed out by Pavel in discussions about commit +729c0c9dd55204f0c9a823ac8a7bfa83d36c7e78 + +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +CC: Stable # 3.18.x+ +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/link.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/cifs/link.c ++++ b/fs/cifs/link.c +@@ -396,7 +396,7 @@ smb3_query_mf_symlink(unsigned int xid, + struct cifs_io_parms io_parms; + int buf_type = CIFS_NO_BUFFER; + __le16 *utf16_path; +- __u8 oplock = SMB2_OPLOCK_LEVEL_II; ++ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct smb2_file_all_info *pfile_info = NULL; + + oparms.tcon = tcon; +@@ -458,7 +458,7 @@ smb3_create_mf_symlink(unsigned int xid, + struct cifs_io_parms io_parms; + int create_options = CREATE_NOT_DIR; + __le16 *utf16_path; +- __u8 oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; ++ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct kvec iov[2]; + + if (backup_cred(cifs_sb)) diff --git a/queue-4.14/smb3-enumerating-snapshots-was-leaving-part-of-the-data-off-end.patch b/queue-4.14/smb3-enumerating-snapshots-was-leaving-part-of-the-data-off-end.patch new file mode 100644 index 00000000000..20d80dab0bb --- /dev/null +++ b/queue-4.14/smb3-enumerating-snapshots-was-leaving-part-of-the-data-off-end.patch @@ -0,0 +1,90 @@ +From e02789a53d71334b067ad72eee5d4e88a0158083 Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Thu, 9 Aug 2018 14:33:12 -0500 +Subject: smb3: enumerating snapshots was leaving part of the data off end + +From: Steve French + +commit e02789a53d71334b067ad72eee5d4e88a0158083 upstream. + +When enumerating snapshots, the last few bytes of the final +snapshot could be left off since we were miscalculating the +length returned (leaving off the sizeof struct SRV_SNAPSHOT_ARRAY) +See MS-SMB2 section 2.2.32.2. In addition fixup the length used +to allow smaller buffer to be passed in, in order to allow +returning the size of the whole snapshot array more easily. + +Sample userspace output with a kernel patched with this +(mounted to a Windows volume with two snapshots). +Before this patch, the second snapshot would be missing a +few bytes at the end. + +~/cifs-2.6# ~/enum-snapshots /mnt/file +press enter to issue the ioctl to retrieve snapshot information ... + +size of snapshot array = 102 +Num snapshots: 2 Num returned: 2 Array Size: 102 + +Snapshot 0:@GMT-2018.06.30-19.34.17 +Snapshot 1:@GMT-2018.06.30-19.33.37 + +CC: Stable +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2ops.c | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1129,6 +1129,13 @@ smb3_set_integrity(const unsigned int xi + + } + ++/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */ ++#define GMT_TOKEN_SIZE 50 ++ ++/* ++ * Input buffer contains (empty) struct smb_snapshot array with size filled in ++ * For output see struct SRV_SNAPSHOT_ARRAY in MS-SMB2 section 2.2.32.2 ++ */ + static int + smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon, + struct cifsFileInfo *cfile, void __user *ioc_buf) +@@ -1158,14 +1165,27 @@ smb3_enum_snapshots(const unsigned int x + kfree(retbuf); + return rc; + } +- if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) { +- rc = -ERANGE; +- kfree(retbuf); +- return rc; +- } + +- if (ret_data_len > snapshot_in.snapshot_array_size) +- ret_data_len = snapshot_in.snapshot_array_size; ++ /* ++ * Check for min size, ie not large enough to fit even one GMT ++ * token (snapshot). On the first ioctl some users may pass in ++ * smaller size (or zero) to simply get the size of the array ++ * so the user space caller can allocate sufficient memory ++ * and retry the ioctl again with larger array size sufficient ++ * to hold all of the snapshot GMT tokens on the second try. ++ */ ++ if (snapshot_in.snapshot_array_size < GMT_TOKEN_SIZE) ++ ret_data_len = sizeof(struct smb_snapshot_array); ++ ++ /* ++ * We return struct SRV_SNAPSHOT_ARRAY, followed by ++ * the snapshot array (of 50 byte GMT tokens) each ++ * representing an available previous version of the data ++ */ ++ if (ret_data_len > (snapshot_in.snapshot_array_size + ++ sizeof(struct smb_snapshot_array))) ++ ret_data_len = snapshot_in.snapshot_array_size + ++ sizeof(struct smb_snapshot_array); + + if (copy_to_user(ioc_buf, retbuf, ret_data_len)) + rc = -EFAULT; diff --git a/queue-4.14/smb3-fill-in-statfs-fsid-and-correct-namelen.patch b/queue-4.14/smb3-fill-in-statfs-fsid-and-correct-namelen.patch new file mode 100644 index 00000000000..0ddfebcf593 --- /dev/null +++ b/queue-4.14/smb3-fill-in-statfs-fsid-and-correct-namelen.patch @@ -0,0 +1,112 @@ +From 21ba3845b59c733a79ed4fe1c4f3732e7ece9df7 Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Sun, 24 Jun 2018 23:18:52 -0500 +Subject: smb3: fill in statfs fsid and correct namelen + +From: Steve French + +commit 21ba3845b59c733a79ed4fe1c4f3732e7ece9df7 upstream. + +Fil in the correct namelen (typically 255 not 4096) in the +statfs response and also fill in a reasonably unique fsid +(in this case taken from the volume id, and the creation time +of the volume). + +In the case of the POSIX statfs all fields are now filled in, +and in the case of non-POSIX mounts, all fields are filled +in which can be. + +Signed-off-by: Steve French +CC: Stable +Reviewed-by: Aurelien Aptel +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifsfs.c | 18 ++++++++++-------- + fs/cifs/smb2ops.c | 2 ++ + fs/cifs/smb2pdu.c | 8 ++++++++ + fs/cifs/smb2pdu.h | 11 +++++++++++ + 4 files changed, 31 insertions(+), 8 deletions(-) + +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -197,14 +197,16 @@ cifs_statfs(struct dentry *dentry, struc + + xid = get_xid(); + +- /* +- * PATH_MAX may be too long - it would presumably be total path, +- * but note that some servers (includinng Samba 3) have a shorter +- * maximum path. +- * +- * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO. +- */ +- buf->f_namelen = PATH_MAX; ++ if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0) ++ buf->f_namelen = ++ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength); ++ else ++ buf->f_namelen = PATH_MAX; ++ ++ buf->f_fsid.val[0] = tcon->vol_serial_number; ++ /* are using part of create time for more randomness, see man statfs */ ++ buf->f_fsid.val[1] = (int)le64_to_cpu(tcon->vol_create_time); ++ + buf->f_files = 0; /* undefined */ + buf->f_ffree = 0; /* unlimited */ + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -333,6 +333,8 @@ smb3_qfs_tcon(const unsigned int xid, st + SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, + FS_DEVICE_INFORMATION); + SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, ++ FS_VOLUME_INFORMATION); ++ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, + FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */ + SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); + return; +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -3455,6 +3455,9 @@ SMB2_QFS_attr(const unsigned int xid, st + } else if (level == FS_SECTOR_SIZE_INFORMATION) { + max_len = sizeof(struct smb3_fs_ss_info); + min_len = sizeof(struct smb3_fs_ss_info); ++ } else if (level == FS_VOLUME_INFORMATION) { ++ max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN; ++ min_len = sizeof(struct smb3_fs_vol_info); + } else { + cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level); + return -EINVAL; +@@ -3495,6 +3498,11 @@ SMB2_QFS_attr(const unsigned int xid, st + tcon->ss_flags = le32_to_cpu(ss_info->Flags); + tcon->perf_sector_size = + le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf); ++ } else if (level == FS_VOLUME_INFORMATION) { ++ struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *) ++ (offset + (char *)rsp); ++ tcon->vol_serial_number = vol_info->VolumeSerialNumber; ++ tcon->vol_create_time = vol_info->VolumeCreationTime; + } + + qfsattr_exit: +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1108,6 +1108,17 @@ struct smb3_fs_ss_info { + __le32 ByteOffsetForPartitionAlignment; + } __packed; + ++/* volume info struct - see MS-FSCC 2.5.9 */ ++#define MAX_VOL_LABEL_LEN 32 ++struct smb3_fs_vol_info { ++ __le64 VolumeCreationTime; ++ __u32 VolumeSerialNumber; ++ __le32 VolumeLabelLength; /* includes trailing null */ ++ __u8 SupportsObjects; /* True if eg like NTFS, supports objects */ ++ __u8 Reserved; ++ __u8 VolumeLabel[0]; /* variable len */ ++} __packed; ++ + /* partial list of QUERY INFO levels */ + #define FILE_DIRECTORY_INFORMATION 1 + #define FILE_FULL_DIRECTORY_INFORMATION 2