| From 32a1fb36f6e50183871c2c1fcf5493c633e84732 Mon Sep 17 00:00:00 2001 |
| From: Ronnie Sahlberg <lsahlber@redhat.com> |
| Date: Wed, 24 Oct 2018 11:50:33 +1000 |
| Subject: cifs: allow calling SMB2_xxx_free(NULL) |
| |
| From: Ronnie Sahlberg <lsahlber@redhat.com> |
| |
| commit 32a1fb36f6e50183871c2c1fcf5493c633e84732 upstream. |
| |
| Change these free functions to allow passing NULL as the argument and |
| treat it as a no-op just like free(NULL) would. |
| Or, if rqst->rq_iov is NULL. |
| |
| The second scenario could happen for smb2_queryfs() if the call |
| to SMB2_query_info_init() fails and we go to qfs_exit to clean up |
| and free all resources. |
| In that case we have not yet assigned rqst[2].rq_iov and thus |
| the rq_iov dereference in SMB2_close_free() will cause a NULL pointer |
| dereference. |
| |
| [ bp: upstream patch also fixes SMB2_set_info_free which was introduced in 4.20 ] |
| |
| Fixes: 1eb9fb52040f ("cifs: create SMB2_open_init()/SMB2_open_free() helpers") |
| |
| Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| Reviewed-by: Aurelien Aptel <aaptel@suse.com> |
| CC: Stable <stable@vger.kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/cifs/smb2pdu.c | 16 ++++++++++------ |
| 1 file changed, 10 insertions(+), 6 deletions(-) |
| |
| --- a/fs/cifs/smb2pdu.c |
| +++ b/fs/cifs/smb2pdu.c |
| @@ -2243,10 +2243,12 @@ SMB2_open_free(struct smb_rqst *rqst) |
| { |
| int i; |
| |
| - cifs_small_buf_release(rqst->rq_iov[0].iov_base); |
| - for (i = 1; i < rqst->rq_nvec; i++) |
| - if (rqst->rq_iov[i].iov_base != smb2_padding) |
| - kfree(rqst->rq_iov[i].iov_base); |
| + if (rqst && rqst->rq_iov) { |
| + cifs_small_buf_release(rqst->rq_iov[0].iov_base); |
| + for (i = 1; i < rqst->rq_nvec; i++) |
| + if (rqst->rq_iov[i].iov_base != smb2_padding) |
| + kfree(rqst->rq_iov[i].iov_base); |
| + } |
| } |
| |
| int |
| @@ -2535,7 +2537,8 @@ SMB2_close_init(struct cifs_tcon *tcon, |
| void |
| SMB2_close_free(struct smb_rqst *rqst) |
| { |
| - cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
| + if (rqst && rqst->rq_iov) |
| + cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
| } |
| |
| int |
| @@ -2685,7 +2688,8 @@ SMB2_query_info_init(struct cifs_tcon *t |
| void |
| SMB2_query_info_free(struct smb_rqst *rqst) |
| { |
| - cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
| + if (rqst && rqst->rq_iov) |
| + cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
| } |
| |
| static int |