diff mbox series

mac80211: aes-cmac: remove VLA usage

Message ID 20180321134247.GA1275@embeddedgus
State Awaiting Upstream, archived
Delegated to: David Miller
Headers show
Series mac80211: aes-cmac: remove VLA usage | expand

Commit Message

Gustavo A. R. Silva March 21, 2018, 1:42 p.m. UTC
In preparation to enabling -Wvla, remove VLAs and replace them
with dynamic memory allocation instead.

The use of stack Variable Length Arrays needs to be avoided, as they
can be a vector for stack exhaustion, which can be both a runtime bug
or a security flaw. Also, in general, as code evolves it is easy to
lose track of how big a VLA can get. Thus, we can end up having runtime
failures that are hard to debug.

Also, fixed as part of the directive to remove all VLAs from
the kernel: https://lkml.org/lkml/2018/3/7/621

Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
 net/mac80211/aes_cmac.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

Comments

Johannes Berg March 21, 2018, 1:48 p.m. UTC | #1
On Wed, 2018-03-21 at 08:42 -0500, Gustavo A. R. Silva wrote:
> In preparation to enabling -Wvla, remove VLAs and replace them
> with dynamic memory allocation instead.
> 
> The use of stack Variable Length Arrays needs to be avoided, as they
> can be a vector for stack exhaustion, which can be both a runtime bug
> or a security flaw. Also, in general, as code evolves it is easy to
> lose track of how big a VLA can get. Thus, we can end up having runtime
> failures that are hard to debug.
> 
> Also, fixed as part of the directive to remove all VLAs from
> the kernel: https://lkml.org/lkml/2018/3/7/621
> 
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
> ---
>  net/mac80211/aes_cmac.c | 36 ++++++++++++++++++++++++------------
>  1 file changed, 24 insertions(+), 12 deletions(-)
> 
> diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
> index 2fb6558..c9444bf 100644
> --- a/net/mac80211/aes_cmac.c
> +++ b/net/mac80211/aes_cmac.c
> @@ -27,30 +27,42 @@ static const u8 zero[CMAC_TLEN_256];
>  void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
>  			const u8 *data, size_t data_len, u8 *mic)
>  {
> -	SHASH_DESC_ON_STACK(desc, tfm);
> +	struct shash_desc *shash;
>  	u8 out[AES_BLOCK_SIZE];
>  
> -	desc->tfm = tfm;
> +	shash = kmalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
> +			GFP_KERNEL);
> +	if (!shash)
> +		return;

Honestly, this seems like a really bad idea - you're now hitting
kmalloc for every TX/RX frame here.

SHA_DESC_ON_STACK() should just be fixed to not need a VLA, but take
some sort of maximum, I guess?

johannes
Gustavo A. R. Silva March 21, 2018, 1:57 p.m. UTC | #2
On 03/21/2018 08:48 AM, Johannes Berg wrote:
> On Wed, 2018-03-21 at 08:42 -0500, Gustavo A. R. Silva wrote:
>> In preparation to enabling -Wvla, remove VLAs and replace them
>> with dynamic memory allocation instead.
>>
>> The use of stack Variable Length Arrays needs to be avoided, as they
>> can be a vector for stack exhaustion, which can be both a runtime bug
>> or a security flaw. Also, in general, as code evolves it is easy to
>> lose track of how big a VLA can get. Thus, we can end up having runtime
>> failures that are hard to debug.
>>
>> Also, fixed as part of the directive to remove all VLAs from
>> the kernel: https://lkml.org/lkml/2018/3/7/621
>>
>> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
>> ---
>>   net/mac80211/aes_cmac.c | 36 ++++++++++++++++++++++++------------
>>   1 file changed, 24 insertions(+), 12 deletions(-)
>>
>> diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
>> index 2fb6558..c9444bf 100644
>> --- a/net/mac80211/aes_cmac.c
>> +++ b/net/mac80211/aes_cmac.c
>> @@ -27,30 +27,42 @@ static const u8 zero[CMAC_TLEN_256];
>>   void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
>>   			const u8 *data, size_t data_len, u8 *mic)
>>   {
>> -	SHASH_DESC_ON_STACK(desc, tfm);
>> +	struct shash_desc *shash;
>>   	u8 out[AES_BLOCK_SIZE];
>>   
>> -	desc->tfm = tfm;
>> +	shash = kmalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
>> +			GFP_KERNEL);
>> +	if (!shash)
>> +		return;
> 
> Honestly, this seems like a really bad idea - you're now hitting
> kmalloc for every TX/RX frame here.
> 
> SHA_DESC_ON_STACK() should just be fixed to not need a VLA, but take
> some sort of maximum, I guess?
> 

