From: Hugo Mills <hugo@carfax.org.uk>
To: Liu Bo <bo.li.liu@oracle.com>
Cc: linux-btrfs@vger.kernel.org
Subject: Re: [PATCH v3] Btrfs: fix out of bounds array access while reading extent buffer
Date: Wed, 9 Aug 2017 18:15:29 +0000 [thread overview]
Message-ID: <20170809181529.GE7140@carfax.org.uk> (raw)
In-Reply-To: <20170809171016.7501-1-bo.li.liu@oracle.com>
[-- Attachment #1: Type: text/plain, Size: 3435 bytes --]
On Wed, Aug 09, 2017 at 11:10:16AM -0600, Liu Bo wrote:
> There is a cornel case that slip through the checkers in functions
^^^^^^ corner
Sorry, that's been bugging me every time it goes past. A cornel is
a kind of tree, apparently.
Hugo.
> reading extent buffer, ie.
>
> if (start < eb->len) and (start + len > eb->len),
> then
>
> a) map_private_extent_buffer() returns immediately because
> it's thinking the range spans across two pages,
>
> b) and the checkers in read_extent_buffer(), WARN_ON(start > eb->len)
> and WARN_ON(start + len > eb->start + eb->len), both are OK in this
> corner case, but it'd actually try to access the eb->pages out of
> bounds because of (start + len > eb->len).
>
> The case is found by switching extent inline ref type from shared data
> ref to non-shared data ref, which is a kind of metadata corruption.
>
> It'd use the wrong helper to access the eb,
> eg. btrfs_extent_data_ref_root(eb, ref) is used but the %ref passing
> here is "struct btrfs_shared_data_ref". And if the extent item
> happens to be the first item in the eb, then offset/length will get
> over eb->len which ends up an invalid memory access.
>
> This is adding proper checks in order to avoid invalid memory access,
> ie. 'general protection fault', before it's too late.
>
> Reviewed-by: Filipe Manana <fdmanana@suse.com>
> Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
> ---
>
> v3: Remove the unnecessary ASSERT and num_pages.
>
> v2: Improve the commit log to clarify that this can only happen if
> metadata is corrupted.
>
> fs/btrfs/extent_io.c | 20 ++++++++++++--------
> 1 file changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 0aff9b2..e6c6853 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -5417,8 +5417,12 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
> size_t start_offset = eb->start & ((u64)PAGE_SIZE - 1);
> unsigned long i = (start_offset + start) >> PAGE_SHIFT;
>
> - WARN_ON(start > eb->len);
> - WARN_ON(start + len > eb->start + eb->len);
> + if (start + len > eb->len) {
> + WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
> + eb->start, eb->len, start, len);
> + memset(dst, 0, len);
> + return;
> + }
>
> offset = (start_offset + start) & (PAGE_SIZE - 1);
>
> @@ -5491,6 +5495,12 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
> unsigned long end_i = (start_offset + start + min_len - 1) >>
> PAGE_SHIFT;
>
> + if (start + min_len > eb->len) {
> + WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
> + eb->start, eb->len, start, min_len);
> + return -EINVAL;
> + }
> +
> if (i != end_i)
> return 1;
>
> @@ -5502,12 +5512,6 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
> *map_start = ((u64)i << PAGE_SHIFT) - start_offset;
> }
>
> - if (start + min_len > eb->len) {
> - WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
> - eb->start, eb->len, start, min_len);
> - return -EINVAL;
> - }
> -
> p = eb->pages[i];
> kaddr = page_address(p);
> *map = kaddr + offset;
--
Hugo Mills | Jazz is the sort of music where no-one plays
hugo@... carfax.org.uk | anything the same way once.
http://carfax.org.uk/ |
PGP: E2AB1DE4 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
next prev parent reply other threads:[~2017-08-09 18:15 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-07 19:39 [PATCH] Btrfs: fix out of bounds array access while reading extent buffer Liu Bo
2017-08-08 8:47 ` Filipe Manana
2017-08-08 17:05 ` Liu Bo
2017-08-09 15:03 ` Filipe Manana
2017-08-09 16:31 ` [PATCH v2] " Liu Bo
2017-08-09 17:35 ` Filipe Manana
2017-08-09 17:40 ` Filipe Manana
2017-08-09 18:03 ` Liu Bo
2017-08-09 17:10 ` [PATCH v3] " Liu Bo
2017-08-09 18:15 ` Hugo Mills [this message]
2017-08-11 0:47 ` Duncan
2017-08-11 21:26 ` [PATCH] " kbuild test robot
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=20170809181529.GE7140@carfax.org.uk \
--to=hugo@carfax.org.uk \
--cc=bo.li.liu@oracle.com \
--cc=linux-btrfs@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.