* [PATCH v4 0/4] btrfs: Enhanced runtime defence against fuzzed images
@ 2020-08-12 6:02 Qu Wenruo
2020-08-12 6:02 ` [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions Qu Wenruo
0 siblings, 1 reply; 6+ messages in thread
From: Qu Wenruo @ 2020-08-12 6:02 UTC (permalink / raw)
To: linux-btrfs; +Cc: Jungyeon Yoon
This patch is revived after one year, as one internal report has hit one
BUG_ON() with real world fs, so I believe this patchset still makes sense.
- Enhanced eb accessors
Not really needed for the fuzzed images, as 448de471cd4c
("btrfs: Check the first key and level for cached extent buffer")
already fixed half of the reported images.
Just add a final layer of safe net.
Just to complain here, two experienced btrfs developer have got
confused by @start, @len in functions like read_extent_buffer() with
logical address.
The best example to solve the confusion is to check the
read_extent_buffer() call in btree_read_extent_buffer_pages().
I'm not sure why this confusion happens or even get spread.
My guess is the extent_buffer::start naming causing the problem.
If so, I would definitely rename extent_buffer::start to
extent_buffer::bytenr at any cost.
Hopes the new commend will address the problem for now.
- BUG_ON() hunt in __btrfs_free_extent()
Kill BUG_ON()s in __btrfs_free_extent(), replace with error reporting
and why it shouldn't happen.
Also add comment on what __btrfs_free_extent() is designed to do, with
two dump-tree examples for newcomers.
- BUG_ON() hunt in __btrfs_inc_extent_ref()
Just like __btrfs_free_extent(), but less comment as
comment for __btrfs_free_extent() should also work for
__btrfs_inc_extent_ref(), and __btrfs_inc_extent_ref() has a better
structure than __btrfs_free_extent().
- Defence against unbalanced empty leaf
- Defence against bad key order across two tree blocks
The last two cases can't be rejected by tree-checker and they are all
cross-eb cases.
Thankfully we can reuse existing first_key check against unbalanced
empty leaf, but needs extra check deep into ctree.c for tree block
merging time check.
Reported-by: Jungyeon Yoon <jungyeon.yoon@gmail.com>
[ Not to mail bombarding the report, thus only RB tag in cover letter ]
Changelog:
v2:
- Remove duplicated error message in WARN() call.
Changed to WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG))
Also move WARN() after btrfs error message.
- Fix a comment error in __btrfs_free_extent()
It's not adding refs to a tree block, but adding the same refs
to an existing tree block ref.
It's impossible a btrfs tree owning the same tree block directly twice.
- Add comment for eb accessors about @start and @len
If anyone could tell me why such confusion between @start @len and
logical address is here, I will definitely solve the root cause no
matter how many codes need to be modified.
- Use bool to replace int where only two values are returned
Also rename to follow the bool type.
- Remove one unrelated change for the error handler in
btrfs_inc_extent_ref()
- Add Reviewed-by tag
v3:
- Rebased to latest misc-next branch
All conflicts can be auto-merged.
v4:
- Remove one patch which is already merged
A little surprised by the fact that git can't detecth such case.
- Add new reviewed-by tags from Josef
Qu Wenruo (4):
btrfs: extent_io: Do extra check for extent buffer read write
functions
btrfs: extent-tree: Kill BUG_ON() in __btrfs_free_extent() and do
better comment
btrfs: extent-tree: Kill the BUG_ON() in
insert_inline_extent_backref()
btrfs: ctree: Checking key orders before merged tree blocks
fs/btrfs/ctree.c | 68 +++++++++++++++++
fs/btrfs/extent-tree.c | 164 +++++++++++++++++++++++++++++++++++++----
fs/btrfs/extent_io.c | 76 +++++++++----------
3 files changed, 257 insertions(+), 51 deletions(-)
--
2.28.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions
2020-08-12 6:02 [PATCH v4 0/4] btrfs: Enhanced runtime defence against fuzzed images Qu Wenruo
@ 2020-08-12 6:02 ` Qu Wenruo
0 siblings, 0 replies; 6+ messages in thread
From: Qu Wenruo @ 2020-08-12 6:02 UTC (permalink / raw)
To: linux-btrfs; +Cc: Josef Bacik
Although we have start, len check for extent buffer reader/write (e.g.
read_extent_buffer()), those checks has its limitations:
- No overflow check
Values like start = 1024 len = -1024 can still pass the basic
(start + len) > eb->len check.
- Checks are not consistent
For read_extent_buffer() we only check (start + len) against eb->len.
While for memcmp_extent_buffer() we also check start against eb->len.
- Different error reporting mechanism
We use WARN() in read_extent_buffer() but BUG() in
memcpy_extent_buffer().
- Still modify memory if the request is obviously wrong
In read_extent_buffer() even we find (start + len) > eb->len, we still
call memset(dst, 0, len), which can eaisly cause memory access error
if start + len overflows.
To address above problems, this patch creates a new common function to
check such access, check_eb_range().
- Add overflow check
This function checks start, start + len against eb->len and overflow
check.
- Unified checks
- Unified error reports
Will call WARN() if CONFIG_BTRFS_DEBUG is configured.
And also do btrfs_warn() message for non-debug build.
- Exit ASAP if check fails
No more possible memory corruption.
- Add extra comment for @start @len used in those functions
Even experienced developers sometimes get confused with the @start
@len with logical address in those functions.
I'm not sure what's the cause, maybe it's the extent_buffer::start
naming.
For now, just add some comment.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=202817
[ Inspired by above report, the report itself is already addressed ]
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/btrfs/extent_io.c | 76 +++++++++++++++++++++++---------------------
1 file changed, 39 insertions(+), 37 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 617ea38e6fd7..9f583ef1e387 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5620,6 +5620,28 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
return ret;
}
+/*
+ * Check if the [start, start + len) range is valid before reading/writing
+ * the eb.
+ * NOTE: @start and @len are offset *INSIDE* the eb, *NOT* logical address.
+ *
+ * Caller should not touch the dst/src memory if this function returns error.
+ */
+static int check_eb_range(const struct extent_buffer *eb, unsigned long start,
+ unsigned long len)
+{
+ /* start, start + len should not go beyond eb->len nor overflow */
+ if (unlikely(start > eb->len || start + len > eb->len ||
+ len > eb->len)) {
+ btrfs_warn(eb->fs_info,
+"btrfs: bad eb rw request, eb bytenr=%llu len=%lu rw start=%lu len=%lu\n",
+ eb->start, eb->len, start, len);
+ WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
+ return -EINVAL;
+ }
+ return 0;
+}
+
void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
unsigned long start, unsigned long len)
{
@@ -5630,12 +5652,8 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
char *dst = (char *)dstv;
unsigned long i = start >> PAGE_SHIFT;
- 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);
+ if (check_eb_range(eb, start, len))
return;
- }
offset = offset_in_page(start);
@@ -5700,8 +5718,8 @@ int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
unsigned long i = start >> PAGE_SHIFT;
int ret = 0;
- WARN_ON(start > eb->len);
- WARN_ON(start + len > eb->start + eb->len);
+ if (check_eb_range(eb, start, len))
+ return -EINVAL;
offset = offset_in_page(start);
@@ -5754,8 +5772,8 @@ void write_extent_buffer(const struct extent_buffer *eb, const void *srcv,
char *src = (char *)srcv;
unsigned long i = start >> PAGE_SHIFT;
- WARN_ON(start > eb->len);
- WARN_ON(start + len > eb->start + eb->len);
+ if (check_eb_range(eb, start, len))
+ return;
offset = offset_in_page(start);
@@ -5783,8 +5801,8 @@ void memzero_extent_buffer(const struct extent_buffer *eb, unsigned long start,
char *kaddr;
unsigned long i = start >> PAGE_SHIFT;
- WARN_ON(start > eb->len);
- WARN_ON(start + len > eb->start + eb->len);
+ if (check_eb_range(eb, start, len))
+ return;
offset = offset_in_page(start);
@@ -5828,6 +5846,10 @@ void copy_extent_buffer(const struct extent_buffer *dst,
char *kaddr;
unsigned long i = dst_offset >> PAGE_SHIFT;
+ if (check_eb_range(dst, dst_offset, len) ||
+ check_eb_range(src, src_offset, len))
+ return;
+
WARN_ON(src->len != dst_len);
offset = offset_in_page(dst_offset);
@@ -6017,25 +6039,15 @@ void memcpy_extent_buffer(const struct extent_buffer *dst,
unsigned long dst_offset, unsigned long src_offset,
unsigned long len)
{
- struct btrfs_fs_info *fs_info = dst->fs_info;
size_t cur;
size_t dst_off_in_page;
size_t src_off_in_page;
unsigned long dst_i;
unsigned long src_i;
- if (src_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus src_offset %lu move len %lu dst len %lu",
- src_offset, len, dst->len);
- BUG();
- }
- if (dst_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus dst_offset %lu move len %lu dst len %lu",
- dst_offset, len, dst->len);
- BUG();
- }
+ if (check_eb_range(dst, dst_offset, len) ||
+ check_eb_range(dst, src_offset, len))
+ return;
while (len > 0) {
dst_off_in_page = offset_in_page(dst_offset);
@@ -6062,7 +6074,6 @@ void memmove_extent_buffer(const struct extent_buffer *dst,
unsigned long dst_offset, unsigned long src_offset,
unsigned long len)
{
- struct btrfs_fs_info *fs_info = dst->fs_info;
size_t cur;
size_t dst_off_in_page;
size_t src_off_in_page;
@@ -6071,18 +6082,9 @@ void memmove_extent_buffer(const struct extent_buffer *dst,
unsigned long dst_i;
unsigned long src_i;
- if (src_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus src_offset %lu move len %lu len %lu",
- src_offset, len, dst->len);
- BUG();
- }
- if (dst_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus dst_offset %lu move len %lu len %lu",
- dst_offset, len, dst->len);
- BUG();
- }
+ if (check_eb_range(dst, dst_offset, len) ||
+ check_eb_range(dst, src_offset, len))
+ return;
if (dst_offset < src_offset) {
memcpy_extent_buffer(dst, dst_offset, src_offset, len);
return;
--
2.28.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions
2020-08-14 0:47 ` Qu Wenruo
@ 2020-08-14 10:29 ` David Sterba
0 siblings, 0 replies; 6+ messages in thread
From: David Sterba @ 2020-08-14 10:29 UTC (permalink / raw)
To: Qu Wenruo; +Cc: dsterba, Qu Wenruo, linux-btrfs, Josef Bacik
On Fri, Aug 14, 2020 at 08:47:17AM +0800, Qu Wenruo wrote:
>
>
> On 2020/8/13 下午10:05, David Sterba wrote:
> > On Wed, Aug 12, 2020 at 02:05:06PM +0800, Qu Wenruo wrote:
> >> +/*
> >> + * Check if the [start, start + len) range is valid before reading/writing
> >> + * the eb.
> >> + * NOTE: @start and @len are offset *INSIDE* the eb, *NOT* logical address.
> >> + *
> >> + * Caller should not touch the dst/src memory if this function returns error.
> >> + */
> >> +static int check_eb_range(const struct extent_buffer *eb, unsigned long start,
> >> + unsigned long len)
> >> +{
> >> + /* start, start + len should not go beyond eb->len nor overflow */
> >> + if (unlikely(start > eb->len || start + len > eb->len ||
> >> + len > eb->len)) {
> >> + btrfs_warn(eb->fs_info,
> >> +"btrfs: bad eb rw request, eb bytenr=%llu len=%lu rw start=%lu len=%lu\n",
> >> + eb->start, eb->len, start, len);
> >> + WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
> >> + return -EINVAL;
> >> + }
> >> + return 0;
> >> +}
> >
> > This helper is similar to the check_setget_bounds that have some
> > performance impact,
> > https://lore.kernel.org/linux-btrfs/20200730110943.GE3703@twin.jikos.cz/
> > .
> >
> > The extent buffer helpers are not called that often as the setget
> > helpers but still it could be improved to avoid the function call
> > penalty on the hot path.
> >
> > static inline in check_eb_range(...) {
> > if (unlikely(out of range))
> > return report_eb_range(...)
> > return 0;
> > }
>
> I thought we should avoid manual inline, but let the compiler to
> determine if it's needed.
>
> Or in this particular case, we're better than the compiler?
In general it shouldn't be necessary to inline or partition the
functions. In the check_setget case it had a noticeable impact on
performance, so crafting the hot path manually produces a better
assembly and does not depend on the compiler optimizations. The
important part here is that this has been analyzed and measured that it
really makes a difference.
For sanity checks I think we should try to make it as fast as possible,
it's better to have them then not but we also don't want to sacrifice
performance. I haven't analyzed the asm code impact in this patch but
the pattern and flow of check_eb_range is the same.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions
2020-08-13 14:05 ` David Sterba
@ 2020-08-14 0:47 ` Qu Wenruo
2020-08-14 10:29 ` David Sterba
0 siblings, 1 reply; 6+ messages in thread
From: Qu Wenruo @ 2020-08-14 0:47 UTC (permalink / raw)
To: dsterba, Qu Wenruo, linux-btrfs, Josef Bacik
[-- Attachment #1.1: Type: text/plain, Size: 1743 bytes --]
On 2020/8/13 下午10:05, David Sterba wrote:
> On Wed, Aug 12, 2020 at 02:05:06PM +0800, Qu Wenruo wrote:
>> +/*
>> + * Check if the [start, start + len) range is valid before reading/writing
>> + * the eb.
>> + * NOTE: @start and @len are offset *INSIDE* the eb, *NOT* logical address.
>> + *
>> + * Caller should not touch the dst/src memory if this function returns error.
>> + */
>> +static int check_eb_range(const struct extent_buffer *eb, unsigned long start,
>> + unsigned long len)
>> +{
>> + /* start, start + len should not go beyond eb->len nor overflow */
>> + if (unlikely(start > eb->len || start + len > eb->len ||
>> + len > eb->len)) {
>> + btrfs_warn(eb->fs_info,
>> +"btrfs: bad eb rw request, eb bytenr=%llu len=%lu rw start=%lu len=%lu\n",
>> + eb->start, eb->len, start, len);
>> + WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
>> + return -EINVAL;
>> + }
>> + return 0;
>> +}
>
> This helper is similar to the check_setget_bounds that have some
> performance impact,
> https://lore.kernel.org/linux-btrfs/20200730110943.GE3703@twin.jikos.cz/
> .
>
> The extent buffer helpers are not called that often as the setget
> helpers but still it could be improved to avoid the function call
> penalty on the hot path.
>
> static inline in check_eb_range(...) {
> if (unlikely(out of range))
> return report_eb_range(...)
> return 0;
> }
I thought we should avoid manual inline, but let the compiler to
determine if it's needed.
Or in this particular case, we're better than the compiler?
Thanks,
Qu
>
> In the original code the range check was open coded and the above will
> lead to the same asm output, while keeping the C code readable.
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions
2020-08-12 6:05 ` [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions Qu Wenruo
@ 2020-08-13 14:05 ` David Sterba
2020-08-14 0:47 ` Qu Wenruo
0 siblings, 1 reply; 6+ messages in thread
From: David Sterba @ 2020-08-13 14:05 UTC (permalink / raw)
To: Qu Wenruo; +Cc: linux-btrfs, Josef Bacik
On Wed, Aug 12, 2020 at 02:05:06PM +0800, Qu Wenruo wrote:
> +/*
> + * Check if the [start, start + len) range is valid before reading/writing
> + * the eb.
> + * NOTE: @start and @len are offset *INSIDE* the eb, *NOT* logical address.
> + *
> + * Caller should not touch the dst/src memory if this function returns error.
> + */
> +static int check_eb_range(const struct extent_buffer *eb, unsigned long start,
> + unsigned long len)
> +{
> + /* start, start + len should not go beyond eb->len nor overflow */
> + if (unlikely(start > eb->len || start + len > eb->len ||
> + len > eb->len)) {
> + btrfs_warn(eb->fs_info,
> +"btrfs: bad eb rw request, eb bytenr=%llu len=%lu rw start=%lu len=%lu\n",
> + eb->start, eb->len, start, len);
> + WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
> + return -EINVAL;
> + }
> + return 0;
> +}
This helper is similar to the check_setget_bounds that have some
performance impact,
https://lore.kernel.org/linux-btrfs/20200730110943.GE3703@twin.jikos.cz/
.
The extent buffer helpers are not called that often as the setget
helpers but still it could be improved to avoid the function call
penalty on the hot path.
static inline in check_eb_range(...) {
if (unlikely(out of range))
return report_eb_range(...)
return 0;
}
In the original code the range check was open coded and the above will
lead to the same asm output, while keeping the C code readable.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions
2020-08-12 6:05 [PATCH v4 0/4] btrfs: Enhanced runtime defence against fuzzed images Qu Wenruo
@ 2020-08-12 6:05 ` Qu Wenruo
2020-08-13 14:05 ` David Sterba
0 siblings, 1 reply; 6+ messages in thread
From: Qu Wenruo @ 2020-08-12 6:05 UTC (permalink / raw)
To: linux-btrfs; +Cc: Josef Bacik
Although we have start, len check for extent buffer reader/write (e.g.
read_extent_buffer()), those checks has its limitations:
- No overflow check
Values like start = 1024 len = -1024 can still pass the basic
(start + len) > eb->len check.
- Checks are not consistent
For read_extent_buffer() we only check (start + len) against eb->len.
While for memcmp_extent_buffer() we also check start against eb->len.
- Different error reporting mechanism
We use WARN() in read_extent_buffer() but BUG() in
memcpy_extent_buffer().
- Still modify memory if the request is obviously wrong
In read_extent_buffer() even we find (start + len) > eb->len, we still
call memset(dst, 0, len), which can eaisly cause memory access error
if start + len overflows.
To address above problems, this patch creates a new common function to
check such access, check_eb_range().
- Add overflow check
This function checks start, start + len against eb->len and overflow
check.
- Unified checks
- Unified error reports
Will call WARN() if CONFIG_BTRFS_DEBUG is configured.
And also do btrfs_warn() message for non-debug build.
- Exit ASAP if check fails
No more possible memory corruption.
- Add extra comment for @start @len used in those functions
Even experienced developers sometimes get confused with the @start
@len with logical address in those functions.
I'm not sure what's the cause, maybe it's the extent_buffer::start
naming.
For now, just add some comment.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=202817
[ Inspired by above report, the report itself is already addressed ]
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/btrfs/extent_io.c | 76 +++++++++++++++++++++++---------------------
1 file changed, 39 insertions(+), 37 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 617ea38e6fd7..9f583ef1e387 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5620,6 +5620,28 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
return ret;
}
+/*
+ * Check if the [start, start + len) range is valid before reading/writing
+ * the eb.
+ * NOTE: @start and @len are offset *INSIDE* the eb, *NOT* logical address.
+ *
+ * Caller should not touch the dst/src memory if this function returns error.
+ */
+static int check_eb_range(const struct extent_buffer *eb, unsigned long start,
+ unsigned long len)
+{
+ /* start, start + len should not go beyond eb->len nor overflow */
+ if (unlikely(start > eb->len || start + len > eb->len ||
+ len > eb->len)) {
+ btrfs_warn(eb->fs_info,
+"btrfs: bad eb rw request, eb bytenr=%llu len=%lu rw start=%lu len=%lu\n",
+ eb->start, eb->len, start, len);
+ WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
+ return -EINVAL;
+ }
+ return 0;
+}
+
void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
unsigned long start, unsigned long len)
{
@@ -5630,12 +5652,8 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
char *dst = (char *)dstv;
unsigned long i = start >> PAGE_SHIFT;
- 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);
+ if (check_eb_range(eb, start, len))
return;
- }
offset = offset_in_page(start);
@@ -5700,8 +5718,8 @@ int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
unsigned long i = start >> PAGE_SHIFT;
int ret = 0;
- WARN_ON(start > eb->len);
- WARN_ON(start + len > eb->start + eb->len);
+ if (check_eb_range(eb, start, len))
+ return -EINVAL;
offset = offset_in_page(start);
@@ -5754,8 +5772,8 @@ void write_extent_buffer(const struct extent_buffer *eb, const void *srcv,
char *src = (char *)srcv;
unsigned long i = start >> PAGE_SHIFT;
- WARN_ON(start > eb->len);
- WARN_ON(start + len > eb->start + eb->len);
+ if (check_eb_range(eb, start, len))
+ return;
offset = offset_in_page(start);
@@ -5783,8 +5801,8 @@ void memzero_extent_buffer(const struct extent_buffer *eb, unsigned long start,
char *kaddr;
unsigned long i = start >> PAGE_SHIFT;
- WARN_ON(start > eb->len);
- WARN_ON(start + len > eb->start + eb->len);
+ if (check_eb_range(eb, start, len))
+ return;
offset = offset_in_page(start);
@@ -5828,6 +5846,10 @@ void copy_extent_buffer(const struct extent_buffer *dst,
char *kaddr;
unsigned long i = dst_offset >> PAGE_SHIFT;
+ if (check_eb_range(dst, dst_offset, len) ||
+ check_eb_range(src, src_offset, len))
+ return;
+
WARN_ON(src->len != dst_len);
offset = offset_in_page(dst_offset);
@@ -6017,25 +6039,15 @@ void memcpy_extent_buffer(const struct extent_buffer *dst,
unsigned long dst_offset, unsigned long src_offset,
unsigned long len)
{
- struct btrfs_fs_info *fs_info = dst->fs_info;
size_t cur;
size_t dst_off_in_page;
size_t src_off_in_page;
unsigned long dst_i;
unsigned long src_i;
- if (src_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus src_offset %lu move len %lu dst len %lu",
- src_offset, len, dst->len);
- BUG();
- }
- if (dst_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus dst_offset %lu move len %lu dst len %lu",
- dst_offset, len, dst->len);
- BUG();
- }
+ if (check_eb_range(dst, dst_offset, len) ||
+ check_eb_range(dst, src_offset, len))
+ return;
while (len > 0) {
dst_off_in_page = offset_in_page(dst_offset);
@@ -6062,7 +6074,6 @@ void memmove_extent_buffer(const struct extent_buffer *dst,
unsigned long dst_offset, unsigned long src_offset,
unsigned long len)
{
- struct btrfs_fs_info *fs_info = dst->fs_info;
size_t cur;
size_t dst_off_in_page;
size_t src_off_in_page;
@@ -6071,18 +6082,9 @@ void memmove_extent_buffer(const struct extent_buffer *dst,
unsigned long dst_i;
unsigned long src_i;
- if (src_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus src_offset %lu move len %lu len %lu",
- src_offset, len, dst->len);
- BUG();
- }
- if (dst_offset + len > dst->len) {
- btrfs_err(fs_info,
- "memmove bogus dst_offset %lu move len %lu len %lu",
- dst_offset, len, dst->len);
- BUG();
- }
+ if (check_eb_range(dst, dst_offset, len) ||
+ check_eb_range(dst, src_offset, len))
+ return;
if (dst_offset < src_offset) {
memcpy_extent_buffer(dst, dst_offset, src_offset, len);
return;
--
2.28.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-08-14 10:30 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-12 6:02 [PATCH v4 0/4] btrfs: Enhanced runtime defence against fuzzed images Qu Wenruo
2020-08-12 6:02 ` [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions Qu Wenruo
2020-08-12 6:05 [PATCH v4 0/4] btrfs: Enhanced runtime defence against fuzzed images Qu Wenruo
2020-08-12 6:05 ` [PATCH v4 1/4] btrfs: extent_io: Do extra check for extent buffer read write functions Qu Wenruo
2020-08-13 14:05 ` David Sterba
2020-08-14 0:47 ` Qu Wenruo
2020-08-14 10:29 ` David Sterba
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.