SHA_DESC_ON_STACK is currently being used in multiple places. But, yeah, 
I think we can define multiple macros of the same kind and adjust to the 
characteristics of each the component.

How big do you think tfm can get?

Thanks
--
Gustavo
Johannes Berg March 21, 2018, 1:58 p.m. UTC | #3
On Wed, 2018-03-21 at 08:57 -0500, Gustavo A. R. Silva wrote:
> 
> SHA_DESC_ON_STACK is currently being used in multiple places. But, yeah, 
> I think we can define multiple macros of the same kind and adjust to the 
> characteristics of each the component.
> 
> How big do you think tfm can get?

I have no idea, I guess you'll have to take that with Herbert.

johannes
Gustavo A. R. Silva March 21, 2018, 2:02 p.m. UTC | #4
On 03/21/2018 08:58 AM, Johannes Berg wrote:
> On Wed, 2018-03-21 at 08:57 -0500, Gustavo A. R. Silva wrote:
>>
>> SHA_DESC_ON_STACK is currently being used in multiple places. But, yeah,
>> I think we can define multiple macros of the same kind and adjust to the
>> characteristics of each the component.
>>
>> How big do you think tfm can get?
> 
> I have no idea, I guess you'll have to take that with Herbert.
> 
> johannes
> 

I see. I'll contact him then.

Thanks for the feedback.
--
Gustavo
diff mbox series

Patch

diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index 2fb6558..c9444bf 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -27,30 +27,42 @@  static const u8 zero[CMAC_TLEN_256];
 void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
 			const u8 *data, size_t data_len, u8 *mic)
 {
-	SHASH_DESC_ON_STACK(desc, tfm);
+	struct shash_desc *shash;
 	u8 out[AES_BLOCK_SIZE];
 
-	desc->tfm = tfm;
+	shash = kmalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
+			GFP_KERNEL);
+	if (!shash)
+		return;
 
-	crypto_shash_init(desc);
-	crypto_shash_update(desc, aad, AAD_LEN);
-	crypto_shash_update(desc, data, data_len - CMAC_TLEN);
-	crypto_shash_finup(desc, zero, CMAC_TLEN, out);
+	shash->tfm = tfm;
+
+	crypto_shash_init(shash);
+	crypto_shash_update(shash, aad, AAD_LEN);
+	crypto_shash_update(shash, data, data_len - CMAC_TLEN);
+	crypto_shash_finup(shash, zero, CMAC_TLEN, out);
 
 	memcpy(mic, out, CMAC_TLEN);
+	kfree(shash);
 }
 
 void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
 			    const u8 *data, size_t data_len, u8 *mic)
 {
-	SHASH_DESC_ON_STACK(desc, tfm);
+	struct shash_desc *shash;
+
+	shash = kmalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
+			GFP_KERNEL);
+	if (!shash)
+		return;
 
-	desc->tfm = tfm;
+	shash->tfm = tfm;
 
-	crypto_shash_init(desc);
-	crypto_shash_update(desc, aad, AAD_LEN);
-	crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
-	crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
+	crypto_shash_init(shash);
+	crypto_shash_update(shash, aad, AAD_LEN);
+	crypto_shash_update(shash, data, data_len - CMAC_TLEN_256);
+	crypto_shash_finup(shash, zero, CMAC_TLEN_256, mic);
+	kfree(shash);
 }
 
 struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],