From: Greg Kroah-Hartman Date: Thu, 18 Aug 2016 09:37:43 +0000 (+0200) Subject: 4.7-stable patches X-Git-Tag: v3.14.77~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=730c41f7b343266b07ae661f5ab87ed9e78b9a94;p=thirdparty%2Fkernel%2Fstable-queue.git 4.7-stable patches added patches: cachefiles-fix-race-between-inactivating-and-culling-a-cache-object.patch cifs-check-for-existing-directory-when-opening-file-with-o_creat.patch cifs-fix-a-possible-invalid-memory-access-in-smb2_query_symlink.patch cifs-fix-crash-due-to-race-in-hmac-md5-handling.patch cifs-unbreak-tcp-session-reuse.patch fs-cifs-make-share-unaccessible-at-root-level-mountable.patch random-add-interrupt-callback-to-vmbus-irq-handler.patch random-initialize-the-non-blocking-pool-via-add_hwgenerator_randomness.patch random-print-a-warning-for-the-first-ten-uninitialized-random-users.patch random-properly-align-get_random_int_hash.patch --- diff --git a/queue-4.7/cachefiles-fix-race-between-inactivating-and-culling-a-cache-object.patch b/queue-4.7/cachefiles-fix-race-between-inactivating-and-culling-a-cache-object.patch new file mode 100644 index 00000000000..29258c73aee --- /dev/null +++ b/queue-4.7/cachefiles-fix-race-between-inactivating-and-culling-a-cache-object.patch @@ -0,0 +1,104 @@ +From db20a8925bc420eed033c5d91ff6afa74465e521 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 3 Aug 2016 17:57:39 +0100 +Subject: cachefiles: Fix race between inactivating and culling a cache object + +From: David Howells + +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: [] 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:[] 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: + [] cachefiles_drop_object+0x6b/0xf0 [cachefiles] + [] fscache_drop_object+0xd6/0x1e0 [fscache] + [] fscache_object_work_func+0xa5/0x200 [fscache] + [] process_one_work+0x17b/0x470 + [] worker_thread+0x126/0x410 + [] ? rescuer_thread+0x460/0x460 + [] kthread+0xcf/0xe0 + [] ? kthread_create_on_node+0x140/0x140 + [] ret_from_fork+0x58/0x90 + [] ? kthread_create_on_node+0x140/0x140 + +The oopsing code shows: + + callq 0xffffffff810af6a0 + 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 +Signed-off-by: David Howells +Reviewed-by: Jeff Layton +Reviewed-by: Steve Dickson +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } diff --git a/queue-4.7/cifs-check-for-existing-directory-when-opening-file-with-o_creat.patch b/queue-4.7/cifs-check-for-existing-directory-when-opening-file-with-o_creat.patch new file mode 100644 index 00000000000..5cc4089fa22 --- /dev/null +++ b/queue-4.7/cifs-check-for-existing-directory-when-opening-file-with-o_creat.patch @@ -0,0 +1,74 @@ +From 8d9535b6efd86e6c07da59f97e68f44efb7fe080 Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Thu, 7 Jul 2016 21:28:27 +0100 +Subject: cifs: Check for existing directory when opening file with O_CREAT + +From: Sachin Prabhu + +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 +Signed-off-by: Steve French +Reported-by: Xiaoli Feng +Signed-off-by: Greg Kroah-Hartman + +--- + 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 diff --git a/queue-4.7/cifs-fix-a-possible-invalid-memory-access-in-smb2_query_symlink.patch b/queue-4.7/cifs-fix-a-possible-invalid-memory-access-in-smb2_query_symlink.patch new file mode 100644 index 00000000000..da6ce98215f --- /dev/null +++ b/queue-4.7/cifs-fix-a-possible-invalid-memory-access-in-smb2_query_symlink.patch @@ -0,0 +1,81 @@ +From 7893242e2465aea6f2cbc2639da8fa5ce96e8cc2 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Sun, 24 Jul 2016 10:37:38 +0300 +Subject: CIFS: Fix a possible invalid memory access in smb2_query_symlink() + +From: Pavel Shilovsky + +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 +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-4.7/cifs-fix-crash-due-to-race-in-hmac-md5-handling.patch b/queue-4.7/cifs-fix-crash-due-to-race-in-hmac-md5-handling.patch new file mode 100644 index 00000000000..3e059b02b09 --- /dev/null +++ b/queue-4.7/cifs-fix-crash-due-to-race-in-hmac-md5-handling.patch @@ -0,0 +1,132 @@ +From bd975d1eead2558b76e1079e861eacf1f678b73b Mon Sep 17 00:00:00 2001 +From: Rabin Vincent +Date: Tue, 19 Jul 2016 09:26:21 +0200 +Subject: cifs: fix crash due to race in hmac(md5) handling + +From: Rabin Vincent + +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 +Acked-by: Sachin Prabhu +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-4.7/cifs-unbreak-tcp-session-reuse.patch b/queue-4.7/cifs-unbreak-tcp-session-reuse.patch new file mode 100644 index 00000000000..8becd75b2f9 --- /dev/null +++ b/queue-4.7/cifs-unbreak-tcp-session-reuse.patch @@ -0,0 +1,54 @@ +From b782fcc1cbeb7e336c0ed1f00004b2208f48ffe0 Mon Sep 17 00:00:00 2001 +From: Rabin Vincent +Date: Tue, 19 Jul 2016 09:25:45 +0200 +Subject: cifs: unbreak TCP session reuse + +From: Rabin Vincent + +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 +Acked-by: Sachin Prabhu +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.7/fs-cifs-make-share-unaccessible-at-root-level-mountable.patch b/queue-4.7/fs-cifs-make-share-unaccessible-at-root-level-mountable.patch new file mode 100644 index 00000000000..cf3403a6c32 --- /dev/null +++ b/queue-4.7/fs-cifs-make-share-unaccessible-at-root-level-mountable.patch @@ -0,0 +1,253 @@ +From a6b5058fafdf508904bbf16c29b24042cef3c496 Mon Sep 17 00:00:00 2001 +From: Aurelien Aptel +Date: Wed, 25 May 2016 19:59:09 +0200 +Subject: fs/cifs: make share unaccessible at root level mountable + +From: Aurelien Aptel + +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 +Reviewed-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + */ diff --git a/queue-4.7/random-add-interrupt-callback-to-vmbus-irq-handler.patch b/queue-4.7/random-add-interrupt-callback-to-vmbus-irq-handler.patch new file mode 100644 index 00000000000..100967d0787 --- /dev/null +++ b/queue-4.7/random-add-interrupt-callback-to-vmbus-irq-handler.patch @@ -0,0 +1,56 @@ +From 4b44f2d18a330565227a7348844493c59366171e Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Mon, 2 May 2016 02:14:34 -0400 +Subject: random: add interrupt callback to VMBus IRQ handler + +From: Stephan Mueller + +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 +Signed-off-by: Stephan Mueller +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + #include ++#include + #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); + } + + diff --git a/queue-4.7/random-initialize-the-non-blocking-pool-via-add_hwgenerator_randomness.patch b/queue-4.7/random-initialize-the-non-blocking-pool-via-add_hwgenerator_randomness.patch new file mode 100644 index 00000000000..59d29f92a16 --- /dev/null +++ b/queue-4.7/random-initialize-the-non-blocking-pool-via-add_hwgenerator_randomness.patch @@ -0,0 +1,46 @@ +From 3371f3da08cff4b75c1f2dce742d460539d6566d Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 12 Jun 2016 18:11:51 -0400 +Subject: random: initialize the non-blocking pool via add_hwgenerator_randomness() + +From: Theodore Ts'o + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } diff --git a/queue-4.7/random-print-a-warning-for-the-first-ten-uninitialized-random-users.patch b/queue-4.7/random-print-a-warning-for-the-first-ten-uninitialized-random-users.patch new file mode 100644 index 00000000000..e8a79acea8a --- /dev/null +++ b/queue-4.7/random-print-a-warning-for-the-first-ten-uninitialized-random-users.patch @@ -0,0 +1,44 @@ +From 9b4d008787f864f17d008c9c15bbe8a0f7e2fc24 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-4.7/random-properly-align-get_random_int_hash.patch b/queue-4.7/random-properly-align-get_random_int_hash.patch new file mode 100644 index 00000000000..d11e1a98fee --- /dev/null +++ b/queue-4.7/random-properly-align-get_random_int_hash.patch @@ -0,0 +1,40 @@ +From b1132deac01c2332d234fa821a70022796b79182 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 4 May 2016 21:08:39 -0400 +Subject: random: properly align get_random_int_hash + +From: Eric Biggers + +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 +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.7/series b/queue-4.7/series index 9d63e153555..b2e7897f8f7 100644 --- a/queue-4.7/series +++ b/queue-4.7/series @@ -72,3 +72,13 @@ remoteproc-fix-potential-race-condition-in-rproc_add.patch 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