--- /dev/null
+From db20a8925bc420eed033c5d91ff6afa74465e521 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Wed, 3 Aug 2016 17:57:39 +0100
+Subject: cachefiles: Fix race between inactivating and culling a cache object
+
+From: David Howells <dhowells@redhat.com>
+
+commit db20a8925bc420eed033c5d91ff6afa74465e521 upstream.
+
+There's a race between cachefiles_mark_object_inactive() and
+cachefiles_cull():
+
+ (1) cachefiles_cull() can't delete a backing file until the cache object
+ is marked inactive, but as soon as that's the case it's fair game.
+
+ (2) cachefiles_mark_object_inactive() marks the object as being inactive
+ and *only then* reads the i_blocks on the backing inode - but
+ cachefiles_cull() might've managed to delete it by this point.
+
+Fix this by making sure cachefiles_mark_object_inactive() gets any data it
+needs from the backing inode before deactivating the object.
+
+Without this, the following oops may occur:
+
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000098
+IP: [<ffffffffa06c5cc1>] cachefiles_mark_object_inactive+0x61/0xb0 [cachefiles]
+...
+CPU: 11 PID: 527 Comm: kworker/u64:4 Tainted: G I ------------ 3.10.0-470.el7.x86_64 #1
+Hardware name: Hewlett-Packard HP Z600 Workstation/0B54h, BIOS 786G4 v03.19 03/11/2011
+Workqueue: fscache_object fscache_object_work_func [fscache]
+task: ffff880035edaf10 ti: ffff8800b77c0000 task.ti: ffff8800b77c0000
+RIP: 0010:[<ffffffffa06c5cc1>] cachefiles_mark_object_inactive+0x61/0xb0 [cachefiles]
+RSP: 0018:ffff8800b77c3d70 EFLAGS: 00010246
+RAX: 0000000000000000 RBX: ffff8800bf6cc400 RCX: 0000000000000034
+RDX: 0000000000000000 RSI: ffff880090ffc710 RDI: ffff8800bf761ef8
+RBP: ffff8800b77c3d88 R08: 2000000000000000 R09: 0090ffc710000000
+R10: ff51005d2ff1c400 R11: 0000000000000000 R12: ffff880090ffc600
+R13: ffff8800bf6cc520 R14: ffff8800bf6cc400 R15: ffff8800bf6cc498
+FS: 0000000000000000(0000) GS:ffff8800bb8c0000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+CR2: 0000000000000098 CR3: 00000000019ba000 CR4: 00000000000007e0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+Stack:
+ ffff880090ffc600 ffff8800bf6cc400 ffff8800867df140 ffff8800b77c3db0
+ ffffffffa06c48cb ffff880090ffc600 ffff880090ffc180 ffff880090ffc658
+ ffff8800b77c3df0 ffffffffa085d846 ffff8800a96b8150 ffff880090ffc600
+Call Trace:
+ [<ffffffffa06c48cb>] cachefiles_drop_object+0x6b/0xf0 [cachefiles]
+ [<ffffffffa085d846>] fscache_drop_object+0xd6/0x1e0 [fscache]
+ [<ffffffffa085d615>] fscache_object_work_func+0xa5/0x200 [fscache]
+ [<ffffffff810a605b>] process_one_work+0x17b/0x470
+ [<ffffffff810a6e96>] worker_thread+0x126/0x410
+ [<ffffffff810a6d70>] ? rescuer_thread+0x460/0x460
+ [<ffffffff810ae64f>] kthread+0xcf/0xe0
+ [<ffffffff810ae580>] ? kthread_create_on_node+0x140/0x140
+ [<ffffffff81695418>] ret_from_fork+0x58/0x90
+ [<ffffffff810ae580>] ? kthread_create_on_node+0x140/0x140
+
+The oopsing code shows:
+
+ callq 0xffffffff810af6a0 <wake_up_bit>
+ mov 0xf8(%r12),%rax
+ mov 0x30(%rax),%rax
+ mov 0x98(%rax),%rax <---- oops here
+ lock add %rax,0x130(%rbx)
+
+where this is:
+
+ d_backing_inode(object->dentry)->i_blocks
+
+Fixes: a5b3a80b899bda0f456f1246c4c5a1191ea01519 (CacheFiles: Provide read-and-reset release counters for cachefilesd)
+Reported-by: Jianhong Yin <jiyin@redhat.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Jeff Layton <jlayton@redhat.com>
+Reviewed-by: Steve Dickson <steved@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cachefiles/namei.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/cachefiles/namei.c
++++ b/fs/cachefiles/namei.c
+@@ -263,6 +263,8 @@ requeue:
+ void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
+ struct cachefiles_object *object)
+ {
++ blkcnt_t i_blocks = d_backing_inode(object->dentry)->i_blocks;
++
+ write_lock(&cache->active_lock);
+ rb_erase(&object->active_node, &cache->active_nodes);
+ clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
+@@ -273,8 +275,7 @@ void cachefiles_mark_object_inactive(str
+ /* This object can now be culled, so we need to let the daemon know
+ * that there is something it can remove if it needs to.
+ */
+- atomic_long_add(d_backing_inode(object->dentry)->i_blocks,
+- &cache->b_released);
++ atomic_long_add(i_blocks, &cache->b_released);
+ if (atomic_inc_return(&cache->f_released))
+ cachefiles_state_changed(cache);
+ }
--- /dev/null
+From 8d9535b6efd86e6c07da59f97e68f44efb7fe080 Mon Sep 17 00:00:00 2001
+From: Sachin Prabhu <sprabhu@redhat.com>
+Date: Thu, 7 Jul 2016 21:28:27 +0100
+Subject: cifs: Check for existing directory when opening file with O_CREAT
+
+From: Sachin Prabhu <sprabhu@redhat.com>
+
+commit 8d9535b6efd86e6c07da59f97e68f44efb7fe080 upstream.
+
+When opening a file with O_CREAT flag, check to see if the file opened
+is an existing directory.
+
+This prevents the directory from being opened which subsequently causes
+a crash when the close function for directories cifs_closedir() is called
+which frees up the file->private_data memory while the file is still
+listed on the open file list for the tcon.
+
+Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reported-by: Xiaoli Feng <xifeng@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/dir.c | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+--- a/fs/cifs/dir.c
++++ b/fs/cifs/dir.c
+@@ -245,6 +245,13 @@ cifs_do_create(struct inode *inode, stru
+ goto cifs_create_get_file_info;
+ }
+
++ if (S_ISDIR(newinode->i_mode)) {
++ CIFSSMBClose(xid, tcon, fid->netfid);
++ iput(newinode);
++ rc = -EISDIR;
++ goto out;
++ }
++
+ if (!S_ISREG(newinode->i_mode)) {
+ /*
+ * The server may allow us to open things like
+@@ -415,10 +422,14 @@ cifs_create_set_dentry:
+ if (rc != 0) {
+ cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n",
+ rc);
+- if (server->ops->close)
+- server->ops->close(xid, tcon, fid);
+- goto out;
++ goto out_err;
+ }
++
++ if (S_ISDIR(newinode->i_mode)) {
++ rc = -EISDIR;
++ goto out_err;
++ }
++
+ d_drop(direntry);
+ d_add(direntry, newinode);
+
+@@ -426,6 +437,13 @@ out:
+ kfree(buf);
+ kfree(full_path);
+ return rc;
++
++out_err:
++ if (server->ops->close)
++ server->ops->close(xid, tcon, fid);
++ if (newinode)
++ iput(newinode);
++ goto out;
+ }
+
+ int
--- /dev/null
+From 7893242e2465aea6f2cbc2639da8fa5ce96e8cc2 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Sun, 24 Jul 2016 10:37:38 +0300
+Subject: CIFS: Fix a possible invalid memory access in smb2_query_symlink()
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 7893242e2465aea6f2cbc2639da8fa5ce96e8cc2 upstream.
+
+During following a symbolic link we received err_buf from SMB2_open().
+While the validity of SMB2 error response is checked previously
+in smb2_check_message() a symbolic link payload is not checked at all.
+Fix it by adding such checks.
+
+Cc: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c | 30 +++++++++++++++++++++++++++++-
+ 1 file changed, 29 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -1044,6 +1044,9 @@ smb2_new_lease_key(struct cifs_fid *fid)
+ get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
+ }
+
++#define SMB2_SYMLINK_STRUCT_SIZE \
++ (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
++
+ static int
+ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *full_path, char **target_path,
+@@ -1056,7 +1059,10 @@ smb2_query_symlink(const unsigned int xi
+ struct cifs_fid fid;
+ struct smb2_err_rsp *err_buf = NULL;
+ struct smb2_symlink_err_rsp *symlink;
+- unsigned int sub_len, sub_offset;
++ unsigned int sub_len;
++ unsigned int sub_offset;
++ unsigned int print_len;
++ unsigned int print_offset;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
+
+@@ -1077,11 +1083,33 @@ smb2_query_symlink(const unsigned int xi
+ kfree(utf16_path);
+ return -ENOENT;
+ }
++
++ if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
++ get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
++ kfree(utf16_path);
++ return -ENOENT;
++ }
++
+ /* open must fail on symlink - reset rc */
+ rc = 0;
+ symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
+ sub_len = le16_to_cpu(symlink->SubstituteNameLength);
+ sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
++ print_len = le16_to_cpu(symlink->PrintNameLength);
++ print_offset = le16_to_cpu(symlink->PrintNameOffset);
++
++ if (get_rfc1002_length(err_buf) + 4 <
++ SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
++ kfree(utf16_path);
++ return -ENOENT;
++ }
++
++ if (get_rfc1002_length(err_buf) + 4 <
++ SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
++ kfree(utf16_path);
++ return -ENOENT;
++ }
++
+ *target_path = cifs_strndup_from_utf16(
+ (char *)symlink->PathBuffer + sub_offset,
+ sub_len, true, cifs_sb->local_nls);
--- /dev/null
+From bd975d1eead2558b76e1079e861eacf1f678b73b Mon Sep 17 00:00:00 2001
+From: Rabin Vincent <rabinv@axis.com>
+Date: Tue, 19 Jul 2016 09:26:21 +0200
+Subject: cifs: fix crash due to race in hmac(md5) handling
+
+From: Rabin Vincent <rabinv@axis.com>
+
+commit bd975d1eead2558b76e1079e861eacf1f678b73b upstream.
+
+The secmech hmac(md5) structures are present in the TCP_Server_Info
+struct and can be shared among multiple CIFS sessions. However, the
+server mutex is not currently held when these structures are allocated
+and used, which can lead to a kernel crashes, as in the scenario below:
+
+mount.cifs(8) #1 mount.cifs(8) #2
+
+Is secmech.sdeschmaccmd5 allocated?
+// false
+
+ Is secmech.sdeschmaccmd5 allocated?
+ // false
+
+secmech.hmacmd = crypto_alloc_shash..
+secmech.sdeschmaccmd5 = kzalloc..
+sdeschmaccmd5->shash.tfm = &secmec.hmacmd;
+
+ secmech.sdeschmaccmd5 = kzalloc
+ // sdeschmaccmd5->shash.tfm
+ // not yet assigned
+
+crypto_shash_update()
+ deref NULL sdeschmaccmd5->shash.tfm
+
+ Unable to handle kernel paging request at virtual address 00000030
+ epc : 8027ba34 crypto_shash_update+0x38/0x158
+ ra : 8020f2e8 setup_ntlmv2_rsp+0x4bc/0xa84
+ Call Trace:
+ crypto_shash_update+0x38/0x158
+ setup_ntlmv2_rsp+0x4bc/0xa84
+ build_ntlmssp_auth_blob+0xbc/0x34c
+ sess_auth_rawntlmssp_authenticate+0xac/0x248
+ CIFS_SessSetup+0xf0/0x178
+ cifs_setup_session+0x4c/0x84
+ cifs_get_smb_ses+0x2c8/0x314
+ cifs_mount+0x38c/0x76c
+ cifs_do_mount+0x98/0x440
+ mount_fs+0x20/0xc0
+ vfs_kern_mount+0x58/0x138
+ do_mount+0x1e8/0xccc
+ SyS_mount+0x88/0xd4
+ syscall_common+0x30/0x54
+
+Fix this by locking the srv_mutex around the code which uses these
+hmac(md5) structures. All the other secmech algos already have similar
+locking.
+
+Fixes: 95dc8dd14e2e84cc ("Limit allocation of crypto mechanisms to dialect which requires")
+Signed-off-by: Rabin Vincent <rabinv@axis.com>
+Acked-by: Sachin Prabhu <sprabhu@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsencrypt.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -743,24 +743,26 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c
+
+ memcpy(ses->auth_key.response + baselen, tiblob, tilen);
+
++ mutex_lock(&ses->server->srv_mutex);
++
+ rc = crypto_hmacmd5_alloc(ses->server);
+ if (rc) {
+ cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
+- goto setup_ntlmv2_rsp_ret;
++ goto unlock;
+ }
+
+ /* calculate ntlmv2_hash */
+ rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
+- goto setup_ntlmv2_rsp_ret;
++ goto unlock;
+ }
+
+ /* calculate first part of the client response (CR1) */
+ rc = CalcNTLMv2_response(ses, ntlmv2_hash);
+ if (rc) {
+ cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
+- goto setup_ntlmv2_rsp_ret;
++ goto unlock;
+ }
+
+ /* now calculate the session key for NTLMv2 */
+@@ -769,13 +771,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
+ __func__);
+- goto setup_ntlmv2_rsp_ret;
++ goto unlock;
+ }
+
+ rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
+- goto setup_ntlmv2_rsp_ret;
++ goto unlock;
+ }
+
+ rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
+@@ -783,7 +785,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c
+ CIFS_HMAC_MD5_HASH_SIZE);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
+- goto setup_ntlmv2_rsp_ret;
++ goto unlock;
+ }
+
+ rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
+@@ -791,6 +793,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
+
++unlock:
++ mutex_unlock(&ses->server->srv_mutex);
+ setup_ntlmv2_rsp_ret:
+ kfree(tiblob);
+
--- /dev/null
+From b782fcc1cbeb7e336c0ed1f00004b2208f48ffe0 Mon Sep 17 00:00:00 2001
+From: Rabin Vincent <rabinv@axis.com>
+Date: Tue, 19 Jul 2016 09:25:45 +0200
+Subject: cifs: unbreak TCP session reuse
+
+From: Rabin Vincent <rabinv@axis.com>
+
+commit b782fcc1cbeb7e336c0ed1f00004b2208f48ffe0 upstream.
+
+adfeb3e0 ("cifs: Make echo interval tunable") added a comparison of
+vol->echo_interval to server->echo_interval as a criterium to
+match_server(), but:
+
+ (1) A default value is set for server->echo_interval but not for
+ vol->echo_interval, meaning these can never match if the echo_interval
+ option is not specified.
+
+ (2) vol->echo_interval is in seconds but server->echo_interval is in
+ jiffies, meaning these can never match even if the echo_interval option
+ is specified.
+
+This broke TCP session reuse since match_server() can never return 1.
+Fix it.
+
+Fixes: adfeb3e0 ("cifs: Make echo interval tunable")
+Signed-off-by: Rabin Vincent <rabinv@axis.com>
+Acked-by: Sachin Prabhu <sprabhu@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/connect.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -1228,6 +1228,8 @@ cifs_parse_mount_options(const char *mou
+ vol->ops = &smb1_operations;
+ vol->vals = &smb1_values;
+
++ vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
++
+ if (!mountdata)
+ goto cifs_parse_mount_err;
+
+@@ -2049,7 +2051,7 @@ static int match_server(struct TCP_Serve
+ if (!match_security(server, vol))
+ return 0;
+
+- if (server->echo_interval != vol->echo_interval)
++ if (server->echo_interval != vol->echo_interval * HZ)
+ return 0;
+
+ return 1;
--- /dev/null
+From a6b5058fafdf508904bbf16c29b24042cef3c496 Mon Sep 17 00:00:00 2001
+From: Aurelien Aptel <aaptel@suse.com>
+Date: Wed, 25 May 2016 19:59:09 +0200
+Subject: fs/cifs: make share unaccessible at root level mountable
+
+From: Aurelien Aptel <aaptel@suse.com>
+
+commit a6b5058fafdf508904bbf16c29b24042cef3c496 upstream.
+
+if, when mounting //HOST/share/sub/dir/foo we can query /sub/dir/foo but
+not any of the path components above:
+
+- store the /sub/dir/foo prefix in the cifs super_block info
+- in the superblock, set root dentry to the subpath dentry (instead of
+ the share root)
+- set a flag in the superblock to remember it
+- use prefixpath when building path from a dentry
+
+fixes bso#8950
+
+Signed-off-by: Aurelien Aptel <aaptel@suse.com>
+Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifs_fs_sb.h | 4 ++++
+ fs/cifs/cifsfs.c | 14 +++++++++++++-
+ fs/cifs/connect.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/cifs/dir.c | 20 ++++++++++++++++++--
+ fs/cifs/inode.c | 22 ++++++++++++++++++++--
+ 5 files changed, 104 insertions(+), 5 deletions(-)
+
+--- a/fs/cifs/cifs_fs_sb.h
++++ b/fs/cifs/cifs_fs_sb.h
+@@ -46,6 +46,9 @@
+ #define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */
+ #define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */
+ #define CIFS_MOUNT_MAP_SFM_CHR 0x800000 /* SFM/MAC mapping for illegal chars */
++#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
++ * root mountable
++ */
+
+ struct cifs_sb_info {
+ struct rb_root tlink_tree;
+@@ -67,5 +70,6 @@ struct cifs_sb_info {
+ struct backing_dev_info bdi;
+ struct delayed_work prune_tlinks;
+ struct rcu_head rcu;
++ char *prepath;
+ };
+ #endif /* _CIFS_FS_SB_H */
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -689,6 +689,14 @@ cifs_do_mount(struct file_system_type *f
+ goto out_cifs_sb;
+ }
+
++ if (volume_info->prepath) {
++ cifs_sb->prepath = kstrdup(volume_info->prepath, GFP_KERNEL);
++ if (cifs_sb->prepath == NULL) {
++ root = ERR_PTR(-ENOMEM);
++ goto out_cifs_sb;
++ }
++ }
++
+ cifs_setup_cifs_sb(volume_info, cifs_sb);
+
+ rc = cifs_mount(cifs_sb, volume_info);
+@@ -727,7 +735,11 @@ cifs_do_mount(struct file_system_type *f
+ sb->s_flags |= MS_ACTIVE;
+ }
+
+- root = cifs_get_root(volume_info, sb);
++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
++ root = dget(sb->s_root);
++ else
++ root = cifs_get_root(volume_info, sb);
++
+ if (IS_ERR(root))
+ goto out_super;
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -3483,6 +3483,44 @@ cifs_get_volume_info(char *mount_data, c
+ return volume_info;
+ }
+
++static int
++cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
++ unsigned int xid,
++ struct cifs_tcon *tcon,
++ struct cifs_sb_info *cifs_sb,
++ char *full_path)
++{
++ int rc;
++ char *s;
++ char sep, tmp;
++
++ sep = CIFS_DIR_SEP(cifs_sb);
++ s = full_path;
++
++ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
++ while (rc == 0) {
++ /* skip separators */
++ while (*s == sep)
++ s++;
++ if (!*s)
++ break;
++ /* next separator */
++ while (*s && *s != sep)
++ s++;
++
++ /*
++ * temporarily null-terminate the path at the end of
++ * the current component
++ */
++ tmp = *s;
++ *s = 0;
++ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
++ full_path);
++ *s = tmp;
++ }
++ return rc;
++}
++
+ int
+ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
+ {
+@@ -3620,6 +3658,16 @@ remote_path_check:
+ kfree(full_path);
+ goto mount_fail_check;
+ }
++
++ rc = cifs_are_all_path_components_accessible(server,
++ xid, tcon, cifs_sb,
++ full_path);
++ if (rc != 0) {
++ cifs_dbg(VFS, "cannot query dirs between root and final path, "
++ "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
++ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
++ rc = 0;
++ }
+ kfree(full_path);
+ }
+
+@@ -3889,6 +3937,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb
+
+ bdi_destroy(&cifs_sb->bdi);
+ kfree(cifs_sb->mountdata);
++ kfree(cifs_sb->prepath);
+ call_rcu(&cifs_sb->rcu, delayed_free);
+ }
+
+--- a/fs/cifs/dir.c
++++ b/fs/cifs/dir.c
+@@ -84,6 +84,7 @@ build_path_from_dentry(struct dentry *di
+ struct dentry *temp;
+ int namelen;
+ int dfsplen;
++ int pplen = 0;
+ char *full_path;
+ char dirsep;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+@@ -95,8 +96,12 @@ build_path_from_dentry(struct dentry *di
+ dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
+ else
+ dfsplen = 0;
++
++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
++ pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
++
+ cifs_bp_rename_retry:
+- namelen = dfsplen;
++ namelen = dfsplen + pplen;
+ seq = read_seqbegin(&rename_lock);
+ rcu_read_lock();
+ for (temp = direntry; !IS_ROOT(temp);) {
+@@ -137,7 +142,7 @@ cifs_bp_rename_retry:
+ }
+ }
+ rcu_read_unlock();
+- if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
++ if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) {
+ cifs_dbg(FYI, "did not end path lookup where expected. namelen=%ddfsplen=%d\n",
+ namelen, dfsplen);
+ /* presumably this is only possible if racing with a rename
+@@ -153,6 +158,17 @@ cifs_bp_rename_retry:
+ those safely to '/' if any are found in the middle of the prepath */
+ /* BB test paths to Windows with '/' in the midst of prepath */
+
++ if (pplen) {
++ int i;
++
++ cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
++ memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1);
++ full_path[dfsplen] = '\\';
++ for (i = 0; i < pplen-1; i++)
++ if (full_path[dfsplen+1+i] == '/')
++ full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb);
++ }
++
+ if (dfsplen) {
+ strncpy(full_path, tcon->treeName, dfsplen);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -1002,10 +1002,26 @@ struct inode *cifs_root_iget(struct supe
+ struct inode *inode = NULL;
+ long rc;
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
++ char *path = NULL;
++ int len;
++
++ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
++ && cifs_sb->prepath) {
++ len = strlen(cifs_sb->prepath);
++ path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
++ if (path == NULL)
++ return ERR_PTR(-ENOMEM);
++ path[0] = '/';
++ memcpy(path+1, cifs_sb->prepath, len);
++ } else {
++ path = kstrdup("", GFP_KERNEL);
++ if (path == NULL)
++ return ERR_PTR(-ENOMEM);
++ }
+
+ xid = get_xid();
+ if (tcon->unix_ext) {
+- rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
++ rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
+ /* some servers mistakenly claim POSIX support */
+ if (rc != -EOPNOTSUPP)
+ goto iget_no_retry;
+@@ -1013,7 +1029,8 @@ struct inode *cifs_root_iget(struct supe
+ tcon->unix_ext = false;
+ }
+
+- rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
++ convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
++ rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
+
+ iget_no_retry:
+ if (!inode) {
+@@ -1042,6 +1059,7 @@ iget_no_retry:
+ }
+
+ out:
++ kfree(path);
+ /* can not call macro free_xid here since in a void func
+ * TODO: This is no longer true
+ */
--- /dev/null
+From 4b44f2d18a330565227a7348844493c59366171e Mon Sep 17 00:00:00 2001
+From: Stephan Mueller <smueller@chronox.de>
+Date: Mon, 2 May 2016 02:14:34 -0400
+Subject: random: add interrupt callback to VMBus IRQ handler
+
+From: Stephan Mueller <smueller@chronox.de>
+
+commit 4b44f2d18a330565227a7348844493c59366171e upstream.
+
+The Hyper-V Linux Integration Services use the VMBus implementation for
+communication with the Hypervisor. VMBus registers its own interrupt
+handler that completely bypasses the common Linux interrupt handling.
+This implies that the interrupt entropy collector is not triggered.
+
+This patch adds the interrupt entropy collection callback into the VMBus
+interrupt handler function.
+
+Signed-off-by: Stephan Mueller <stephan.mueller@atsec.com>
+Signed-off-by: Stephan Mueller <smueller@chronox.de>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/random.c | 1 +
+ drivers/hv/vmbus_drv.c | 3 +++
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -949,6 +949,7 @@ void add_interrupt_randomness(int irq, i
+ /* award one bit for the contents of the fast pool */
+ credit_entropy_bits(r, credit + 1);
+ }
++EXPORT_SYMBOL_GPL(add_interrupt_randomness);
+
+ #ifdef CONFIG_BLOCK
+ void add_disk_randomness(struct gendisk *disk)
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -42,6 +42,7 @@
+ #include <linux/screen_info.h>
+ #include <linux/kdebug.h>
+ #include <linux/efi.h>
++#include <linux/random.h>
+ #include "hyperv_vmbus.h"
+
+ static struct acpi_device *hv_acpi_dev;
+@@ -806,6 +807,8 @@ static void vmbus_isr(void)
+ else
+ tasklet_schedule(hv_context.msg_dpc[cpu]);
+ }
++
++ add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
+ }
+
+
--- /dev/null
+From 3371f3da08cff4b75c1f2dce742d460539d6566d Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sun, 12 Jun 2016 18:11:51 -0400
+Subject: random: initialize the non-blocking pool via add_hwgenerator_randomness()
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 3371f3da08cff4b75c1f2dce742d460539d6566d upstream.
+
+If we have a hardware RNG and are using the in-kernel rngd, we should
+use this to initialize the non-blocking pool so that getrandom(2)
+doesn't block unnecessarily.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/random.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1853,12 +1853,18 @@ void add_hwgenerator_randomness(const ch
+ {
+ struct entropy_store *poolp = &input_pool;
+
+- /* Suspend writing if we're above the trickle threshold.
+- * We'll be woken up again once below random_write_wakeup_thresh,
+- * or when the calling thread is about to terminate.
+- */
+- wait_event_interruptible(random_write_wait, kthread_should_stop() ||
++ if (unlikely(nonblocking_pool.initialized == 0))
++ poolp = &nonblocking_pool;
++ else {
++ /* Suspend writing if we're above the trickle
++ * threshold. We'll be woken up again once below
++ * random_write_wakeup_thresh, or when the calling
++ * thread is about to terminate.
++ */
++ wait_event_interruptible(random_write_wait,
++ kthread_should_stop() ||
+ ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
++ }
+ mix_pool_bytes(poolp, buffer, count);
+ credit_entropy_bits(poolp, entropy);
+ }
--- /dev/null
+From 9b4d008787f864f17d008c9c15bbe8a0f7e2fc24 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Mon, 13 Jun 2016 10:10:51 -0400
+Subject: random: print a warning for the first ten uninitialized random users
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 9b4d008787f864f17d008c9c15bbe8a0f7e2fc24 upstream.
+
+Since systemd is consistently using /dev/urandom before it is
+initialized, we can't see the other potentially dangerous users of
+/dev/urandom immediately after boot. So print the first ten such
+complaints instead.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/random.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1462,12 +1462,16 @@ random_read(struct file *file, char __us
+ static ssize_t
+ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
++ static int maxwarn = 10;
+ int ret;
+
+- if (unlikely(nonblocking_pool.initialized == 0))
+- printk_once(KERN_NOTICE "random: %s urandom read "
+- "with %d bits of entropy available\n",
+- current->comm, nonblocking_pool.entropy_total);
++ if (unlikely(nonblocking_pool.initialized == 0) &&
++ maxwarn > 0) {
++ maxwarn--;
++ printk(KERN_NOTICE "random: %s: uninitialized urandom read "
++ "(%zd bytes read, %d bits of entropy available)\n",
++ current->comm, nbytes, nonblocking_pool.entropy_total);
++ }
+
+ nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
+ ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
--- /dev/null
+From b1132deac01c2332d234fa821a70022796b79182 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers3@gmail.com>
+Date: Wed, 4 May 2016 21:08:39 -0400
+Subject: random: properly align get_random_int_hash
+
+From: Eric Biggers <ebiggers3@gmail.com>
+
+commit b1132deac01c2332d234fa821a70022796b79182 upstream.
+
+get_random_long() reads from the get_random_int_hash array using an
+unsigned long pointer. For this code to be guaranteed correct on all
+architectures, the array must be aligned to an unsigned long boundary.
+
+Signed-off-by: Eric Biggers <ebiggers3@gmail.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/random.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1775,13 +1775,15 @@ int random_int_secret_init(void)
+ return 0;
+ }
+
++static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
++ __aligned(sizeof(unsigned long));
++
+ /*
+ * Get a random word for internal kernel use only. Similar to urandom but
+ * with the goal of minimal entropy pool depletion. As a result, the random
+ * value is not cryptographically secure but for several uses the cost of
+ * depleting entropy is too high
+ */
+-static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
+ unsigned int get_random_int(void)
+ {
+ __u32 *hash;
arc-mm-don-t-loose-pte_special-in-pte_modify.patch
arc-dma-fix-address-translation-in-arc_dma_free.patch
jbd2-make-journal-y2038-safe.patch
+fs-cifs-make-share-unaccessible-at-root-level-mountable.patch
+cifs-check-for-existing-directory-when-opening-file-with-o_creat.patch
+cifs-unbreak-tcp-session-reuse.patch
+cifs-fix-crash-due-to-race-in-hmac-md5-handling.patch
+cifs-fix-a-possible-invalid-memory-access-in-smb2_query_symlink.patch
+random-add-interrupt-callback-to-vmbus-irq-handler.patch
+random-properly-align-get_random_int_hash.patch
+random-initialize-the-non-blocking-pool-via-add_hwgenerator_randomness.patch
+random-print-a-warning-for-the-first-ten-uninitialized-random-users.patch
+cachefiles-fix-race-between-inactivating-and-culling-a-cache-object.patch