Commit 6238f921 authored by Dong Jia Shi's avatar Dong Jia Shi Committed by Cornelia Huck

vfio: ccw: set ccw->cda to NULL defensively

Let's avoid free on ccw->cda that points to a guest address
or an already freed memory area by setting it to NULL if memory
allocation didn't happen or failed.
Signed-off-by: default avatarDong Jia Shi <bjsdjshi@linux.ibm.com>
Message-Id: <20180523025645.8978-4-bjsdjshi@linux.ibm.com>
Signed-off-by: default avatarCornelia Huck <cohuck@redhat.com>
parent 5c1cfb1c
...@@ -502,7 +502,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain, ...@@ -502,7 +502,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
struct ccw1 *ccw; struct ccw1 *ccw;
struct pfn_array_table *pat; struct pfn_array_table *pat;
unsigned long *idaws; unsigned long *idaws;
int idaw_nr; int ret;
ccw = chain->ch_ccw + idx; ccw = chain->ch_ccw + idx;
...@@ -522,18 +522,19 @@ static int ccwchain_fetch_direct(struct ccwchain *chain, ...@@ -522,18 +522,19 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
* needed when translating a direct ccw to a idal ccw. * needed when translating a direct ccw to a idal ccw.
*/ */
pat = chain->ch_pat + idx; pat = chain->ch_pat + idx;
if (pfn_array_table_init(pat, 1)) ret = pfn_array_table_init(pat, 1);
return -ENOMEM; if (ret)
idaw_nr = pfn_array_alloc_pin(pat->pat_pa, cp->mdev, goto out_init;
ccw->cda, ccw->count);
if (idaw_nr < 0) ret = pfn_array_alloc_pin(pat->pat_pa, cp->mdev, ccw->cda, ccw->count);
return idaw_nr; if (ret < 0)
goto out_init;
/* Translate this direct ccw to a idal ccw. */ /* Translate this direct ccw to a idal ccw. */
idaws = kcalloc(idaw_nr, sizeof(*idaws), GFP_DMA | GFP_KERNEL); idaws = kcalloc(ret, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
if (!idaws) { if (!idaws) {
pfn_array_table_unpin_free(pat, cp->mdev); ret = -ENOMEM;
return -ENOMEM; goto out_unpin;
} }
ccw->cda = (__u32) virt_to_phys(idaws); ccw->cda = (__u32) virt_to_phys(idaws);
ccw->flags |= CCW_FLAG_IDA; ccw->flags |= CCW_FLAG_IDA;
...@@ -541,6 +542,12 @@ static int ccwchain_fetch_direct(struct ccwchain *chain, ...@@ -541,6 +542,12 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
pfn_array_table_idal_create_words(pat, idaws); pfn_array_table_idal_create_words(pat, idaws);
return 0; return 0;
out_unpin:
pfn_array_table_unpin_free(pat, cp->mdev);
out_init:
ccw->cda = 0;
return ret;
} }
static int ccwchain_fetch_idal(struct ccwchain *chain, static int ccwchain_fetch_idal(struct ccwchain *chain,
...@@ -570,7 +577,7 @@ static int ccwchain_fetch_idal(struct ccwchain *chain, ...@@ -570,7 +577,7 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
pat = chain->ch_pat + idx; pat = chain->ch_pat + idx;
ret = pfn_array_table_init(pat, idaw_nr); ret = pfn_array_table_init(pat, idaw_nr);
if (ret) if (ret)
return ret; goto out_init;
/* Translate idal ccw to use new allocated idaws. */ /* Translate idal ccw to use new allocated idaws. */
idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL); idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL);
...@@ -602,6 +609,8 @@ static int ccwchain_fetch_idal(struct ccwchain *chain, ...@@ -602,6 +609,8 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
kfree(idaws); kfree(idaws);
out_unpin: out_unpin:
pfn_array_table_unpin_free(pat, cp->mdev); pfn_array_table_unpin_free(pat, cp->mdev);
out_init:
ccw->cda = 0;
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment