2015-11-04 20:14:27

by Corentin Labbe

[permalink] [raw]
Subject: [PATCH 1/7] crypto: marvell: check return value of sg_nents_for_len

The sg_nents_for_len() function could fail, this patch add a check for
its return value.

Signed-off-by: LABBE Corentin <[email protected]>
---
drivers/crypto/marvell/cipher.c | 8 ++++++++
drivers/crypto/marvell/hash.c | 4 ++++
2 files changed, 12 insertions(+)

diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c
index 3df2f4e..78cf6f9 100644
--- a/drivers/crypto/marvell/cipher.c
+++ b/drivers/crypto/marvell/cipher.c
@@ -400,7 +400,15 @@ static int mv_cesa_ablkcipher_req_init(struct ablkcipher_request *req,
return -EINVAL;

creq->src_nents = sg_nents_for_len(req->src, req->nbytes);
+ if (creq->src_nents < 0) {
+ dev_err(cesa_dev->dev, "Invalid number of src SG");
+ return creq->src_nents;
+ }
creq->dst_nents = sg_nents_for_len(req->dst, req->nbytes);
+ if (creq->dst_nents < 0) {
+ dev_err(cesa_dev->dev, "Invalid number of dst SG");
+ return creq->dst_nents;
+ }

mv_cesa_update_op_cfg(tmpl, CESA_SA_DESC_CFG_OP_CRYPT_ONLY,
CESA_SA_DESC_CFG_OP_MSK);
diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c
index e8d0d71..250c6e5 100644
--- a/drivers/crypto/marvell/hash.c
+++ b/drivers/crypto/marvell/hash.c
@@ -710,6 +710,10 @@ static int mv_cesa_ahash_req_init(struct ahash_request *req, bool *cached)
creq->req.base.type = CESA_STD_REQ;

creq->src_nents = sg_nents_for_len(req->src, req->nbytes);
+ if (creq->src_nents < 0) {
+ dev_err(cesa_dev->dev, "Invalid number of src SG");
+ return creq->src_nents;
+ }

ret = mv_cesa_ahash_cache_req(req, cached);
if (ret)
--
2.4.10


2015-11-04 20:17:52

by Corentin Labbe

[permalink] [raw]
Subject: [PATCH 2/7] crypto: talitos: check return value of sg_nents_for_len

The sg_nents_for_len() function could fail, this patch add a check for
its return value.

Signed-off-by: LABBE Corentin <[email protected]>
---
drivers/crypto/talitos.c | 41 ++++++++++++++++++++++++++++++++++-------
1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 46f531e..898ab6c 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1216,6 +1216,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
struct talitos_private *priv = dev_get_drvdata(dev);
bool is_sec1 = has_ftr_sec1(priv);
int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
+ void *err;

if (cryptlen + authsize > max_len) {
dev_err(dev, "length exceeds h/w max limit\n");
@@ -1228,14 +1229,29 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
if (!dst || dst == src) {
src_nents = sg_nents_for_len(src,
assoclen + cryptlen + authsize);
+ if (src_nents < 0) {
+ dev_err(dev, "Invalid number of src SG.\n");
+ err = ERR_PTR(-EINVAL);
+ goto error_sg;
+ }
src_nents = (src_nents == 1) ? 0 : src_nents;
dst_nents = dst ? src_nents : 0;
} else { /* dst && dst != src*/
src_nents = sg_nents_for_len(src, assoclen + cryptlen +
(encrypt ? 0 : authsize));
+ if (src_nents < 0) {
+ dev_err(dev, "Invalid number of src SG.\n");
+ err = ERR_PTR(-EINVAL);
+ goto error_sg;
+ }
src_nents = (src_nents == 1) ? 0 : src_nents;
dst_nents = sg_nents_for_len(dst, assoclen + cryptlen +
(encrypt ? authsize : 0));
+ if (dst_nents < 0) {
+ dev_err(dev, "Invalid number of dst SG.\n");
+ err = ERR_PTR(-EINVAL);
+ goto error_sg;
+ }
dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}

@@ -1260,11 +1276,9 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,

edesc = kmalloc(alloc_len, GFP_DMA | flags);
if (!edesc) {
- if (iv_dma)
- dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
-
dev_err(dev, "could not allocate edescriptor\n");
- return ERR_PTR(-ENOMEM);
+ err = ERR_PTR(-ENOMEM);
+ goto error_sg;
}

edesc->src_nents = src_nents;
@@ -1277,6 +1291,10 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
DMA_BIDIRECTIONAL);

return edesc;
+error_sg:
+ if (iv_dma)
+ dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+ return err;
}

