Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -502,7 +502,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
	struct ccw1 *ccw;
	struct pfn_array_table *pat;
	unsigned long *idaws;
	int idaw_nr;
	int ret;

	ccw = chain->ch_ccw + idx;

@@ -522,18 +522,19 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
	 * needed when translating a direct ccw to a idal ccw.
	 */
	pat = chain->ch_pat + idx;
	if (pfn_array_table_init(pat, 1))
		return -ENOMEM;
	idaw_nr = pfn_array_alloc_pin(pat->pat_pa, cp->mdev,
				      ccw->cda, ccw->count);
	if (idaw_nr < 0)
		return idaw_nr;
	ret = pfn_array_table_init(pat, 1);
	if (ret)
		goto out_init;

	ret = pfn_array_alloc_pin(pat->pat_pa, cp->mdev, ccw->cda, ccw->count);
	if (ret < 0)
		goto out_init;

	/* 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) {
		pfn_array_table_unpin_free(pat, cp->mdev);
		return -ENOMEM;
		ret = -ENOMEM;
		goto out_unpin;
	}
	ccw->cda = (__u32) virt_to_phys(idaws);
	ccw->flags |= CCW_FLAG_IDA;
@@ -541,6 +542,12 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
	pfn_array_table_idal_create_words(pat, idaws);

	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,
@@ -570,7 +577,7 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
	pat = chain->ch_pat + idx;
	ret = pfn_array_table_init(pat, idaw_nr);
	if (ret)
		return ret;
		goto out_init;

	/* Translate idal ccw to use new allocated idaws. */
	idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL);
@@ -602,6 +609,8 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
	kfree(idaws);
out_unpin:
	pfn_array_table_unpin_free(pat, cp->mdev);
out_init:
	ccw->cda = 0;
	return ret;
}