From: Greg Kroah-Hartman Date: Wed, 4 Jan 2017 14:00:19 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.9.1~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ed16bf057f0a7bc194f46e8542bafd80af2858c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: arm-xen-use-alloc_percpu-rather-than-__alloc_percpu.patch cifs-decrease-verbosity-of-ioctl-call.patch cifs-fix-a-possible-double-locking-of-mutex-during-reconnect.patch cifs-fix-a-possible-memory-corruption-during-reconnect.patch cifs-fix-a-possible-memory-corruption-in-push-locks.patch cifs-fix-missing-nls-unload-in-smb2_reconnect.patch cifs-fix-smbencrypt-to-stop-pointing-a-scatterlist-at-the-stack.patch kernel-debug-debug_core.c-more-properly-delay-for-secondary-cpus.patch kernel-watchdog-use-nmi-registers-snapshot-in-hardlockup-handler.patch tpm-xen-remove-bogus-tpm_chip_unregister.patch watchdog-mei_wdt-request-stop-on-reboot-to-prevent-false-positive-event.patch watchdog-qcom-fix-kernel-panic-due-to-external-abort-on-non-linefetch.patch xen-gntdev-use-vm_mixedmap-instead-of-vm_io-to-avoid-numa-balancing.patch xfs-fix-up-xfs_swap_extent_forks-inline-extent-handling.patch xfs-set-agi-buffer-type-in-xlog_recover_clear_agi_bucket.patch --- diff --git a/queue-4.9/arm-xen-use-alloc_percpu-rather-than-__alloc_percpu.patch b/queue-4.9/arm-xen-use-alloc_percpu-rather-than-__alloc_percpu.patch new file mode 100644 index 00000000000..0178345939a --- /dev/null +++ b/queue-4.9/arm-xen-use-alloc_percpu-rather-than-__alloc_percpu.patch @@ -0,0 +1,108 @@ +From 24d5373dda7c00a438d26016bce140299fae675e Mon Sep 17 00:00:00 2001 +From: Julien Grall +Date: Wed, 7 Dec 2016 12:24:40 +0000 +Subject: arm/xen: Use alloc_percpu rather than __alloc_percpu + +From: Julien Grall + +commit 24d5373dda7c00a438d26016bce140299fae675e upstream. + +The function xen_guest_init is using __alloc_percpu with an alignment +which are not power of two. + +However, the percpu allocator never supported alignments which are not power +of two and has always behaved incorectly in thise case. + +Commit 3ca45a4 "percpu: ensure requested alignment is power of two" +introduced a check which trigger a warning [1] when booting linux-next +on Xen. But in reality this bug was always present. + +This can be fixed by replacing the call to __alloc_percpu with +alloc_percpu. The latter will use an alignment which are a power of two. + +[1] + +[ 0.023921] illegal size (48) or align (48) for percpu allocation +[ 0.024167] ------------[ cut here ]------------ +[ 0.024344] WARNING: CPU: 0 PID: 1 at linux/mm/percpu.c:892 pcpu_alloc+0x88/0x6c0 +[ 0.024584] Modules linked in: +[ 0.024708] +[ 0.024804] CPU: 0 PID: 1 Comm: swapper/0 Not tainted +4.9.0-rc7-next-20161128 #473 +[ 0.025012] Hardware name: Foundation-v8A (DT) +[ 0.025162] task: ffff80003d870000 task.stack: ffff80003d844000 +[ 0.025351] PC is at pcpu_alloc+0x88/0x6c0 +[ 0.025490] LR is at pcpu_alloc+0x88/0x6c0 +[ 0.025624] pc : [] lr : [] +pstate: 60000045 +[ 0.025830] sp : ffff80003d847cd0 +[ 0.025946] x29: ffff80003d847cd0 x28: 0000000000000000 +[ 0.026147] x27: 0000000000000000 x26: 0000000000000000 +[ 0.026348] x25: 0000000000000000 x24: 0000000000000000 +[ 0.026549] x23: 0000000000000000 x22: 00000000024000c0 +[ 0.026752] x21: ffff000008e97000 x20: 0000000000000000 +[ 0.026953] x19: 0000000000000030 x18: 0000000000000010 +[ 0.027155] x17: 0000000000000a3f x16: 00000000deadbeef +[ 0.027357] x15: 0000000000000006 x14: ffff000088f79c3f +[ 0.027573] x13: ffff000008f79c4d x12: 0000000000000041 +[ 0.027782] x11: 0000000000000006 x10: 0000000000000042 +[ 0.027995] x9 : ffff80003d847a40 x8 : 6f697461636f6c6c +[ 0.028208] x7 : 6120757063726570 x6 : ffff000008f79c84 +[ 0.028419] x5 : 0000000000000005 x4 : 0000000000000000 +[ 0.028628] x3 : 0000000000000000 x2 : 000000000000017f +[ 0.028840] x1 : ffff80003d870000 x0 : 0000000000000035 +[ 0.029056] +[ 0.029152] ---[ end trace 0000000000000000 ]--- +[ 0.029297] Call trace: +[ 0.029403] Exception stack(0xffff80003d847b00 to + 0xffff80003d847c30) +[ 0.029621] 7b00: 0000000000000030 0001000000000000 +ffff80003d847cd0 ffff00000818e678 +[ 0.029901] 7b20: 0000000000000002 0000000000000004 +ffff000008f7c060 0000000000000035 +[ 0.030153] 7b40: ffff000008f79000 ffff000008c4cd88 +ffff80003d847bf0 ffff000008101778 +[ 0.030402] 7b60: 0000000000000030 0000000000000000 +ffff000008e97000 00000000024000c0 +[ 0.030647] 7b80: 0000000000000000 0000000000000000 +0000000000000000 0000000000000000 +[ 0.030895] 7ba0: 0000000000000035 ffff80003d870000 +000000000000017f 0000000000000000 +[ 0.031144] 7bc0: 0000000000000000 0000000000000005 +ffff000008f79c84 6120757063726570 +[ 0.031394] 7be0: 6f697461636f6c6c ffff80003d847a40 +0000000000000042 0000000000000006 +[ 0.031643] 7c00: 0000000000000041 ffff000008f79c4d +ffff000088f79c3f 0000000000000006 +[ 0.031877] 7c20: 00000000deadbeef 0000000000000a3f +[ 0.032051] [] pcpu_alloc+0x88/0x6c0 +[ 0.032229] [] __alloc_percpu+0x18/0x20 +[ 0.032409] [] xen_guest_init+0x174/0x2f4 +[ 0.032591] [] do_one_initcall+0x38/0x130 +[ 0.032783] [] kernel_init_freeable+0xe0/0x248 +[ 0.032995] [] kernel_init+0x10/0x100 +[ 0.033172] [] ret_from_fork+0x10/0x50 + +Reported-by: Wei Chen +Link: https://lkml.org/lkml/2016/11/28/669 +Signed-off-by: Julien Grall +Signed-off-by: Stefano Stabellini +Reviewed-by: Stefano Stabellini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/xen/enlighten.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/arm/xen/enlighten.c ++++ b/arch/arm/xen/enlighten.c +@@ -372,8 +372,7 @@ static int __init xen_guest_init(void) + * for secondary CPUs as they are brought up. + * For uniformity we use VCPUOP_register_vcpu_info even on cpu0. + */ +- xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info), +- sizeof(struct vcpu_info)); ++ xen_vcpu_info = alloc_percpu(struct vcpu_info); + if (xen_vcpu_info == NULL) + return -ENOMEM; + diff --git a/queue-4.9/cifs-decrease-verbosity-of-ioctl-call.patch b/queue-4.9/cifs-decrease-verbosity-of-ioctl-call.patch new file mode 100644 index 00000000000..7641b823256 --- /dev/null +++ b/queue-4.9/cifs-decrease-verbosity-of-ioctl-call.patch @@ -0,0 +1,29 @@ +From b0a752b5ce76bd1d8b733a53757c3263511dcb69 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Wed, 16 Nov 2016 15:17:15 -0800 +Subject: CIFS: Decrease verbosity of ioctl call + +From: Pavel Shilovsky + +commit b0a752b5ce76bd1d8b733a53757c3263511dcb69 upstream. + +Reviewed-by: Aurelien Aptel +Acked-by: Sachin Prabhu +Signed-off-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsi + xid = get_xid(); + + cifs_sb = CIFS_SB(inode->i_sb); +- cifs_dbg(VFS, "cifs ioctl 0x%x\n", command); ++ cifs_dbg(FYI, "cifs ioctl 0x%x\n", command); + switch (command) { + case FS_IOC_GETFLAGS: + if (pSMBFile == NULL) diff --git a/queue-4.9/cifs-fix-a-possible-double-locking-of-mutex-during-reconnect.patch b/queue-4.9/cifs-fix-a-possible-double-locking-of-mutex-during-reconnect.patch new file mode 100644 index 00000000000..521bca11faa --- /dev/null +++ b/queue-4.9/cifs-fix-a-possible-double-locking-of-mutex-during-reconnect.patch @@ -0,0 +1,126 @@ +From 96a988ffeb90dba33a71c3826086fe67c897a183 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Tue, 29 Nov 2016 11:31:23 -0800 +Subject: CIFS: Fix a possible double locking of mutex during reconnect + +From: Pavel Shilovsky + +commit 96a988ffeb90dba33a71c3826086fe67c897a183 upstream. + +With the current code it is possible to lock a mutex twice when +a subsequent reconnects are triggered. On the 1st reconnect we +reconnect sessions and tcons and then persistent file handles. +If the 2nd reconnect happens during the reconnecting of persistent +file handles then the following sequence of calls is observed: + +cifs_reopen_file -> SMB2_open -> small_smb2_init -> smb2_reconnect +-> cifs_reopen_persistent_file_handles -> cifs_reopen_file (again!). + +So, we are trying to acquire the same cfile->fh_mutex twice which +is wrong. Fix this by moving reconnecting of persistent handles to +the delayed work (smb2_reconnect_server) and submitting this work +every time we reconnect tcon in SMB2 commands handling codepath. + +This can also lead to corruption of a temporary file list in +cifs_reopen_persistent_file_handles() because we can recursively +call this function twice. + +Signed-off-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifsglob.h | 1 + + fs/cifs/file.c | 8 +++++++- + fs/cifs/smb2pdu.c | 14 +++++++++----- + fs/cifs/smb2pdu.h | 2 ++ + 4 files changed, 19 insertions(+), 6 deletions(-) + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -925,6 +925,7 @@ struct cifs_tcon { + bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ + bool broken_sparse_sup; /* if server or share does not support sparse */ + bool need_reconnect:1; /* connection reset, tid now invalid */ ++ bool need_reopen_files:1; /* need to reopen tcon file handles */ + bool use_resilient:1; /* use resilient instead of durable handles */ + bool use_persistent:1; /* use persistent instead of durable handles */ + #ifdef CONFIG_CIFS_SMB2 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -777,6 +777,11 @@ cifs_reopen_persistent_handles(struct ci + struct list_head *tmp1; + struct list_head tmp_list; + ++ if (!tcon->use_persistent || !tcon->need_reopen_files) ++ return; ++ ++ tcon->need_reopen_files = false; ++ + cifs_dbg(FYI, "Reopen persistent handles"); + INIT_LIST_HEAD(&tmp_list); + +@@ -793,7 +798,8 @@ cifs_reopen_persistent_handles(struct ci + + list_for_each_safe(tmp, tmp1, &tmp_list) { + open_file = list_entry(tmp, struct cifsFileInfo, rlist); +- cifs_reopen_file(open_file, false /* do not flush */); ++ if (cifs_reopen_file(open_file, false /* do not flush */)) ++ tcon->need_reopen_files = true; + list_del_init(&open_file->rlist); + cifsFileInfo_put(open_file); + } +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -250,16 +250,19 @@ smb2_reconnect(__le16 smb2_command, stru + } + + cifs_mark_open_files_invalid(tcon); ++ if (tcon->use_persistent) ++ tcon->need_reopen_files = true; + + rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage); + mutex_unlock(&tcon->ses->session_mutex); + +- if (tcon->use_persistent) +- cifs_reopen_persistent_handles(tcon); +- + cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); + if (rc) + goto out; ++ ++ if (smb2_command != SMB2_INTERNAL_CMD) ++ queue_delayed_work(cifsiod_wq, &server->reconnect, 0); ++ + atomic_inc(&tconInfoReconnectCount); + out: + /* +@@ -1990,7 +1993,7 @@ void smb2_reconnect_server(struct work_s + spin_lock(&cifs_tcp_ses_lock); + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { +- if (tcon->need_reconnect) { ++ if (tcon->need_reconnect || tcon->need_reopen_files) { + tcon->tc_count++; + list_add_tail(&tcon->rlist, &tmp_list); + tcon_exist = true; +@@ -2007,7 +2010,8 @@ void smb2_reconnect_server(struct work_s + spin_unlock(&cifs_tcp_ses_lock); + + list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { +- smb2_reconnect(SMB2_ECHO, tcon); ++ if (!smb2_reconnect(SMB2_INTERNAL_CMD, tcon)) ++ cifs_reopen_persistent_handles(tcon); + list_del_init(&tcon->rlist); + cifs_put_tcon(tcon); + } +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -80,6 +80,8 @@ + #define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE) + #define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE) + ++#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF) ++ + #define NUMBER_OF_SMB2_COMMANDS 0x0013 + + /* BB FIXME - analyze following length BB */ diff --git a/queue-4.9/cifs-fix-a-possible-memory-corruption-during-reconnect.patch b/queue-4.9/cifs-fix-a-possible-memory-corruption-during-reconnect.patch new file mode 100644 index 00000000000..94f2f71feda --- /dev/null +++ b/queue-4.9/cifs-fix-a-possible-memory-corruption-during-reconnect.patch @@ -0,0 +1,260 @@ +From 53e0e11efe9289535b060a51d4cf37c25e0d0f2b Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Fri, 4 Nov 2016 11:50:31 -0700 +Subject: CIFS: Fix a possible memory corruption during reconnect + +From: Pavel Shilovsky + +commit 53e0e11efe9289535b060a51d4cf37c25e0d0f2b upstream. + +We can not unlock/lock cifs_tcp_ses_lock while walking through ses +and tcon lists because it can corrupt list iterator pointers and +a tcon structure can be released if we don't hold an extra reference. +Fix it by moving a reconnect process to a separate delayed work +and acquiring a reference to every tcon that needs to be reconnected. +Also do not send an echo request on newly established connections. + +Signed-off-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifsglob.h | 3 ++ + fs/cifs/cifsproto.h | 3 ++ + fs/cifs/connect.c | 34 ++++++++++++++++++----- + fs/cifs/smb2pdu.c | 75 +++++++++++++++++++++++++++++++++++----------------- + fs/cifs/smb2proto.h | 1 + 5 files changed, 85 insertions(+), 31 deletions(-) + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -646,6 +646,8 @@ struct TCP_Server_Info { + unsigned int max_read; + unsigned int max_write; + __u8 preauth_hash[512]; ++ struct delayed_work reconnect; /* reconnect workqueue job */ ++ struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ + #endif /* CONFIG_CIFS_SMB2 */ + unsigned long echo_interval; + }; +@@ -849,6 +851,7 @@ cap_unix(struct cifs_ses *ses) + struct cifs_tcon { + struct list_head tcon_list; + int tc_count; ++ struct list_head rlist; /* reconnect list */ + struct list_head openFileList; + spinlock_t open_file_lock; /* protects list above */ + struct cifs_ses *ses; /* pointer to session associated with */ +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -206,6 +206,9 @@ extern void cifs_add_pending_open_locked + struct tcon_link *tlink, + struct cifs_pending_open *open); + extern void cifs_del_pending_open(struct cifs_pending_open *open); ++extern void cifs_put_tcp_session(struct TCP_Server_Info *server, ++ int from_reconnect); ++extern void cifs_put_tcon(struct cifs_tcon *tcon); + + #if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) + extern void cifs_dfs_release_automount_timer(void); +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -52,6 +52,9 @@ + #include "nterr.h" + #include "rfc1002pdu.h" + #include "fscache.h" ++#ifdef CONFIG_CIFS_SMB2 ++#include "smb2proto.h" ++#endif + + #define CIFS_PORT 445 + #define RFC1001_PORT 139 +@@ -2100,8 +2103,8 @@ cifs_find_tcp_session(struct smb_vol *vo + return NULL; + } + +-static void +-cifs_put_tcp_session(struct TCP_Server_Info *server) ++void ++cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) + { + struct task_struct *task; + +@@ -2118,6 +2121,19 @@ cifs_put_tcp_session(struct TCP_Server_I + + cancel_delayed_work_sync(&server->echo); + ++#ifdef CONFIG_CIFS_SMB2 ++ if (from_reconnect) ++ /* ++ * Avoid deadlock here: reconnect work calls ++ * cifs_put_tcp_session() at its end. Need to be sure ++ * that reconnect work does nothing with server pointer after ++ * that step. ++ */ ++ cancel_delayed_work(&server->reconnect); ++ else ++ cancel_delayed_work_sync(&server->reconnect); ++#endif ++ + spin_lock(&GlobalMid_Lock); + server->tcpStatus = CifsExiting; + spin_unlock(&GlobalMid_Lock); +@@ -2182,6 +2198,10 @@ cifs_get_tcp_session(struct smb_vol *vol + INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); + INIT_LIST_HEAD(&tcp_ses->smb_ses_list); + INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); ++#ifdef CONFIG_CIFS_SMB2 ++ INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); ++ mutex_init(&tcp_ses->reconnect_mutex); ++#endif + memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr, + sizeof(tcp_ses->srcaddr)); + memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, +@@ -2340,7 +2360,7 @@ cifs_put_smb_ses(struct cifs_ses *ses) + spin_unlock(&cifs_tcp_ses_lock); + + sesInfoFree(ses); +- cifs_put_tcp_session(server); ++ cifs_put_tcp_session(server, 0); + } + + #ifdef CONFIG_KEYS +@@ -2514,7 +2534,7 @@ cifs_get_smb_ses(struct TCP_Server_Info + mutex_unlock(&ses->session_mutex); + + /* existing SMB ses has a server reference already */ +- cifs_put_tcp_session(server); ++ cifs_put_tcp_session(server, 0); + free_xid(xid); + return ses; + } +@@ -2604,7 +2624,7 @@ cifs_find_tcon(struct cifs_ses *ses, con + return NULL; + } + +-static void ++void + cifs_put_tcon(struct cifs_tcon *tcon) + { + unsigned int xid; +@@ -3792,7 +3812,7 @@ mount_fail_check: + else if (ses) + cifs_put_smb_ses(ses); + else +- cifs_put_tcp_session(server); ++ cifs_put_tcp_session(server, 0); + bdi_destroy(&cifs_sb->bdi); + } + +@@ -4103,7 +4123,7 @@ cifs_construct_tcon(struct cifs_sb_info + ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info); + if (IS_ERR(ses)) { + tcon = (struct cifs_tcon *)ses; +- cifs_put_tcp_session(master_tcon->ses->server); ++ cifs_put_tcp_session(master_tcon->ses->server, 0); + goto out; + } + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1972,6 +1972,54 @@ smb2_echo_callback(struct mid_q_entry *m + add_credits(server, credits_received, CIFS_ECHO_OP); + } + ++void smb2_reconnect_server(struct work_struct *work) ++{ ++ struct TCP_Server_Info *server = container_of(work, ++ struct TCP_Server_Info, reconnect.work); ++ struct cifs_ses *ses; ++ struct cifs_tcon *tcon, *tcon2; ++ struct list_head tmp_list; ++ int tcon_exist = false; ++ ++ /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ ++ mutex_lock(&server->reconnect_mutex); ++ ++ INIT_LIST_HEAD(&tmp_list); ++ cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n"); ++ ++ spin_lock(&cifs_tcp_ses_lock); ++ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { ++ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { ++ if (tcon->need_reconnect) { ++ tcon->tc_count++; ++ list_add_tail(&tcon->rlist, &tmp_list); ++ tcon_exist = true; ++ } ++ } ++ } ++ /* ++ * Get the reference to server struct to be sure that the last call of ++ * cifs_put_tcon() in the loop below won't release the server pointer. ++ */ ++ if (tcon_exist) ++ server->srv_count++; ++ ++ spin_unlock(&cifs_tcp_ses_lock); ++ ++ list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { ++ smb2_reconnect(SMB2_ECHO, tcon); ++ list_del_init(&tcon->rlist); ++ cifs_put_tcon(tcon); ++ } ++ ++ cifs_dbg(FYI, "Reconnecting tcons finished\n"); ++ mutex_unlock(&server->reconnect_mutex); ++ ++ /* now we can safely release srv struct */ ++ if (tcon_exist) ++ cifs_put_tcp_session(server, 1); ++} ++ + int + SMB2_echo(struct TCP_Server_Info *server) + { +@@ -1984,32 +2032,11 @@ SMB2_echo(struct TCP_Server_Info *server + cifs_dbg(FYI, "In echo request\n"); + + if (server->tcpStatus == CifsNeedNegotiate) { +- struct list_head *tmp, *tmp2; +- struct cifs_ses *ses; +- struct cifs_tcon *tcon; +- +- cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n"); +- spin_lock(&cifs_tcp_ses_lock); +- list_for_each(tmp, &server->smb_ses_list) { +- ses = list_entry(tmp, struct cifs_ses, smb_ses_list); +- list_for_each(tmp2, &ses->tcon_list) { +- tcon = list_entry(tmp2, struct cifs_tcon, +- tcon_list); +- /* add check for persistent handle reconnect */ +- if (tcon && tcon->need_reconnect) { +- spin_unlock(&cifs_tcp_ses_lock); +- rc = smb2_reconnect(SMB2_ECHO, tcon); +- spin_lock(&cifs_tcp_ses_lock); +- } +- } +- } +- spin_unlock(&cifs_tcp_ses_lock); ++ /* No need to send echo on newly established connections */ ++ queue_delayed_work(cifsiod_wq, &server->reconnect, 0); ++ return rc; + } + +- /* if no session, renegotiate failed above */ +- if (server->tcpStatus == CifsNeedNegotiate) +- return -EIO; +- + rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req); + if (rc) + return rc; +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -96,6 +96,7 @@ extern int smb2_open_file(const unsigned + extern int smb2_unlock_range(struct cifsFileInfo *cfile, + struct file_lock *flock, const unsigned int xid); + extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); ++extern void smb2_reconnect_server(struct work_struct *work); + + /* + * SMB2 Worker functions - most of protocol specific implementation details diff --git a/queue-4.9/cifs-fix-a-possible-memory-corruption-in-push-locks.patch b/queue-4.9/cifs-fix-a-possible-memory-corruption-in-push-locks.patch new file mode 100644 index 00000000000..aefc83cc59c --- /dev/null +++ b/queue-4.9/cifs-fix-a-possible-memory-corruption-in-push-locks.patch @@ -0,0 +1,30 @@ +From e3d240e9d505fc67f8f8735836df97a794bbd946 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Tue, 29 Nov 2016 16:14:43 -0800 +Subject: CIFS: Fix a possible memory corruption in push locks + +From: Pavel Shilovsky + +commit e3d240e9d505fc67f8f8735836df97a794bbd946 upstream. + +If maxBuf is not 0 but less than a size of SMB2 lock structure +we can end up with a memory corruption. + +Signed-off-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/cifs/smb2file.c ++++ b/fs/cifs/smb2file.c +@@ -260,7 +260,7 @@ smb2_push_mandatory_locks(struct cifsFil + * and check it for zero before using. + */ + max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf; +- if (!max_buf) { ++ if (max_buf < sizeof(struct smb2_lock_element)) { + free_xid(xid); + return -EINVAL; + } diff --git a/queue-4.9/cifs-fix-missing-nls-unload-in-smb2_reconnect.patch b/queue-4.9/cifs-fix-missing-nls-unload-in-smb2_reconnect.patch new file mode 100644 index 00000000000..bddcafa991c --- /dev/null +++ b/queue-4.9/cifs-fix-missing-nls-unload-in-smb2_reconnect.patch @@ -0,0 +1,28 @@ +From 4772c79599564bd08ee6682715a7d3516f67433f Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Tue, 29 Nov 2016 11:30:58 -0800 +Subject: CIFS: Fix missing nls unload in smb2_reconnect() + +From: Pavel Shilovsky + +commit 4772c79599564bd08ee6682715a7d3516f67433f upstream. + +Acked-by: Sachin Prabhu +Signed-off-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2pdu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -280,7 +280,7 @@ out: + case SMB2_CHANGE_NOTIFY: + case SMB2_QUERY_INFO: + case SMB2_SET_INFO: +- return -EAGAIN; ++ rc = -EAGAIN; + } + unload_nls(nls_codepage); + return rc; diff --git a/queue-4.9/cifs-fix-smbencrypt-to-stop-pointing-a-scatterlist-at-the-stack.patch b/queue-4.9/cifs-fix-smbencrypt-to-stop-pointing-a-scatterlist-at-the-stack.patch new file mode 100644 index 00000000000..5c5a00fe7d6 --- /dev/null +++ b/queue-4.9/cifs-fix-smbencrypt-to-stop-pointing-a-scatterlist-at-the-stack.patch @@ -0,0 +1,93 @@ +From 06deeec77a5a689cc94b21a8a91a76e42176685d Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Mon, 12 Dec 2016 12:54:37 -0800 +Subject: cifs: Fix smbencrypt() to stop pointing a scatterlist at the stack + +From: Andy Lutomirski + +commit 06deeec77a5a689cc94b21a8a91a76e42176685d upstream. + +smbencrypt() points a scatterlist to the stack, which is breaks if +CONFIG_VMAP_STACK=y. + +Fix it by switching to crypto_cipher_encrypt_one(). The new code +should be considerably faster as an added benefit. + +This code is nearly identical to some code that Eric Biggers +suggested. + +Reported-by: Eric Biggers +Signed-off-by: Andy Lutomirski +Acked-by: Jeff Layton +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smbencrypt.c | 40 ++++++++-------------------------------- + 1 file changed, 8 insertions(+), 32 deletions(-) + +--- a/fs/cifs/smbencrypt.c ++++ b/fs/cifs/smbencrypt.c +@@ -23,7 +23,7 @@ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +-#include ++#include + #include + #include + #include +@@ -69,46 +69,22 @@ str_to_key(unsigned char *str, unsigned + static int + smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) + { +- int rc; + unsigned char key2[8]; +- struct crypto_skcipher *tfm_des; +- struct scatterlist sgin, sgout; +- struct skcipher_request *req; ++ struct crypto_cipher *tfm_des; + + str_to_key(key, key2); + +- tfm_des = crypto_alloc_skcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC); ++ tfm_des = crypto_alloc_cipher("des", 0, 0); + if (IS_ERR(tfm_des)) { +- rc = PTR_ERR(tfm_des); + cifs_dbg(VFS, "could not allocate des crypto API\n"); +- goto smbhash_err; ++ return PTR_ERR(tfm_des); + } + +- req = skcipher_request_alloc(tfm_des, GFP_KERNEL); +- if (!req) { +- rc = -ENOMEM; +- cifs_dbg(VFS, "could not allocate des crypto API\n"); +- goto smbhash_free_skcipher; +- } +- +- crypto_skcipher_setkey(tfm_des, key2, 8); +- +- sg_init_one(&sgin, in, 8); +- sg_init_one(&sgout, out, 8); +- +- skcipher_request_set_callback(req, 0, NULL, NULL); +- skcipher_request_set_crypt(req, &sgin, &sgout, 8, NULL); +- +- rc = crypto_skcipher_encrypt(req); +- if (rc) +- cifs_dbg(VFS, "could not encrypt crypt key rc: %d\n", rc); +- +- skcipher_request_free(req); ++ crypto_cipher_setkey(tfm_des, key2, 8); ++ crypto_cipher_encrypt_one(tfm_des, out, in); ++ crypto_free_cipher(tfm_des); + +-smbhash_free_skcipher: +- crypto_free_skcipher(tfm_des); +-smbhash_err: +- return rc; ++ return 0; + } + + static int diff --git a/queue-4.9/kernel-debug-debug_core.c-more-properly-delay-for-secondary-cpus.patch b/queue-4.9/kernel-debug-debug_core.c-more-properly-delay-for-secondary-cpus.patch new file mode 100644 index 00000000000..06f7bba5c75 --- /dev/null +++ b/queue-4.9/kernel-debug-debug_core.c-more-properly-delay-for-secondary-cpus.patch @@ -0,0 +1,56 @@ +From 2d13bb6494c807bcf3f78af0e96c0b8615a94385 Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Wed, 14 Dec 2016 15:05:49 -0800 +Subject: kernel/debug/debug_core.c: more properly delay for secondary CPUs + +From: Douglas Anderson + +commit 2d13bb6494c807bcf3f78af0e96c0b8615a94385 upstream. + +We've got a delay loop waiting for secondary CPUs. That loop uses +loops_per_jiffy. However, loops_per_jiffy doesn't actually mean how +many tight loops make up a jiffy on all architectures. It is quite +common to see things like this in the boot log: + + Calibrating delay loop (skipped), value calculated using timer + frequency.. 48.00 BogoMIPS (lpj=24000) + +In my case I was seeing lots of cases where other CPUs timed out +entering the debugger only to print their stack crawls shortly after the +kdb> prompt was written. + +Elsewhere in kgdb we already use udelay(), so that should be safe enough +to use to implement our timeout. We'll delay 1 ms for 1000 times, which +should give us a full second of delay (just like the old code wanted) +but allow us to notice that we're done every 1 ms. + +[akpm@linux-foundation.org: simplifications, per Daniel] +Link: http://lkml.kernel.org/r/1477091361-2039-1-git-send-email-dianders@chromium.org +Signed-off-by: Douglas Anderson +Reviewed-by: Daniel Thompson +Cc: Jason Wessel +Cc: Brian Norris +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/debug/debug_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/kernel/debug/debug_core.c ++++ b/kernel/debug/debug_core.c +@@ -598,11 +598,11 @@ return_normal: + /* + * Wait for the other CPUs to be notified and be waiting for us: + */ +- time_left = loops_per_jiffy * HZ; ++ time_left = MSEC_PER_SEC; + while (kgdb_do_roundup && --time_left && + (atomic_read(&masters_in_kgdb) + atomic_read(&slaves_in_kgdb)) != + online_cpus) +- cpu_relax(); ++ udelay(1000); + if (!time_left) + pr_crit("Timed out waiting for secondary CPUs.\n"); + diff --git a/queue-4.9/kernel-watchdog-use-nmi-registers-snapshot-in-hardlockup-handler.patch b/queue-4.9/kernel-watchdog-use-nmi-registers-snapshot-in-hardlockup-handler.patch new file mode 100644 index 00000000000..4f015649b60 --- /dev/null +++ b/queue-4.9/kernel-watchdog-use-nmi-registers-snapshot-in-hardlockup-handler.patch @@ -0,0 +1,44 @@ +From 4d1f0fb096aedea7bb5489af93498a82e467c480 Mon Sep 17 00:00:00 2001 +From: Konstantin Khlebnikov +Date: Wed, 14 Dec 2016 15:04:04 -0800 +Subject: kernel/watchdog: use nmi registers snapshot in hardlockup handler + +From: Konstantin Khlebnikov + +commit 4d1f0fb096aedea7bb5489af93498a82e467c480 upstream. + +NMI handler doesn't call set_irq_regs(), it's set only by normal IRQ. +Thus get_irq_regs() returns NULL or stale registers snapshot with IP/SP +pointing to the code interrupted by IRQ which was interrupted by NMI. +NULL isn't a problem: in this case watchdog calls dump_stack() and +prints full stack trace including NMI. But if we're stuck in IRQ +handler then NMI watchlog will print stack trace without IRQ part at +all. + +This patch uses registers snapshot passed into NMI handler as arguments: +these registers point exactly to the instruction interrupted by NMI. + +Fixes: 55537871ef66 ("kernel/watchdog.c: perform all-CPU backtrace in case of hard lockup") +Link: http://lkml.kernel.org/r/146771764784.86724.6006627197118544150.stgit@buzz +Signed-off-by: Konstantin Khlebnikov +Cc: Jiri Kosina +Cc: Ulrich Obergfell +Cc: Aaron Tomlin +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/watchdog.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -344,7 +344,6 @@ static void watchdog_overflow_callback(s + */ + if (is_hardlockup()) { + int this_cpu = smp_processor_id(); +- struct pt_regs *regs = get_irq_regs(); + + /* only print hardlockups once */ + if (__this_cpu_read(hard_watchdog_warn) == true) diff --git a/queue-4.9/series b/queue-4.9/series index ed427ccc2c0..9372f6e9fb5 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -64,3 +64,18 @@ dm-rq-fix-a-race-condition-in-rq_completed.patch dm-raid-fix-discard-support-regression.patch dm-space-map-metadata-fix-struct-sm_metadata-leak-on-failed-create.patch asoc-intel-fix-crash-at-suspend-resume-without-card-registration.patch +cifs-fix-smbencrypt-to-stop-pointing-a-scatterlist-at-the-stack.patch +cifs-fix-a-possible-memory-corruption-during-reconnect.patch +cifs-fix-missing-nls-unload-in-smb2_reconnect.patch +cifs-fix-a-possible-double-locking-of-mutex-during-reconnect.patch +cifs-decrease-verbosity-of-ioctl-call.patch +cifs-fix-a-possible-memory-corruption-in-push-locks.patch +kernel-watchdog-use-nmi-registers-snapshot-in-hardlockup-handler.patch +watchdog-mei_wdt-request-stop-on-reboot-to-prevent-false-positive-event.patch +watchdog-qcom-fix-kernel-panic-due-to-external-abort-on-non-linefetch.patch +kernel-debug-debug_core.c-more-properly-delay-for-secondary-cpus.patch +tpm-xen-remove-bogus-tpm_chip_unregister.patch +xen-gntdev-use-vm_mixedmap-instead-of-vm_io-to-avoid-numa-balancing.patch +arm-xen-use-alloc_percpu-rather-than-__alloc_percpu.patch +xfs-fix-up-xfs_swap_extent_forks-inline-extent-handling.patch +xfs-set-agi-buffer-type-in-xlog_recover_clear_agi_bucket.patch diff --git a/queue-4.9/tpm-xen-remove-bogus-tpm_chip_unregister.patch b/queue-4.9/tpm-xen-remove-bogus-tpm_chip_unregister.patch new file mode 100644 index 00000000000..4c5ef4db879 --- /dev/null +++ b/queue-4.9/tpm-xen-remove-bogus-tpm_chip_unregister.patch @@ -0,0 +1,31 @@ +From 1f0f30e404b3d8f4597a2d9b77fba55452f8fd0e Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Wed, 26 Oct 2016 16:28:45 -0600 +Subject: tpm xen: Remove bogus tpm_chip_unregister + +From: Jason Gunthorpe + +commit 1f0f30e404b3d8f4597a2d9b77fba55452f8fd0e upstream. + +tpm_chip_unregister can only be called after tpm_chip_register. +devm manages the allocation so no unwind is needed here. + +Fixes: afb5abc262e96 ("tpm: two-phase chip management functions") +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/xen-tpmfront.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/char/tpm/xen-tpmfront.c ++++ b/drivers/char/tpm/xen-tpmfront.c +@@ -307,7 +307,6 @@ static int tpmfront_probe(struct xenbus_ + rv = setup_ring(dev, priv); + if (rv) { + chip = dev_get_drvdata(&dev->dev); +- tpm_chip_unregister(chip); + ring_free(priv); + return rv; + } diff --git a/queue-4.9/watchdog-mei_wdt-request-stop-on-reboot-to-prevent-false-positive-event.patch b/queue-4.9/watchdog-mei_wdt-request-stop-on-reboot-to-prevent-false-positive-event.patch new file mode 100644 index 00000000000..5edb54cb0a5 --- /dev/null +++ b/queue-4.9/watchdog-mei_wdt-request-stop-on-reboot-to-prevent-false-positive-event.patch @@ -0,0 +1,39 @@ +From 9eff1140a82db8c5520f76e51c21827b4af670b3 Mon Sep 17 00:00:00 2001 +From: Alexander Usyskin +Date: Tue, 8 Nov 2016 17:55:52 +0200 +Subject: watchdog: mei_wdt: request stop on reboot to prevent false positive event + +From: Alexander Usyskin + +commit 9eff1140a82db8c5520f76e51c21827b4af670b3 upstream. + +Systemd on reboot enables shutdown watchdog that leaves the watchdog +device open to ensure that even if power down process get stuck the +platform reboots nonetheless. +The iamt_wdt is an alarm-only watchdog and can't reboot system, but the +FW will generate an alarm event reboot was completed in time, as the +watchdog is not automatically disabled during power cycle. +So we should request stop watchdog on reboot to eliminate wrong alarm +from the FW. + +Signed-off-by: Alexander Usyskin +Signed-off-by: Tomas Winkler +Reviewed-by: Guenter Roeck +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/watchdog/mei_wdt.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/watchdog/mei_wdt.c ++++ b/drivers/watchdog/mei_wdt.c +@@ -389,6 +389,8 @@ static int mei_wdt_register(struct mei_w + wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT; + + watchdog_set_drvdata(&wdt->wdd, wdt); ++ watchdog_stop_on_reboot(&wdt->wdd); ++ + ret = watchdog_register_device(&wdt->wdd); + if (ret) { + dev_err(dev, "unable to register watchdog device = %d.\n", ret); diff --git a/queue-4.9/watchdog-qcom-fix-kernel-panic-due-to-external-abort-on-non-linefetch.patch b/queue-4.9/watchdog-qcom-fix-kernel-panic-due-to-external-abort-on-non-linefetch.patch new file mode 100644 index 00000000000..597c85a85bb --- /dev/null +++ b/queue-4.9/watchdog-qcom-fix-kernel-panic-due-to-external-abort-on-non-linefetch.patch @@ -0,0 +1,55 @@ +From f06f35c66fdbd5ac38901a3305ce763a0cd59375 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Mon, 14 Nov 2016 02:11:16 +0100 +Subject: watchdog: qcom: fix kernel panic due to external abort on non-linefetch + +From: Christian Lamparter + +commit f06f35c66fdbd5ac38901a3305ce763a0cd59375 upstream. + +This patch fixes a off-by-one in the "watchdog: qcom: add option for +standalone watchdog not in timer block" patch that causes the +following panic on boot: + +> Unhandled fault: external abort on non-linefetch (0x1008) at 0xc8874002 +> pgd = c0204000 +> [c8874002] *pgd=87806811, *pte=0b017653, *ppte=0b017453 +> Internal error: : 1008 [#1] SMP ARM +> CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.8.6 #0 +> Hardware name: Generic DT based system +> PC is at 0xc02222f4 +> LR is at 0x1 +> pc : [] lr : [<00000001>] psr: 00000113 +> sp : c782fc98 ip : 00000003 fp : 00000000 +> r10: 00000004 r9 : c782e000 r8 : c04ab98c +> r7 : 00000001 r6 : c8874002 r5 : c782fe00 r4 : 00000002 +> r3 : 00000000 r2 : c782fe00 r1 : 00100000 r0 : c8874002 +> Flags: nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none +> Control: 10c5387d Table: 8020406a DAC: 00000051 +> Process swapper/0 (pid: 1, stack limit = 0xc782e210) +> Stack: (0xc782fc98 to 0xc7830000) +> [...] + +The WDT_STS (status) needs to be translated via wdt_addr as well. + +fixes: f0d9d0f4b44a ("watchdog: qcom: add option for standalone watchdog not in timer block") +Signed-off-by: Christian Lamparter +Reviewed-by: Guenter Roeck +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/watchdog/qcom-wdt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/watchdog/qcom-wdt.c ++++ b/drivers/watchdog/qcom-wdt.c +@@ -209,7 +209,7 @@ static int qcom_wdt_probe(struct platfor + wdt->wdd.parent = &pdev->dev; + wdt->layout = regs; + +- if (readl(wdt->base + WDT_STS) & 1) ++ if (readl(wdt_addr(wdt, WDT_STS)) & 1) + wdt->wdd.bootstatus = WDIOF_CARDRESET; + + /* diff --git a/queue-4.9/xen-gntdev-use-vm_mixedmap-instead-of-vm_io-to-avoid-numa-balancing.patch b/queue-4.9/xen-gntdev-use-vm_mixedmap-instead-of-vm_io-to-avoid-numa-balancing.patch new file mode 100644 index 00000000000..115eb91d6e5 --- /dev/null +++ b/queue-4.9/xen-gntdev-use-vm_mixedmap-instead-of-vm_io-to-avoid-numa-balancing.patch @@ -0,0 +1,60 @@ +From 30faaafdfa0c754c91bac60f216c9f34a2bfdf7e Mon Sep 17 00:00:00 2001 +From: Boris Ostrovsky +Date: Mon, 21 Nov 2016 09:56:06 -0500 +Subject: xen/gntdev: Use VM_MIXEDMAP instead of VM_IO to avoid NUMA balancing + +From: Boris Ostrovsky + +commit 30faaafdfa0c754c91bac60f216c9f34a2bfdf7e upstream. + +Commit 9c17d96500f7 ("xen/gntdev: Grant maps should not be subject to +NUMA balancing") set VM_IO flag to prevent grant maps from being +subjected to NUMA balancing. + +It was discovered recently that this flag causes get_user_pages() to +always fail with -EFAULT. + +check_vma_flags +__get_user_pages +__get_user_pages_locked +__get_user_pages_unlocked +get_user_pages_fast +iov_iter_get_pages +dio_refill_pages +do_direct_IO +do_blockdev_direct_IO +do_blockdev_direct_IO +ext4_direct_IO_read +generic_file_read_iter +aio_run_iocb + +(which can happen if guest's vdisk has direct-io-safe option). + +To avoid this let's use VM_MIXEDMAP flag instead --- it prevents +NUMA balancing just as VM_IO does and has no effect on +check_vma_flags(). + + +Reported-by: Olaf Hering +Suggested-by: Hugh Dickins +Signed-off-by: Boris Ostrovsky +Acked-by: Hugh Dickins +Tested-by: Olaf Hering +Signed-off-by: Juergen Gross +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/xen/gntdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -1007,7 +1007,7 @@ static int gntdev_mmap(struct file *flip + + vma->vm_ops = &gntdev_vmops; + +- vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO; ++ vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_MIXEDMAP; + + if (use_ptemod) + vma->vm_flags |= VM_DONTCOPY; diff --git a/queue-4.9/xfs-fix-up-xfs_swap_extent_forks-inline-extent-handling.patch b/queue-4.9/xfs-fix-up-xfs_swap_extent_forks-inline-extent-handling.patch new file mode 100644 index 00000000000..1881de44e62 --- /dev/null +++ b/queue-4.9/xfs-fix-up-xfs_swap_extent_forks-inline-extent-handling.patch @@ -0,0 +1,94 @@ +From 4dfce57db6354603641132fac3c887614e3ebe81 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Tue, 8 Nov 2016 12:55:18 +1100 +Subject: xfs: fix up xfs_swap_extent_forks inline extent handling + +From: Eric Sandeen + +commit 4dfce57db6354603641132fac3c887614e3ebe81 upstream. + +There have been several reports over the years of NULL pointer +dereferences in xfs_trans_log_inode during xfs_fsr processes, +when the process is doing an fput and tearing down extents +on the temporary inode, something like: + +BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 +PID: 29439 TASK: ffff880550584fa0 CPU: 6 COMMAND: "xfs_fsr" + [exception RIP: xfs_trans_log_inode+0x10] + #9 [ffff8800a57bbbe0] xfs_bunmapi at ffffffffa037398e [xfs] +#10 [ffff8800a57bbce8] xfs_itruncate_extents at ffffffffa0391b29 [xfs] +#11 [ffff8800a57bbd88] xfs_inactive_truncate at ffffffffa0391d0c [xfs] +#12 [ffff8800a57bbdb8] xfs_inactive at ffffffffa0392508 [xfs] +#13 [ffff8800a57bbdd8] xfs_fs_evict_inode at ffffffffa035907e [xfs] +#14 [ffff8800a57bbe00] evict at ffffffff811e1b67 +#15 [ffff8800a57bbe28] iput at ffffffff811e23a5 +#16 [ffff8800a57bbe58] dentry_kill at ffffffff811dcfc8 +#17 [ffff8800a57bbe88] dput at ffffffff811dd06c +#18 [ffff8800a57bbea8] __fput at ffffffff811c823b +#19 [ffff8800a57bbef0] ____fput at ffffffff811c846e +#20 [ffff8800a57bbf00] task_work_run at ffffffff81093b27 +#21 [ffff8800a57bbf30] do_notify_resume at ffffffff81013b0c +#22 [ffff8800a57bbf50] int_signal at ffffffff8161405d + +As it turns out, this is because the i_itemp pointer, along +with the d_ops pointer, has been overwritten with zeros +when we tear down the extents during truncate. When the in-core +inode fork on the temporary inode used by xfs_fsr was originally +set up during the extent swap, we mistakenly looked at di_nextents +to determine whether all extents fit inline, but this misses extents +generated by speculative preallocation; we should be using if_bytes +instead. + +This mistake corrupts the in-memory inode, and code in +xfs_iext_remove_inline eventually gets bad inputs, causing +it to memmove and memset incorrect ranges; this became apparent +because the two values in ifp->if_u2.if_inline_ext[1] contained +what should have been in d_ops and i_itemp; they were memmoved due +to incorrect array indexing and then the original locations +were zeroed with memset, again due to an array overrun. + +Fix this by properly using i_df.if_bytes to determine the number +of extents, not di_nextents. + +Thanks to dchinner for looking at this with me and spotting the +root cause. + +Signed-off-by: Eric Sandeen +Reviewed-by: Brian Foster +Signed-off-by: Dave Chinner +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_bmap_util.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/fs/xfs/xfs_bmap_util.c ++++ b/fs/xfs/xfs_bmap_util.c +@@ -1792,6 +1792,7 @@ xfs_swap_extent_forks( + struct xfs_ifork tempifp, *ifp, *tifp; + int aforkblks = 0; + int taforkblks = 0; ++ xfs_extnum_t nextents; + __uint64_t tmp; + int error; + +@@ -1881,7 +1882,8 @@ xfs_swap_extent_forks( + * pointer. Otherwise it's already NULL or + * pointing to the extent. + */ +- if (ip->i_d.di_nextents <= XFS_INLINE_EXTS) { ++ nextents = ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ++ if (nextents <= XFS_INLINE_EXTS) { + ifp->if_u1.if_extents = + ifp->if_u2.if_inline_ext; + } +@@ -1900,7 +1902,8 @@ xfs_swap_extent_forks( + * pointer. Otherwise it's already NULL or + * pointing to the extent. + */ +- if (tip->i_d.di_nextents <= XFS_INLINE_EXTS) { ++ nextents = tip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ++ if (nextents <= XFS_INLINE_EXTS) { + tifp->if_u1.if_extents = + tifp->if_u2.if_inline_ext; + } diff --git a/queue-4.9/xfs-set-agi-buffer-type-in-xlog_recover_clear_agi_bucket.patch b/queue-4.9/xfs-set-agi-buffer-type-in-xlog_recover_clear_agi_bucket.patch new file mode 100644 index 00000000000..584a1239ab5 --- /dev/null +++ b/queue-4.9/xfs-set-agi-buffer-type-in-xlog_recover_clear_agi_bucket.patch @@ -0,0 +1,39 @@ +From 6b10b23ca94451fae153a5cc8d62fd721bec2019 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Mon, 5 Dec 2016 12:31:06 +1100 +Subject: xfs: set AGI buffer type in xlog_recover_clear_agi_bucket + +From: Eric Sandeen + +commit 6b10b23ca94451fae153a5cc8d62fd721bec2019 upstream. + +xlog_recover_clear_agi_bucket didn't set the +type to XFS_BLFT_AGI_BUF, so we got a warning during log +replay (or an ASSERT on a debug build). + + XFS (md0): Unknown buffer type 0! + XFS (md0): _xfs_buf_ioapply: no ops on block 0xaea8802/0x1 + +Fix this, as was done in f19b872b for 2 other locations +with the same problem. + +Signed-off-by: Eric Sandeen +Reviewed-by: Brian Foster +Reviewed-by: Christoph Hellwig +Signed-off-by: Dave Chinner +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_log_recover.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -4929,6 +4929,7 @@ xlog_recover_clear_agi_bucket( + agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); + offset = offsetof(xfs_agi_t, agi_unlinked) + + (sizeof(xfs_agino_t) * bucket); ++ xfs_trans_buf_set_type(tp, agibp, XFS_BLFT_AGI_BUF); + xfs_trans_log_buf(tp, agibp, offset, + (offset + sizeof(xfs_agino_t) - 1)); +