cifs: fix panic in smb2_reconnect
diff mbox series

Message ID 20190603073138.25211-1-lsahlber@redhat.com
State New
Headers show
Series
  • cifs: fix panic in smb2_reconnect
Related show

Commit Message

Ronnie Sahlberg June 3, 2019, 7:31 a.m. UTC
RH Bugzilla: 1702264

We need to protect so that the call to smb2_reconnect() in
smb2_reconnect_server() does not end up freeing the session
because it can lead to a use after free and crash.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/smb2pdu.c | 3 +++
 1 file changed, 3 insertions(+)

Comments

Aurélien Aptel June 3, 2019, 10 a.m. UTC | #1
Ronnie Sahlberg <lsahlber@redhat.com> writes:
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index 565b60b62f4d..c4f3e2403b58 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -3116,6 +3116,7 @@ void smb2_reconnect_server(struct work_struct *work)

I would add a comment here. Something like:

    /* IPC has the same lifetime as its session and uses its
       refcount */

>  		if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
>  			list_add_tail(&ses->tcon_ipc->rlist, &tmp_list);
>  			tcon_exist = true;
> +			ses->ses_count++;
>  		}
>  	}
>  	/*
> @@ -3134,6 +3135,8 @@ void smb2_reconnect_server(struct work_struct *work)
>  		else
>  			resched = true;
>  		list_del_init(&tcon->rlist);
> +		if (tcon->ipc)
> +			cifs_put_smb_ses(tcon->ses);
>  		cifs_put_tcon(tcon);

Since cifs_put_tcon() is a noop on IPC this looks correct but I think an
putting it in an "else" would make the logic clearer.

Reviewed-by: Aurelien Aptel <aaptel@suse.com>

Patch
diff mbox series

diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 565b60b62f4d..c4f3e2403b58 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -3116,6 +3116,7 @@  void smb2_reconnect_server(struct work_struct *work)
 		if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
 			list_add_tail(&ses->tcon_ipc->rlist, &tmp_list);
 			tcon_exist = true;
+			ses->ses_count++;
 		}
 	}
 	/*
@@ -3134,6 +3135,8 @@  void smb2_reconnect_server(struct work_struct *work)
 		else
 			resched = true;
 		list_del_init(&tcon->rlist);
+		if (tcon->ipc)
+			cifs_put_smb_ses(tcon->ses);
 		cifs_put_tcon(tcon);
 	}