diff mbox series

security:trusted_tpm2: Fix memory leak in tpm2_key_encode()

Message ID 20220607074650.432834-1-niejianglei2021@163.com (mailing list archive)
State New, archived
Headers show
Series security:trusted_tpm2: Fix memory leak in tpm2_key_encode() | expand

Commit Message

Jianglei Nie June 7, 2022, 7:46 a.m. UTC
The function allocates a memory chunk for scratch by kmalloc(), but
it is never freed through the function, which leads to a memory leak.
Handle those cases with kfree().

Signed-off-by: Jianglei Nie <niejianglei2021@163.com>
---
 security/keys/trusted-keys/trusted_tpm2.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

Comments

Ahmad Fatoum June 7, 2022, 8:34 a.m. UTC | #1
Hello Jianglei,

On 07.06.22 09:46, Jianglei Nie wrote:
> The function allocates a memory chunk for scratch by kmalloc(), but
> it is never freed through the function, which leads to a memory leak.
> Handle those cases with kfree().

Thanks for your patch.

Shouldn't you free scratch before successful return too?

I haven't looked too deeply, but it looks like scratch is indeed
scratch space and data written to it are memcpy'd elsewhere before
the function returns and no pointer derived from it survives after
function return.

If this is indeed the case, consider also to switch this to a goto out.

Cheers,
Ahmad
  

> 
> Signed-off-by: Jianglei Nie <niejianglei2021@163.com>
> ---
>  security/keys/trusted-keys/trusted_tpm2.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
> index 0165da386289..dc9efd6c8b14 100644
> --- a/security/keys/trusted-keys/trusted_tpm2.c
> +++ b/security/keys/trusted-keys/trusted_tpm2.c
> @@ -57,8 +57,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
>  		unsigned char bool[3], *w = bool;
>  		/* tag 0 is emptyAuth */
>  		w = asn1_encode_boolean(w, w + sizeof(bool), true);
> -		if (WARN(IS_ERR(w), "BUG: Boolean failed to encode"))
> +		if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) {
> +			kfree(scratch);
>  			return PTR_ERR(w);
> +		}
>  		work = asn1_encode_tag(work, end_work, 0, bool, w - bool);
>  	}
>  
> @@ -69,8 +71,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
>  	 * trigger, so if it does there's something nefarious going on
>  	 */
>  	if (WARN(work - scratch + pub_len + priv_len + 14 > SCRATCH_SIZE,
> -		 "BUG: scratch buffer is too small"))
> +		 "BUG: scratch buffer is too small")) {
> +		kfree(scratch);
>  		return -EINVAL;
> +	}
>  
>  	work = asn1_encode_integer(work, end_work, options->keyhandle);
>  	work = asn1_encode_octet_string(work, end_work, pub, pub_len);
> @@ -79,8 +83,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
>  	work1 = payload->blob;
>  	work1 = asn1_encode_sequence(work1, work1 + sizeof(payload->blob),
>  				     scratch, work - scratch);
> -	if (WARN(IS_ERR(work1), "BUG: ASN.1 encoder failed"))
> +	if (WARN(IS_ERR(work1), "BUG: ASN.1 encoder failed")) {
> +		kfree(scratch);
>  		return PTR_ERR(work1);
> +	}
>  
>  	return work1 - payload->blob;
>  }
Jarkko Sakkinen June 7, 2022, 10:09 a.m. UTC | #2
"KEYS: trusted: fix memory leak in tpm2_key_encode()"

On Tue, Jun 07, 2022 at 03:46:50PM +0800, Jianglei Nie wrote:
> The function allocates a memory chunk for scratch by kmalloc(), but
                                        ~~~         ~~ 
                                        from        with

There's more than one function in Linux - maybe you'd rather want
to write: "tpm2_key_encode() allocates ..."

> it is never freed through the function, which leads to a memory leak.

You can just write "it is never freed, which leads to a memory leak."

> Handle those cases with kfree().

"Free the memory chunk with kfree() in the return paths."

> Signed-off-by: Jianglei Nie <niejianglei2021@163.com>

Thank you finding this and providing a fix, it is highly appreciated.
Please don't take the nitpicking with the language personally. Just want
to have it documented in appropriate form.

BR, Jarkko
diff mbox series

Patch

diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 0165da386289..dc9efd6c8b14 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -57,8 +57,10 @@  static int tpm2_key_encode(struct trusted_key_payload *payload,
 		unsigned char bool[3], *w = bool;
 		/* tag 0 is emptyAuth */
 		w = asn1_encode_boolean(w, w + sizeof(bool), true);
-		if (WARN(IS_ERR(w), "BUG: Boolean failed to encode"))
+		if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) {
+			kfree(scratch);
 			return PTR_ERR(w);
+		}
 		work = asn1_encode_tag(work, end_work, 0, bool, w - bool);
 	}
 
@@ -69,8 +71,10 @@  static int tpm2_key_encode(struct trusted_key_payload *payload,
 	 * trigger, so if it does there's something nefarious going on
 	 */
 	if (WARN(work - scratch + pub_len + priv_len + 14 > SCRATCH_SIZE,
-		 "BUG: scratch buffer is too small"))
+		 "BUG: scratch buffer is too small")) {
+		kfree(scratch);
 		return -EINVAL;
+	}
 
 	work = asn1_encode_integer(work, end_work, options->keyhandle);
 	work = asn1_encode_octet_string(work, end_work, pub, pub_len);
@@ -79,8 +83,10 @@  static int tpm2_key_encode(struct trusted_key_payload *payload,
 	work1 = payload->blob;
 	work1 = asn1_encode_sequence(work1, work1 + sizeof(payload->blob),
 				     scratch, work - scratch);
-	if (WARN(IS_ERR(work1), "BUG: ASN.1 encoder failed"))
+	if (WARN(IS_ERR(work1), "BUG: ASN.1 encoder failed")) {
+		kfree(scratch);
 		return PTR_ERR(work1);
+	}
 
 	return work1 - payload->blob;
 }