2014-04-18 10:01:41

by Horia Geantă

[permalink] [raw]
Subject: [PATCH crypto 1/2] crypto: caam - fix mem leak in ahash_setkey

In case hash key is bigger than algorithm block size, it is hashed.
In this case, memory is allocated to keep this hash in hashed_key.
hashed_key has to be freed on the key_dma dma mapping error path.

Cc: <[email protected]> # 3.10+
Signed-off-by: Horia Geanta <[email protected]>
---
drivers/crypto/caam/caamhash.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 0378328f47a7..2d244e629ed2 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -545,7 +545,8 @@ static int ahash_setkey(struct crypto_ahash *ahash,
DMA_TO_DEVICE);
if (dma_mapping_error(jrdev, ctx->key_dma)) {
dev_err(jrdev, "unable to map key i/o memory\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto map_err;
}
#ifdef DEBUG
print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
@@ -559,6 +560,7 @@ static int ahash_setkey(struct crypto_ahash *ahash,
DMA_TO_DEVICE);
}

+map_err:
kfree(hashed_key);
return ret;
badkey:
--
1.8.3.1


2014-04-18 10:01:42

by Horia Geantă

[permalink] [raw]
Subject: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

GFP_ATOMIC memory allocation could fail.
In this case, avoid NULL pointer dereference and notify user.

Cc: <[email protected]> # 3.2+
Cc: Kim Phillips <[email protected]>
Signed-off-by: Horia Geanta <[email protected]>
---
drivers/crypto/caam/error.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
index 9f25f5296029..0eabd81e1a90 100644
--- a/drivers/crypto/caam/error.c
+++ b/drivers/crypto/caam/error.c
@@ -16,9 +16,13 @@
char *tmp; \
\
tmp = kmalloc(sizeof(format) + max_alloc, GFP_ATOMIC); \
- sprintf(tmp, format, param); \
- strcat(str, tmp); \
- kfree(tmp); \
+ if (likely(tmp)) { \
+ sprintf(tmp, format, param); \
+ strcat(str, tmp); \
+ kfree(tmp); \
+ } else { \
+ strcat(str, "kmalloc failure in SPRINTFCAT"); \
+ } \
}

static void report_jump_idx(u32 status, char *outstr)
--
1.8.3.1

2014-04-22 23:59:06

by Marek Vasut

[permalink] [raw]
Subject: Re: [PATCH crypto 1/2] crypto: caam - fix mem leak in ahash_setkey

On Friday, April 18, 2014 at 12:01:41 PM, Horia Geanta wrote:
> In case hash key is bigger than algorithm block size, it is hashed.
> In this case, memory is allocated to keep this hash in hashed_key.
> hashed_key has to be freed on the key_dma dma mapping error path.
>
> Cc: <[email protected]> # 3.10+
> Signed-off-by: Horia Geanta <[email protected]>
> ---
> drivers/crypto/caam/caamhash.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/crypto/caam/caamhash.c
> b/drivers/crypto/caam/caamhash.c index 0378328f47a7..2d244e629ed2 100644
> --- a/drivers/crypto/caam/caamhash.c
> +++ b/drivers/crypto/caam/caamhash.c
> @@ -545,7 +545,8 @@ static int ahash_setkey(struct crypto_ahash *ahash,
> DMA_TO_DEVICE);
> if (dma_mapping_error(jrdev, ctx->key_dma)) {
> dev_err(jrdev, "unable to map key i/o memory\n");
> - return -ENOMEM;
> + ret = -ENOMEM;
> + goto map_err;
> }
> #ifdef DEBUG
> print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
> @@ -559,6 +560,7 @@ static int ahash_setkey(struct crypto_ahash *ahash,
> DMA_TO_DEVICE);
> }
>
> +map_err:
> kfree(hashed_key);

Reviewed-by: Marek Vasut <[email protected]>

btw you might want to clean up the use of printk() vs. dev_*() throughout the
driver, it's horribly intermixed. It'd be nice to use just dev_*() for output.
Stuff like
#ifdef DEBUG
printk(...)
#endif
can be easily replaced with dev_dbg() for example ...

Best regards,
Marek Vasut

2014-04-22 23:59:06

by Marek Vasut

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On Friday, April 18, 2014 at 12:01:42 PM, Horia Geanta wrote:
> GFP_ATOMIC memory allocation could fail.
> In this case, avoid NULL pointer dereference and notify user.
>
> Cc: <[email protected]> # 3.2+

If I recall correctly, you need to get the patch accepted into mainline before
sending it for -stable .

> Cc: Kim Phillips <[email protected]>
> Signed-off-by: Horia Geanta <[email protected]>
> ---
> drivers/crypto/caam/error.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
> index 9f25f5296029..0eabd81e1a90 100644
> --- a/drivers/crypto/caam/error.c
> +++ b/drivers/crypto/caam/error.c
> @@ -16,9 +16,13 @@
> char *tmp; \
> \
> tmp = kmalloc(sizeof(format) + max_alloc, GFP_ATOMIC); \
> - sprintf(tmp, format, param); \
> - strcat(str, tmp); \
> - kfree(tmp); \
> + if (likely(tmp)) { \
> + sprintf(tmp, format, param); \
> + strcat(str, tmp); \
> + kfree(tmp); \
> + } else { \
> + strcat(str, "kmalloc failure in SPRINTFCAT"); \

This entire macro looks somewhat strange.
1) Can't you just snprintf() into $str + some offset ? Something like:
snprintf(str + strlen(str), str_total_sz - strlen(str), format, param);

2) Why is noone checking if the $str has enough space for contents of $tmp ?

Best regards,
Marek Vasut

2014-04-23 16:50:51

by Horia Geantă

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On 4/23/2014 2:56 AM, Marek Vasut wrote:
> On Friday, April 18, 2014 at 12:01:42 PM, Horia Geanta wrote:
>> GFP_ATOMIC memory allocation could fail.
>> In this case, avoid NULL pointer dereference and notify user.
>>
>> Cc: <[email protected]> # 3.2+
>
> If I recall correctly, you need to get the patch accepted into mainline before
> sending it for -stable .
>

From Documentation/stable_kernel_rules.txt
- To have the patch automatically included in the stable tree, add the tag
Cc: [email protected]
in the sign-off area. Once the patch is merged it will be applied to
the stable tree without anything else needing to be done by the author
or subsystem maintainer.

>> Cc: Kim Phillips <[email protected]>
>> Signed-off-by: Horia Geanta <[email protected]>
>> ---
>> drivers/crypto/caam/error.c | 10 +++++++---
>> 1 file changed, 7 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
>> index 9f25f5296029..0eabd81e1a90 100644
>> --- a/drivers/crypto/caam/error.c
>> +++ b/drivers/crypto/caam/error.c
>> @@ -16,9 +16,13 @@
>> char *tmp; \
>> \
>> tmp = kmalloc(sizeof(format) + max_alloc, GFP_ATOMIC); \
>> - sprintf(tmp, format, param); \
>> - strcat(str, tmp); \
>> - kfree(tmp); \
>> + if (likely(tmp)) { \
>> + sprintf(tmp, format, param); \
>> + strcat(str, tmp); \
>> + kfree(tmp); \
>> + } else { \
>> + strcat(str, "kmalloc failure in SPRINTFCAT"); \
>
> This entire macro looks somewhat strange.

I am trying to fix it with minimal changes, so the patch qualifies for
-stable.

> 1) Can't you just snprintf() into $str + some offset ? Something like:
> snprintf(str + strlen(str), str_total_sz - strlen(str), format, param);
>

I think this would work. It also gets rid of memory allocation.

Note that strlen(str) is undefined if str is not initialized /
null-terminated.
However, all code paths seem to touch this line in caam_jr_strstatus():
sprintf(outstr, "%s: ", status_src[ssrc].error);
before reaching SPRINTFCAT macros, so str is null-terminated.

I'll send v2.

> 2) Why is noone checking if the $str has enough space for contents of $tmp ?

All call sites reach this macro via caam_jr_strstatus(tmp, ...), which
is always called having:
char tmp[CAAM_ERROR_STR_MAX];

CAAM_ERROR_STR_MAX is 302, probably enough according to commit
de2954d66408da3ae34effda777bb564fd17781b (crypto: caam - fix printk
recursion for long error texts).

Horia

2014-04-23 17:12:19

by Marek Vasut

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On Wednesday, April 23, 2014 at 06:35:45 PM, Horia Geantă wrote:

[...]

> > This entire macro looks somewhat strange.
>
> I am trying to fix it with minimal changes, so the patch qualifies for
> -stable.

This is just broken and you're not fixing it. You're just feeding this slimy
monster called technical debt more and more code, so it can grow and get uglier
and uglier. I hope you have no attachment to this abomination, since I'd like to
see it dead.

> > 1) Can't you just snprintf() into $str + some offset ? Something like:
> > snprintf(str + strlen(str), str_total_sz - strlen(str), format,
> > param);
>
> I think this would work. It also gets rid of memory allocation.
>
> Note that strlen(str) is undefined if str is not initialized /
> null-terminated.
> However, all code paths seem to touch this line in caam_jr_strstatus():
> sprintf(outstr, "%s: ", status_src[ssrc].error);
> before reaching SPRINTFCAT macros, so str is null-terminated.
>
> I'll send v2.

No, let us first agree on how to fix this insane abomination please.

But while I am looking, I see stuff like:

caam_jr_strstatus() can call report_ccb_status( , "CCB"); (basically with a
fixed-size string argument):

265 if (status_src[ssrc].report_ssed)
266 status_src[ssrc].report_ssed(status, outstr);

Report_ccb_status( , "CCB"); will call report_jump_idx( , "CCB"); (still with
fixed-size string arg), which contains your SPRINTFCAT() macro.

This will expand to:

...
strcat("CCB", tmp);
...

So basically you are writing into a fixed-size string? But the string is three-
bytes long, so you are overwriting kernel memory ?

If I read the code wrong, I really apologize in advance.

> > 2) Why is noone checking if the $str has enough space for contents of
> > $tmp ?
>
> All call sites reach this macro via caam_jr_strstatus(tmp, ...), which
> is always called having:
> char tmp[CAAM_ERROR_STR_MAX];
>
> CAAM_ERROR_STR_MAX is 302, probably enough according to commit
> de2954d66408da3ae34effda777bb564fd17781b (crypto: caam - fix printk
> recursion for long error texts).

You are digging in Linux's crypto code, not OpenSSL. We need accurate fixes and
accurate discussion ... using 'probably' does not work here.

Best regards,
Marek Vasut

2014-04-23 17:41:02

by Marek Vasut

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On Wednesday, April 23, 2014 at 07:12:19 PM, Marek Vasut wrote:
> On Wednesday, April 23, 2014 at 06:35:45 PM, Horia Geantă wrote:
>
> [...]
>
> > > This entire macro looks somewhat strange.
> >
> > I am trying to fix it with minimal changes, so the patch qualifies for
> > -stable.
>
> This is just broken and you're not fixing it. You're just feeding this
> slimy monster called technical debt more and more code, so it can grow and
> get uglier and uglier. I hope you have no attachment to this abomination,
> since I'd like to see it dead.
>
> > > 1) Can't you just snprintf() into $str + some offset ? Something like:
> > > snprintf(str + strlen(str), str_total_sz - strlen(str), format,
> > > param);
> >
> > I think this would work. It also gets rid of memory allocation.
> >
> > Note that strlen(str) is undefined if str is not initialized /
> > null-terminated.
> > However, all code paths seem to touch this line in caam_jr_strstatus():
> > sprintf(outstr, "%s: ", status_src[ssrc].error);
> > before reaching SPRINTFCAT macros, so str is null-terminated.
> >
> > I'll send v2.
>
> No, let us first agree on how to fix this insane abomination please.
>
> But while I am looking, I see stuff like:
>
> caam_jr_strstatus() can call report_ccb_status( , "CCB"); (basically with a
> fixed-size string argument):
>
> 265 if (status_src[ssrc].report_ssed)
> 266 status_src[ssrc].report_ssed(status, outstr);
>
> Report_ccb_status( , "CCB"); will call report_jump_idx( , "CCB"); (still
> with fixed-size string arg), which contains your SPRINTFCAT() macro.
>
> This will expand to:
>
> ...
> strcat("CCB", tmp);
> ...
>
> So basically you are writing into a fixed-size string? But the string is
> three- bytes long, so you are overwriting kernel memory ?

Ok, I apologize. You were right. The 'strcat()' is always called with a fixed-
length 302byte long buffer allocated on stack. Thus this code is only fragile.

I will need to think of this code a bit more before I blurt out some serious
nonsense again.

Best regards,
Marek Vasut

2014-04-28 10:24:41

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On Fri, Apr 18, 2014 at 01:01:42PM +0300, Horia Geanta wrote:
> GFP_ATOMIC memory allocation could fail.
> In this case, avoid NULL pointer dereference and notify user.
>
> Cc: <[email protected]> # 3.2+
> Cc: Kim Phillips <[email protected]>
> Signed-off-by: Horia Geanta <[email protected]>

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

2014-04-28 10:25:36

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH crypto 1/2] crypto: caam - fix mem leak in ahash_setkey

On Wed, Apr 23, 2014 at 01:47:32AM +0200, Marek Vasut wrote:
> On Friday, April 18, 2014 at 12:01:41 PM, Horia Geanta wrote:
> > In case hash key is bigger than algorithm block size, it is hashed.
> > In this case, memory is allocated to keep this hash in hashed_key.
> > hashed_key has to be freed on the key_dma dma mapping error path.
> >
> > Cc: <[email protected]> # 3.10+
> > Signed-off-by: Horia Geanta <[email protected]>
> > ---
> > drivers/crypto/caam/caamhash.c | 4 +++-
> > 1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/crypto/caam/caamhash.c
> > b/drivers/crypto/caam/caamhash.c index 0378328f47a7..2d244e629ed2 100644
> > --- a/drivers/crypto/caam/caamhash.c
> > +++ b/drivers/crypto/caam/caamhash.c
> > @@ -545,7 +545,8 @@ static int ahash_setkey(struct crypto_ahash *ahash,
> > DMA_TO_DEVICE);
> > if (dma_mapping_error(jrdev, ctx->key_dma)) {
> > dev_err(jrdev, "unable to map key i/o memory\n");
> > - return -ENOMEM;
> > + ret = -ENOMEM;
> > + goto map_err;
> > }
> > #ifdef DEBUG
> > print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
> > @@ -559,6 +560,7 @@ static int ahash_setkey(struct crypto_ahash *ahash,
> > DMA_TO_DEVICE);
> > }
> >
> > +map_err:
> > kfree(hashed_key);
>
> Reviewed-by: Marek Vasut <[email protected]>

Patch applied to cryptodev. I'm not pushing this to stable
because it doesn't satisfy the conditions for it.

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

2014-04-28 21:52:12

by Marek Vasut

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On Monday, April 28, 2014 at 12:24:41 PM, Herbert Xu wrote:
> On Fri, Apr 18, 2014 at 01:01:42PM +0300, Horia Geanta wrote:
> > GFP_ATOMIC memory allocation could fail.
> > In this case, avoid NULL pointer dereference and notify user.
> >
> > Cc: <[email protected]> # 3.2+
> > Cc: Kim Phillips <[email protected]>
> > Signed-off-by: Horia Geanta <[email protected]>
>
> Patch applied to the crypto tree. Thanks.

Hi Herbert,

Don't you instead want to apply my 11-patch series from
Message-Id: <[email protected]>
Subject: [PATCH 00/11] crypto: caam: Error reporting fixes
which actually fixes this SPRINTFCAT() horror properly please ?

Best regards,
Marek Vasut

2014-04-28 21:53:23

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On Mon, Apr 28, 2014 at 09:28:41PM +0200, Marek Vasut wrote:
> On Monday, April 28, 2014 at 12:24:41 PM, Herbert Xu wrote:
> > On Fri, Apr 18, 2014 at 01:01:42PM +0300, Horia Geanta wrote:
> > > GFP_ATOMIC memory allocation could fail.
> > > In this case, avoid NULL pointer dereference and notify user.
> > >
> > > Cc: <[email protected]> # 3.2+
> > > Cc: Kim Phillips <[email protected]>
> > > Signed-off-by: Horia Geanta <[email protected]>
> >
> > Patch applied to the crypto tree. Thanks.
>
> Hi Herbert,
>
> Don't you instead want to apply my 11-patch series from
> Message-Id: <[email protected]>
> Subject: [PATCH 00/11] crypto: caam: Error reporting fixes
> which actually fixes this SPRINTFCAT() horror properly please ?

This patch is going into the current release while your patches
are better suited for the next merge window.

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

2014-04-28 22:46:54

by Marek Vasut

[permalink] [raw]
Subject: Re: [PATCH crypto 2/2] crypto: caam - add allocation failure handling in SPRINTFCAT macro

On Monday, April 28, 2014 at 11:53:23 PM, Herbert Xu wrote:
> On Mon, Apr 28, 2014 at 09:28:41PM +0200, Marek Vasut wrote:
> > On Monday, April 28, 2014 at 12:24:41 PM, Herbert Xu wrote:
> > > On Fri, Apr 18, 2014 at 01:01:42PM +0300, Horia Geanta wrote:
> > > > GFP_ATOMIC memory allocation could fail.
> > > > In this case, avoid NULL pointer dereference and notify user.
> > > >
> > > > Cc: <[email protected]> # 3.2+
> > > > Cc: Kim Phillips <[email protected]>
> > > > Signed-off-by: Horia Geanta <[email protected]>
> > >
> > > Patch applied to the crypto tree. Thanks.
> >
> > Hi Herbert,
> >
> > Don't you instead want to apply my 11-patch series from
> > Message-Id: <[email protected]>
> > Subject: [PATCH 00/11] crypto: caam: Error reporting fixes
> > which actually fixes this SPRINTFCAT() horror properly please ?
>
> This patch is going into the current release while your patches
> are better suited for the next merge window.

I agree with you that we're rather late in the RC now, but I also believe this
patch is just hiding the real bug and that we should fix the root cause of the
problem instead of adding a plaster over it.

I also believe that while my 11-patch series is big, it should go into -stable
eventually, since it fixes the real problem.

Best regards,
Marek Vasut