Re: [PATCH] eCryptfs: Check array bounds for filename characters

From: Tyler Hicks
Date: Mon Nov 21 2011 - 18:46:55 EST


On 2011-11-21 15:32:58, Michael Halcrow wrote:
> Characters with ASCII values greater than the size of
> filename_rev_map[] are valid filename
> characters. ecryptfs_decode_from_filename() will access kernel memory
> beyond that array, and ecryptfs_parse_tag_70_packet() will then
> decrypt those characters. The attacker, using the FNEK of the crafted
> file, can then re-encrypt the characters to reveal the kernel memory
> past the end of the filename_rev_map[] array. I expect low security
> impact since this array is statically allocated in the text area, and
> the amount of memory past the array that is accessible is limited by
> the largest possible ASCII filename character.
>
> This change verifies that the offset into filename_rev_map[] is within
> bounds. If any one character is not, then eCryptfs will consider the
> filename to not be a valid encrypted filename and will copy it
> verbatim rather than try to decode/decrypt it.
>
> Signed-off-by: Mike Halcrow <mhalcrow@xxxxxxxxxx>

Linus - This is a pretty low security risk, but I figure that it is
probably best if you apply it directly to your tree. I don't think there
is much need for it to go through my tree. If you do take it in, feel
free to add the following tags:

Cc: <stable@xxxxxxxxxx>
Acked-by: Tyler Hicks <tyhicks@xxxxxxxxxxxxx>

BTW, I reviewed and tested this patch before Mike sent it out to the
list.

Tyler

>
> diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
> index 58609bd..d2d2b9e 100644
> --- a/fs/ecryptfs/crypto.c
> +++ b/fs/ecryptfs/crypto.c
> @@ -2032,11 +2032,14 @@ out:
> * @dst_size: Set to the size of the decoded string.
> * @src: The encoded set of octets to decode.
> * @src_size: The size of the encoded set of octets to decode.
> + *
> + * Returns zero on success; non-zero otherwise
> */
> -static void
> +static int
> ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
> const unsigned char *src, size_t src_size)
> {
> + int rc = 0;
> u8 current_bit_offset = 0;
> size_t src_byte_offset = 0;
> size_t dst_byte_offset = 0;
> @@ -2052,9 +2055,13 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
> goto out;
> }
> while (src_byte_offset < src_size) {
> - unsigned char src_byte =
> - filename_rev_map[(int)src[src_byte_offset]];
> -
> + int rev_map_offset = (int)src[src_byte_offset];
> + unsigned char src_byte;
> + if (rev_map_offset > (ARRAY_SIZE(filename_rev_map) - 1)) {
> + rc = -EINVAL;
> + goto out;
> + }
> + src_byte = filename_rev_map[rev_map_offset];
> switch (current_bit_offset) {
> case 0:
> dst[dst_byte_offset] = (src_byte << 2);
> @@ -2081,7 +2088,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
> }
> (*dst_size) = dst_byte_offset;
> out:
> - return;
> + return rc;
> }
>
> /**
> @@ -2235,8 +2242,14 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name,
>
> name += ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
> name_size -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
> - ecryptfs_decode_from_filename(NULL, &decoded_name_size,
> - name, name_size);
> + rc = ecryptfs_decode_from_filename(NULL, &decoded_name_size,
> + name, name_size);
> + if (rc) {
> + rc = ecryptfs_copy_filename(plaintext_name,
> + plaintext_name_size,
> + orig_name, orig_name_size);
> + goto out;
> + }
> decoded_name = kmalloc(decoded_name_size, GFP_KERNEL);
> if (!decoded_name) {
> printk(KERN_ERR "%s: Out of memory whilst attempting "
> @@ -2245,8 +2258,16 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name,
> rc = -ENOMEM;
> goto out;
> }
> - ecryptfs_decode_from_filename(decoded_name, &decoded_name_size,
> - name, name_size);
> + rc = ecryptfs_decode_from_filename(decoded_name,
> + &decoded_name_size,
> + name,
> + name_size);
> + if (rc) {
> + rc = ecryptfs_copy_filename(plaintext_name,
> + plaintext_name_size,
> + orig_name, orig_name_size);
> + goto out_free;
> + }
> rc = ecryptfs_parse_tag_70_packet(plaintext_name,
> plaintext_name_size,
> &packet_size,

Attachment: signature.asc
Description: Digital signature