Patch "CIFS: Fix a possible memory corruption during reconnect" has been added to the 4.9-stable tree
This is a note to let you know that I've just added the patch titled
CIFS: Fix a possible memory corruption during reconnect
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
cifs-fix-a-possible-memory-corruption-during-reconnect.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
53e0e11efe9289535b060a51d4cf37c25e0d0f2bMon Sep 17 00:00:00 2001
From: Pavel Shilovsky <[email protected]>
Date: Fri, 4 Nov 2016 11:50:31 -0700
Subject: CIFS: Fix a possible memory corruption during reconnect
From: Pavel Shilovsky <[email protected]>
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.
--- 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(-)
fs/cifs/cifsglob.h +3 -0
@@ -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 */
fs/cifs/cifsproto.h +3 -0
@@ -206,6 +206,9 @@ extern void cifs_add_pending_open_lockedstruct 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 );
fs/cifs/connect.c +27 -7
@@ -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 *voreturn 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_Icancel_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 *volINIT_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_Infomutex_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, conreturn 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; }
fs/cifs/smb2pdu.c +51 -24
89 lines not on this page · raw message
fs/cifs/smb2proto.h +1 -0
@@ -96,6 +96,7 @@ extern int smb2_open_file(const unsignedextern 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
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/cifs-fix-missing-nls-unload-in-smb2_reconnect.patch queue-4.9/cifs-decrease-verbosity-of-ioctl-call.patch queue-4.9/cifs-fix-a-possible-double-locking-of-mutex-during-reconnect.patch queue-4.9/cifs-fix-a-possible-memory-corruption-in-push-locks.patch queue-4.9/cifs-fix-a-possible-memory-corruption-during-reconnect.patch