static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
@@ -1830,11 +1848,16 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
unsigned int nbytes_to_hash;
unsigned int to_hash_later;
unsigned int nsg;
+ int nents;

if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
/* Buffer up to one whole block */
- sg_copy_to_buffer(areq->src,
- sg_nents_for_len(areq->src, nbytes),
+ nents = sg_nents_for_len(areq->src, nbytes);
+ if (nents < 0) {
+ dev_err(ctx->dev, "Invalid number of src SG.\n");
+ return nents;
+ }
+ sg_copy_to_buffer(areq->src, nents,
req_ctx->buf + req_ctx->nbuf, nbytes);
req_ctx->nbuf += nbytes;
return 0;
@@ -1867,7 +1890,11 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
req_ctx->psrc = areq->src;

if (to_hash_later) {
- int nents = sg_nents_for_len(areq->src, nbytes);
+ nents = sg_nents_for_len(areq->src, nbytes);
+ if (nents < 0) {
+ dev_err(ctx->dev, "Invalid number of src SG.\n");
+ return nents;
+ }
sg_pcopy_to_buffer(areq->src, nents,
req_ctx->bufnext,
to_hash_later,
--
2.4.10

2015-11-04 20:14:31

by Corentin Labbe

[permalink] [raw]
Subject: [PATCH 3/7] crypto: sahara: check return value of sg_nents_for_len

The sg_nents_for_len() function could fail, this patch add a check for
its return value.

Signed-off-by: LABBE Corentin <[email protected]>
---
drivers/crypto/sahara.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c
index f68c24a..ea9f56a 100644
--- a/drivers/crypto/sahara.c
+++ b/drivers/crypto/sahara.c
@@ -477,7 +477,15 @@ static int sahara_hw_descriptor_create(struct sahara_dev *dev)
}

dev->nb_in_sg = sg_nents_for_len(dev->in_sg, dev->total);
+ if (dev->nb_in_sg < 0) {
+ dev_err(dev->device, "Invalid numbers of src SG.\n");
+ return dev->nb_in_sg;
+ }
dev->nb_out_sg = sg_nents_for_len(dev->out_sg, dev->total);
+ if (dev->nb_out_sg < 0) {
+ dev_err(dev->device, "Invalid numbers of dst SG.\n");
+ return dev->nb_out_sg;
+ }
if ((dev->nb_in_sg + dev->nb_out_sg) > SAHARA_MAX_HW_LINK) {
dev_err(dev->device, "not enough hw links (%d)\n",
dev->nb_in_sg + dev->nb_out_sg);
@@ -793,6 +801,10 @@ static int sahara_sha_hw_links_create(struct sahara_dev *dev,
dev->in_sg = rctx->in_sg;

dev->nb_in_sg = sg_nents_for_len(dev->in_sg, rctx->total);
+ if (dev->nb_in_sg < 0) {
+ dev_err(dev->device, "Invalid numbers of src SG.\n");
+ return dev->nb_in_sg;
+ }
if ((dev->nb_in_sg) > SAHARA_MAX_HW_LINK) {
dev_err(dev->device, "not enough hw links (%d)\n",
dev->nb_in_sg + dev->nb_out_sg);
--
2.4.10

2015-11-04 20:14:42

by Corentin Labbe

[permalink] [raw]
Subject: [PATCH 4/7] crypto: qce: check return value of sg_nents_for_len

The sg_nents_for_len() function could fail, this patch add a check for
its return value.

Signed-off-by: LABBE Corentin <[email protected]>
---
drivers/crypto/qce/ablkcipher.c | 8 ++++++++
drivers/crypto/qce/sha.c | 5 +++++
2 files changed, 13 insertions(+)

diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/ablkcipher.c
index 2c0d63d..dbcbbe2 100644
--- a/drivers/crypto/qce/ablkcipher.c
+++ b/drivers/crypto/qce/ablkcipher.c
@@ -83,6 +83,14 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes);
else
rctx->dst_nents = rctx->src_nents;
+ if (rctx->src_nents < 0) {
+ dev_err(qce->dev, "Invalid numbers of src SG.\n");
+ return rctx->src_nents;
+ }
+ if (rctx->dst_nents < 0) {
+ dev_err(qce->dev, "Invalid numbers of dst SG.\n");
+ return -rctx->dst_nents;
+ }

rctx->dst_nents += 1;

diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c
index 0c9973e..47e114a 100644
--- a/drivers/crypto/qce/sha.c
+++ b/drivers/crypto/qce/sha.c
@@ -92,6 +92,11 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req)
}

rctx->src_nents = sg_nents_for_len(req->src, req->nbytes);
+ if (rctx->src_nents < 0) {
+ dev_err(qce->dev, "Invalid numbers of src SG.\n");
+ return rctx->src_nents;
+ }
+
ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
if (ret < 0)
return ret;
--
2.4.10

2015-11-04 20:16:37

by Corentin Labbe

[permalink] [raw]
Subject: [PATCH 5/7] crypto: picoxcell: check return value of sg_nents_for_len

The sg_nents_for_len() function could fail, this patch add a check for
its return value.
In the same time, we remove sg_count() as it is used as an alias of
sg_nents_for_len.

Signed-off-by: LABBE Corentin <[email protected]>
---
drivers/crypto/picoxcell_crypto.c | 48 +++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index da36de2..1b16eb28 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -272,12 +272,6 @@ static unsigned spacc_load_ctx(struct spacc_generic_ctx *ctx,
return indx;
}

-/* Count the number of scatterlist entries in a scatterlist. */
-static inline int sg_count(struct scatterlist *sg_list, int nbytes)
-{
- return sg_nents_for_len(sg_list, nbytes);
-}
-
static inline void ddt_set(struct spacc_ddt *ddt, dma_addr_t phys, size_t len)
{
ddt->p = phys;
@@ -300,7 +294,11 @@ static struct spacc_ddt *spacc_sg_to_ddt(struct spacc_engine *engine,
struct spacc_ddt *ddt;
int i;

- nents = sg_count(payload, nbytes);
+ nents = sg_nents_for_len(payload, nbytes);
+ if (nents < 0) {
+ dev_err(engine->dev, "Invalid numbers of SG.\n");
+ return NULL;
+ }
mapped_ents = dma_map_sg(engine->dev, payload, nents, dir);

if (mapped_ents + 1 > MAX_DDT_LEN)
@@ -336,13 +334,21 @@ static int spacc_aead_make_ddts(struct aead_request *areq)
if (req->is_encrypt)
total += crypto_aead_authsize(aead);

- src_nents = sg_count(areq->src, total);
+ src_nents = sg_nents_for_len(areq->src, total);
+ if (src_nents < 0) {
+ dev_err(engine->dev, "Invalid numbers of src SG.\n");
+ return src_nents;
+ }
if (src_nents + 1 > MAX_DDT_LEN)
return -E2BIG;

dst_nents = 0;
if (areq->src != areq->dst) {
- dst_nents = sg_count(areq->dst, total);
+ dst_nents = sg_nents_for_len(areq->dst, total);
+ if (dst_nents < 0) {
+ dev_err(engine->dev, "Invalid numbers of dst SG.\n");
+ return dst_nents;
+ }
if (src_nents + 1 > MAX_DDT_LEN)
return -E2BIG;
}
@@ -422,13 +428,22 @@ static void spacc_aead_free_ddts(struct spacc_req *req)
(req->is_encrypt ? crypto_aead_authsize(aead) : 0);
struct spacc_aead_ctx *aead_ctx = crypto_aead_ctx(aead);
struct spacc_engine *engine = aead_ctx->generic.engine;
- unsigned nents = sg_count(areq->src, total);
+ int nents = sg_nents_for_len(areq->src, total);
+
+ /* sg_nents_for_len should not fail since it works when mapping sg */
+ if (unlikely(nents < 0)) {
+ dev_err(engine->dev, "Invalid numbers of src SG.\n");
+ return;
+ }

if (areq->src != areq->dst) {
dma_unmap_sg(engine->dev, areq->src, nents, DMA_TO_DEVICE);
- dma_unmap_sg(engine->dev, areq->dst,
- sg_count(areq->dst, total),
- DMA_FROM_DEVICE);
+ nents = sg_nents_for_len(areq->dst, total);
+ if (unlikely(nents < 0)) {
+ dev_err(engine->dev, "Invalid numbers of dst SG.\n");
+ return;
+ }
+ dma_unmap_sg(engine->dev, areq->dst, nents, DMA_FROM_DEVICE);
} else
dma_unmap_sg(engine->dev, areq->src, nents, DMA_BIDIRECTIONAL);

@@ -440,7 +455,12 @@ static void spacc_free_ddt(struct spacc_req *req, struct spacc_ddt *ddt,
dma_addr_t ddt_addr, struct scatterlist *payload,
unsigned nbytes, enum dma_data_direction dir)
{
- unsigned nents = sg_count(payload, nbytes);
+ int nents = sg_nents_for_len(payload, nbytes);
+
+ if (nents < 0) {
+ dev_err(req->engine->dev, "Invalid numbers of SG.\n");
+ return;
+ }

dma_unmap_sg(req->engine->dev, payload, nents, dir);
dma_pool_free(req->engine->req_pool, ddt, ddt_addr);
--
2.4.10

2015-11-04 20:14:50

by Corentin Labbe

[permalink] [raw]
Subject: [PATCH 6/7] crypto: caam: check return value of sg_nents_for_len

The sg_nents_for_len() function could fail, this patch add a check for
its return value.
We do the same for sg_count since it use sg_nents_for_len().

Signed-off-by: LABBE Corentin <[email protected]>
---
drivers/crypto/caam/caamhash.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)

diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 9609f66..b894ce3 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -794,6 +794,10 @@ static int ahash_update_ctx(struct ahash_request *req)
if (to_hash) {
src_nents = sg_nents_for_len(req->src,
req->nbytes - (*next_buflen));
+ if (src_nents < 0) {
+ dev_err(jrdev, "Invalid number of src SG.\n");
+ return src_nents;
+ }
sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
sizeof(struct sec4_sg_entry);
@@ -993,6 +997,10 @@ static int ahash_finup_ctx(struct ahash_request *req)
int sh_len;

src_nents = sg_nents_for_len(req->src, req->nbytes);
+ if (src_nents < 0) {
+ dev_err(jrdev, "Invalid number of src SG.\n");
+ return src_nents;
+ }
sec4_sg_src_index = 1 + (buflen ? 1 : 0);
sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
sizeof(struct sec4_sg_entry);
@@ -1077,6 +1085,10 @@ static int ahash_digest(struct ahash_request *req)
int sh_len;

src_nents = sg_count(req->src, req->nbytes);
+ if (src_nents < 0) {
+ dev_err(jrdev, "Invalid number of src SG.\n");
+ return src_nents;
+ }
dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE);
sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);

@@ -1225,6 +1237,10 @@ static int ahash_update_no_ctx(struct ahash_request *req)
if (to_hash) {
src_nents = sg_nents_for_len(req->src,
req->nbytes - (*next_buflen));
+ if (src_nents < 0) {
+ dev_err(jrdev, "Invalid number of src SG.\n");
+ return src_nents;
+ }
sec4_sg_bytes = (1 + src_nents) *
sizeof(struct sec4_sg_entry);

@@ -1333,6 +1349,10 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
int ret = 0;

src_nents = sg_nents_for_len(req->src, req->nbytes);
+ if (src_nents < 0) {
+ dev_err(jrdev, "Invalid number of src SG.\n");
+ return src_nents;
+ }
sec4_sg_src_index = 2;
sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
sizeof(struct sec4_sg_entry);
@@ -1421,6 +1441,10 @@ static int ahash_update_first(struct ahash_request *req)

if (to_hash) {
src_nents = sg_count(req->src, req->nbytes - (*next_buflen));
+ if (src_nents < 0) {
+ dev_err(jrdev, "Invalid number of src SG.\n");
+ return src_nents;
+ }
dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE);
sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);

--
2.4.10

2015-11-04 20:14:57

by Corentin Labbe

[permalink] [raw]
Subject: [PATCH 7/7] crypto: amcc: check return value of sg_nents_for_len

The sg_nents_for_len() function could fail, this patch add a check for
its return value.

Signed-off-by: LABBE Corentin <[email protected]>
---
drivers/crypto/amcc/crypto4xx_core.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 27288fc..e6f7757 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -781,6 +781,10 @@ u32 crypto4xx_build_pd(struct crypto_async_request *req,

/* figure how many gd is needed */
num_gd = sg_nents_for_len(src, datalen);
+ if ((int)num_gd < 0) {
+ dev_err(dev->core_dev->device, "Invalid number of src SG.\n");
+ return -EINVAL;
+ }
if (num_gd == 1)
num_gd = 0;

--
2.4.10

2015-11-06 15:31:05

by Jamie Iles

[permalink] [raw]
Subject: Re: [PATCH 5/7] crypto: picoxcell: check return value of sg_nents_for_len

On Wed, Nov 04, 2015 at 09:13:37PM +0100, LABBE Corentin wrote:
> The sg_nents_for_len() function could fail, this patch add a check for
> its return value.
> In the same time, we remove sg_count() as it is used as an alias of
> sg_nents_for_len.
>
> Signed-off-by: LABBE Corentin <[email protected]>

Acked-by: Jamie Iles <[email protected]>

thanks for doing this!

Jamie

2015-11-17 14:09:16

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 1/7] crypto: marvell: check return value of sg_nents_for_len

On Wed, Nov 04, 2015 at 09:13:33PM +0100, LABBE Corentin wrote:
> The sg_nents_for_len() function could fail, this patch add a check for
> its return value.
>
> Signed-off-by: LABBE Corentin <[email protected]>

All applied. Thanks.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt