From 210782038b54ec8e9059a3c12d6f6ae173efa3a9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 17 May 2019 09:12:33 +0100 Subject: cifs: fix memory leak of pneg_inbuf on -EOPNOTSUPP ioctl case Currently in the case where SMB2_ioctl returns the -EOPNOTSUPP error there is a memory leak of pneg_inbuf. Fix this by returning via the out_free_inbuf exit path that will perform the relevant kfree. Addresses-Coverity: ("Resource leak") Fixes: 969ae8e8d4ee ("cifs: Accept validate negotiate if server return NT_STATUS_NOT_SUPPORTED") CC: Stable # v5.1+ Signed-off-by: Colin Ian King Signed-off-by: Steve French --- fs/cifs/smb2pdu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 710ceb875161..5b8d1482ffbd 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1054,7 +1054,8 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) * not supported error. Client should accept it. */ cifs_dbg(VFS, "Server does not support validate negotiate\n"); - return 0; + rc = 0; + goto out_free_inbuf; } else if (rc != 0) { cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); rc = -EIO; -- cgit v1.2.3-59-g8ed1b From 6457c20e336867fc90286d35bddcc9c0b0aaa936 Mon Sep 17 00:00:00 2001 From: Murphy Zhou Date: Thu, 23 May 2019 12:12:43 +0800 Subject: fs/cifs/smb2pdu.c: fix buffer free in SMB2_ioctl_free The 2nd buffer could be NULL even if iov_len is not zero. This can trigger a panic when handling symlinks. It's easy to reproduce with LTP fs_racer scripts[1] which are randomly craete/delete/link files and dirs. Fix this panic by checking if the 2nd buffer is padding before kfree, like what we do in SMB2_open_free. [1] https://github.com/linux-test-project/ltp/tree/master/testcases/kernel/fs/racer Fixes: 2c87d6a94d16 ("cifs: Allocate memory for all iovs in smb2_ioctl") Signed-off-by: Murphy Zhou Signed-off-by: Steve French Reviewed-by: Ronnie sahlberg --- fs/cifs/smb2pdu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 5b8d1482ffbd..29b699d532ef 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2620,10 +2620,12 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, void SMB2_ioctl_free(struct smb_rqst *rqst) { + int i; if (rqst && rqst->rq_iov) { cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ - if (rqst->rq_iov[1].iov_len) - kfree(rqst->rq_iov[1].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); } } -- cgit v1.2.3-59-g8ed1b From 50fbc13dc12666f3604dc2555a47fc8c4e29162b Mon Sep 17 00:00:00 2001 From: Gen Zhang Date: Tue, 28 May 2019 09:12:39 +0800 Subject: dfs_cache: fix a wrong use of kfree in flush_cache_ent() In flush_cache_ent(), 'ce->ce_path' is allocated by kstrdup_const(). It should be freed by kfree_const(), rather than kfree(). Signed-off-by: Gen Zhang Reviewed-by: Paulo Alcantara Signed-off-by: Steve French --- fs/cifs/dfs_cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index 85dc89d3a203..e3e1c13df439 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -132,7 +132,7 @@ static inline void flush_cache_ent(struct dfs_cache_entry *ce) return; hlist_del_init_rcu(&ce->ce_hlist); - kfree(ce->ce_path); + kfree_const(ce->ce_path); free_tgts(ce); dfs_cache_count--; call_rcu(&ce->ce_rcu, free_cache_entry); @@ -422,7 +422,7 @@ alloc_cache_entry(const char *path, const struct dfs_info3_param *refs, rc = copy_ref_data(refs, numrefs, ce, NULL); if (rc) { - kfree(ce->ce_path); + kfree_const(ce->ce_path); kmem_cache_free(dfs_cache_slab, ce); ce = ERR_PTR(rc); } -- cgit v1.2.3-59-g8ed1b From 31fad7d41e73731f05b8053d17078638cf850fa6 Mon Sep 17 00:00:00 2001 From: Roberto Bergantinos Corpas Date: Tue, 28 May 2019 09:38:14 +0200 Subject: CIFS: cifs_read_allocate_pages: don't iterate through whole page array on ENOMEM In cifs_read_allocate_pages, in case of ENOMEM, we go through whole rdata->pages array but we have failed the allocation before nr_pages, therefore we may end up calling put_page with NULL pointer, causing oops Signed-off-by: Roberto Bergantinos Corpas Acked-by: Pavel Shilovsky Signed-off-by: Steve French CC: Stable --- fs/cifs/file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ce9a5be11df5..06e27ac6d82c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -3216,7 +3216,9 @@ cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages) } if (rc) { - for (i = 0; i < nr_pages; i++) { + unsigned int nr_page_failed = i; + + for (i = 0; i < nr_page_failed; i++) { put_page(rdata->pages[i]); rdata->pages[i] = NULL; } -- cgit v1.2.3-59-g8ed1b