linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: Johannes Thumshirn <jth@kernel.org>
Cc: David Sterba <dsterba@suse.cz>,
	linux-fsdevel@vger.kernel.org, linux-btrfs@vger.kernel.org,
	Richard Weinberger <richard@nod.at>,
	Johannes Thumshirn <johannes.thumshirn@wdc.com>,
	Johannes Thumshirn <jthumshirn@suse.de>
Subject: Re: [PATCH v2 1/2] btrfs: add authentication support
Date: Thu, 30 Apr 2020 22:39:08 -0700	[thread overview]
Message-ID: <20200501053908.GC1003@sol.localdomain> (raw)
In-Reply-To: <20200428105859.4719-2-jth@kernel.org>

On Tue, Apr 28, 2020 at 12:58:58PM +0200, Johannes Thumshirn wrote:
> From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
> 
> Add authentication support for a BTRFS file-system.
> 
> This works, because in BTRFS every meta-data block as well as every
> data-block has a own checksum. For meta-data the checksum is in the
> meta-data node itself. For data blocks, the checksums are stored in the
> checksum tree.
> 
> When replacing the checksum algorithm with a keyed hash, like HMAC(SHA256),
> a key is needed to mount a verified file-system. This key also needs to be
> used at file-system creation time.
> 
> We have to used a keyed hash scheme, in contrast to doing a normal
> cryptographic hash, to guarantee integrity of the file system, as a
> potential attacker could just replay file-system operations and the
> changes would go unnoticed.
> 
> Having a keyed hash only on the topmost Node of a tree or even just in the
> super-block and using cryptographic hashes on the normal meta-data nodes
> and checksum tree entries doesn't work either, as the BTRFS B-Tree's Nodes
> do not include the checksums of their respective child nodes, but only the
> block pointers and offsets where to find them on disk.
> 
> Also note, we do not need a incompat R/O flag for this, because if an old
> kernel tries to mount an authenticated file-system it will fail the
> initial checksum type verification and thus refuses to mount.
> 
> The key has to be supplied by the kernel's keyring and the method of
> getting the key securely into the kernel is not subject of this patch.

This is a good idea, but can you explain exactly what security properties you
aim to achieve?

As far as I can tell, btrfs hashes each data block individually.  There's no
contextual information about where eaech block is located or which file(s) it
belongs to.  So, with this proposal, an attacker can still replace any data
block with any other data block.  Is that what you have in mind?  Have you
considered including contextual information in the hashes, to prevent this?

What about metadata blocks -- how well are they authenticated?  Can they be
moved around?  And does this proposal authenticate *everything* on the
filesystem, or is there any part that is missed?  What about the superblock?

You also mentioned preventing replay of filesystem operations, which suggests
you're trying to achieve rollback protection.  But actually this scheme doesn't
provide rollback protection.  For one, an attacker can always just rollback the
entire filesystem to a previous state.

This feature would still be useful even with the above limitations.  But what is
your goal exactly?  Can this be made better?

> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index d10c7be10f3b..fe403fb62178 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -17,6 +17,7 @@
>  #include <linux/error-injection.h>
>  #include <linux/crc32c.h>
>  #include <linux/sched/mm.h>
> +#include <keys/user-type.h>
>  #include <asm/unaligned.h>
>  #include <crypto/hash.h>
>  #include "ctree.h"
> @@ -339,6 +340,7 @@ static bool btrfs_supported_super_csum(u16 csum_type)
>  	case BTRFS_CSUM_TYPE_XXHASH:
>  	case BTRFS_CSUM_TYPE_SHA256:
>  	case BTRFS_CSUM_TYPE_BLAKE2:
> +	case BTRFS_CSUM_TYPE_HMAC_SHA256:
>  		return true;
>  	default:
>  		return false;
> @@ -2187,6 +2189,9 @@ static int btrfs_init_csum_hash(struct btrfs_fs_info *fs_info, u16 csum_type)
>  {
>  	struct crypto_shash *csum_shash;
>  	const char *csum_driver = btrfs_super_csum_driver(csum_type);
> +	struct key *key;
> +	const struct user_key_payload *ukp;
> +	int err = 0;
>  
>  	csum_shash = crypto_alloc_shash(csum_driver, 0, 0);
>  
> @@ -2198,7 +2203,53 @@ static int btrfs_init_csum_hash(struct btrfs_fs_info *fs_info, u16 csum_type)
>  
>  	fs_info->csum_shash = csum_shash;
>  
> -	return 0;
> +	/*
> +	 * if we're not doing authentication, we're done by now. Still we have
> +	 * to validate the possible combinations of BTRFS_MOUNT_AUTH_KEY and
> +	 * keyed hashes.
> +	 */
> +	if (csum_type == BTRFS_CSUM_TYPE_HMAC_SHA256 &&
> +	    !btrfs_test_opt(fs_info, AUTH_KEY)) {
> +		crypto_free_shash(fs_info->csum_shash);
> +		return -EINVAL;

Seems there should be an error message here that says that a key is needed.

> +	} else if (btrfs_test_opt(fs_info, AUTH_KEY)
> +		   && csum_type != BTRFS_CSUM_TYPE_HMAC_SHA256) {
> +		crypto_free_shash(fs_info->csum_shash);
> +		return -EINVAL;

The hash algorithm needs to be passed as a mount option.  Otherwise the attacker
gets to choose it for you among all the supported keyed hash algorithms, as soon
as support for a second one is added.  Maybe use 'auth_hash_name' like UBIFS
does?

> +	} else if (!btrfs_test_opt(fs_info, AUTH_KEY)) {
> +		/*
> +		 * This is the normal case, if noone want's authentication and
> +		 * doesn't have a keyed hash, we're done.
> +		 */
> +		return 0;
> +	}
> +
> +	key = request_key(&key_type_logon, fs_info->auth_key_name, NULL);
> +	if (IS_ERR(key))
> +		return PTR_ERR(key);

Seems this should print an error message if the key can't be found.

Also, this should enforce that the key description uses a service prefix by
formatting it as kasprintf("btrfs:%s", fs_info->auth_key_name).  Otherwise
people can abuse this feature to use keys that were added for other kernel
features.  (This already got screwed up elsewhere, which makes the "logon" key
type a bit of a disaster.  But there's no need to make it worse.)

- Eric

  parent reply	other threads:[~2020-05-01  5:39 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-28 10:58 [PATCH v2 0/2] Add file-system authentication to BTRFS Johannes Thumshirn
2020-04-28 10:58 ` [PATCH v2 1/2] btrfs: add authentication support Johannes Thumshirn
2020-04-29  7:23   ` kbuild test robot
2020-04-29 11:46   ` Johannes Thumshirn
2020-05-01  5:39   ` Eric Biggers [this message]
2020-05-01  6:30     ` Eric Biggers
2020-05-04  8:38       ` Johannes Thumshirn
2020-05-05 22:33         ` David Sterba
2020-05-06  8:10           ` Johannes Thumshirn
2020-05-04 10:09     ` Johannes Thumshirn
2020-05-04 20:59       ` Eric Biggers
2020-05-05  8:11         ` Johannes Thumshirn
2020-05-05  9:26           ` Qu Wenruo
2020-05-05  9:59             ` Qu Wenruo
2020-05-05 22:32               ` David Sterba
2020-05-05 23:55                 ` Qu Wenruo
2020-05-06 20:40             ` btree [was Re: [PATCH v2 1/2] btrfs: add authentication support] Goffredo Baroncelli
2020-05-05 22:19           ` [PATCH v2 1/2] btrfs: add authentication support David Sterba
2020-05-05 22:37           ` Eric Biggers
2020-05-06  8:30             ` Johannes Thumshirn
2020-05-05 22:14         ` David Sterba
2020-05-05 22:31           ` Eric Biggers
2020-05-05 22:46             ` David Sterba
2020-05-05 23:31               ` Eric Biggers
2020-05-06  0:29                 ` David Sterba
2020-05-06  0:44                   ` Eric Biggers
2020-05-04 21:37       ` Richard Weinberger
2020-05-05  7:46         ` Johannes Thumshirn
2020-05-05 11:56           ` Richard Weinberger
2020-05-04 21:59   ` Richard Weinberger
2020-05-05  7:55     ` Johannes Thumshirn
2020-05-05 12:36       ` Jeff Mahoney
2020-05-05 12:39         ` Qu Wenruo
2020-05-05 12:41           ` Jeff Mahoney
2020-05-05 12:48             ` Qu Wenruo
2020-05-05 23:02           ` David Sterba
2020-05-06 21:24         ` Goffredo Baroncelli
2020-05-05 23:00     ` David Sterba
2020-05-05  9:43   ` Qu Wenruo
2020-05-06 20:59     ` Goffredo Baroncelli
2020-04-28 10:58 ` [PATCH v2 2/2] btrfs: rename btrfs_parse_device_options back to btrfs_parse_early_options Johannes Thumshirn
2020-05-01  6:03 ` [PATCH v2 0/2] Add file-system authentication to BTRFS Eric Biggers
2020-05-04  8:39   ` Johannes Thumshirn
2020-05-05 23:16   ` David Sterba
2020-05-01 21:26 ` Jason A. Donenfeld
2020-05-05 23:38   ` David Sterba

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200501053908.GC1003@sol.localdomain \
    --to=ebiggers@kernel.org \
    --cc=dsterba@suse.cz \
    --cc=johannes.thumshirn@wdc.com \
    --cc=jth@kernel.org \
    --cc=jthumshirn@suse.de \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=richard@nod.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).