2018-02-05 20:03:58

by Jin Qian

[permalink] [raw]
Subject: [PATCH 1/1] KEYS: encrypted: fix buffer overread in valid_master_desc()

From: Eric Biggers <[email protected]>

commit 794b4bc292f5d31739d89c0202c54e7dc9bc3add upstream

With the 'encrypted' key type it was possible for userspace to provide a
data blob ending with a master key description shorter than expected,
e.g. 'keyctl add encrypted desc "new x" @s'. When validating such a
master key description, validate_master_desc() could read beyond the end
of the buffer. Fix this by using strncmp() instead of memcmp(). [Also
clean up the code to deduplicate some logic.]

Cc: [email protected]
Cc: Mimi Zohar <[email protected]>
Signed-off-by: Eric Biggers <[email protected]>
Signed-off-by: David Howells <[email protected]>
Signed-off-by: James Morris <[email protected]>
Signed-off-by: Jin Qian <[email protected]>
---
security/keys/encrypted-keys/encrypted.c | 31 +++++++++++++++----------------
1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index a871159bf03c..ead2fd60244d 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -141,23 +141,22 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc)
*/
static int valid_master_desc(const char *new_desc, const char *orig_desc)
{
- if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) {
- if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN)
- goto out;
- if (orig_desc)
- if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN))
- goto out;
- } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) {
- if (strlen(new_desc) == KEY_USER_PREFIX_LEN)
- goto out;
- if (orig_desc)
- if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN))
- goto out;
- } else
- goto out;
+ int prefix_len;
+
+ if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN))
+ prefix_len = KEY_TRUSTED_PREFIX_LEN;
+ else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN))
+ prefix_len = KEY_USER_PREFIX_LEN;
+ else
+ return -EINVAL;
+
+ if (!new_desc[prefix_len])
+ return -EINVAL;
+
+ if (orig_desc && strncmp(new_desc, orig_desc, prefix_len))
+ return -EINVAL;
+
return 0;
-out:
- return -EINVAL;
}

/*
--
2.16.0.rc1.238.g530d649a79-goog



2018-02-06 01:57:17

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 1/1] KEYS: encrypted: fix buffer overread in valid_master_desc()

On Mon, Feb 05, 2018 at 12:02:46PM -0800, Jin Qian wrote:
> From: Eric Biggers <[email protected]>
>
> commit 794b4bc292f5d31739d89c0202c54e7dc9bc3add upstream
>
> With the 'encrypted' key type it was possible for userspace to provide a
> data blob ending with a master key description shorter than expected,
> e.g. 'keyctl add encrypted desc "new x" @s'. When validating such a
> master key description, validate_master_desc() could read beyond the end
> of the buffer. Fix this by using strncmp() instead of memcmp(). [Also
> clean up the code to deduplicate some logic.]
>
> Cc: [email protected]
> Cc: Mimi Zohar <[email protected]>
> Signed-off-by: Eric Biggers <[email protected]>
> Signed-off-by: David Howells <[email protected]>
> Signed-off-by: James Morris <[email protected]>
> Signed-off-by: Jin Qian <[email protected]>
> ---
> security/keys/encrypted-keys/encrypted.c | 31 +++++++++++++++----------------
> 1 file changed, 15 insertions(+), 16 deletions(-)
>

Hi Jin, see Documentation/stable_kernel_rules.txt -- patches for stable should
be sent To: [email protected] (and generally with a lighter Cc: list,
unless it's a complicated backport), and you need to say which kernel version(s)
it should be applied to. Also for upstream commits that cherry-pick cleanly,
such as this one, you don't need to send an actual patch but rather just request
that it be applied. The reason it should be applied is helpful too; in this
case the commit fixes a bug that caused a KASAN warning.

Thanks!

- Eric