linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] btrfs: tree-checker: Check level for leaves and nodes
@ 2018-09-27 23:59 Qu Wenruo
  2018-09-28  0:32 ` Su Yue
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Qu Wenruo @ 2018-09-27 23:59 UTC (permalink / raw)
  To: linux-btrfs

Although we have tree level check at tree read runtime, it's completely
based on its parent level.
We still need to do accurate level check to avoid invalid tree blocks
sneak into kernel space.

The check itself is simple, for leaf its level should always be 0.
For nodes its level should be in range [1, BTRFS_MAX_LEVEL - 1].

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/tree-checker.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index db835635372f..cab0b1f1f741 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -487,6 +487,13 @@ static int check_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf,
 	u32 nritems = btrfs_header_nritems(leaf);
 	int slot;
 
+	if (btrfs_header_level(leaf) != 0) {
+		generic_err(fs_info, leaf, 0,
+			"invalid level for leaf, have %d expect 0",
+			btrfs_header_level(leaf));
+		return -EUCLEAN;
+	}
+
 	/*
 	 * Extent buffers from a relocation tree have a owner field that
 	 * corresponds to the subvolume tree they are based on. So just from an
@@ -645,9 +652,16 @@ int btrfs_check_node(struct btrfs_fs_info *fs_info, struct extent_buffer *node)
 	unsigned long nr = btrfs_header_nritems(node);
 	struct btrfs_key key, next_key;
 	int slot;
+	int level = btrfs_header_level(node);
 	u64 bytenr;
 	int ret = 0;
 
+	if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
+		generic_err(fs_info, node, 0,
+			"invalid level for node, have %d expect [1, %d]",
+			level, BTRFS_MAX_LEVEL - 1);
+		return -EUCLEAN;
+	}
 	if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) {
 		btrfs_crit(fs_info,
 "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]",
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: tree-checker: Check level for leaves and nodes
  2018-09-27 23:59 [PATCH] btrfs: tree-checker: Check level for leaves and nodes Qu Wenruo
@ 2018-09-28  0:32 ` Su Yue
  2018-09-28  1:08 ` Su Yue
  2018-10-02 13:13 ` David Sterba
  2 siblings, 0 replies; 5+ messages in thread
From: Su Yue @ 2018-09-28  0:32 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs



> Sent: Friday, September 28, 2018 at 7:59 AM
> From: "Qu Wenruo" <wqu@suse.com>
> To: linux-btrfs@vger.kernel.org
> Subject: [PATCH] btrfs: tree-checker: Check level for leaves and nodes
>
> Although we have tree level check at tree read runtime, it's completely
> based on its parent level.
> We still need to do accurate level check to avoid invalid tree blocks
> sneak into kernel space.
> 
> The check itself is simple, for leaf its level should always be 0.
> For nodes its level should be in range [1, BTRFS_MAX_LEVEL - 1].
> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>

Reviewed-by: Su Yue <suy.fnst@cn.fujitsu.com>
> ---
>  fs/btrfs/tree-checker.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
> index db835635372f..cab0b1f1f741 100644
> --- a/fs/btrfs/tree-checker.c
> +++ b/fs/btrfs/tree-checker.c
> @@ -487,6 +487,13 @@ static int check_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf,
>  	u32 nritems = btrfs_header_nritems(leaf);
>  	int slot;
>  
> +	if (btrfs_header_level(leaf) != 0) {
> +		generic_err(fs_info, leaf, 0,
> +			"invalid level for leaf, have %d expect 0",
> +			btrfs_header_level(leaf));
> +		return -EUCLEAN;
> +	}
> +
>  	/*
>  	 * Extent buffers from a relocation tree have a owner field that
>  	 * corresponds to the subvolume tree they are based on. So just from an
> @@ -645,9 +652,16 @@ int btrfs_check_node(struct btrfs_fs_info *fs_info, struct extent_buffer *node)
>  	unsigned long nr = btrfs_header_nritems(node);
>  	struct btrfs_key key, next_key;
>  	int slot;
> +	int level = btrfs_header_level(node);
>  	u64 bytenr;
>  	int ret = 0;
>  
> +	if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
> +		generic_err(fs_info, node, 0,
> +			"invalid level for node, have %d expect [1, %d]",
> +			level, BTRFS_MAX_LEVEL - 1);
> +		return -EUCLEAN;
> +	}
>  	if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) {
>  		btrfs_crit(fs_info,
>  "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]",
> -- 
> 2.19.0
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: tree-checker: Check level for leaves and nodes
  2018-09-28  1:08 ` Su Yue
@ 2018-09-28  1:03   ` Qu Wenruo
  0 siblings, 0 replies; 5+ messages in thread
From: Qu Wenruo @ 2018-09-28  1:03 UTC (permalink / raw)
  To: Su Yue, linux-btrfs



On 2018/9/28 上午9:08, Su Yue wrote:
> 
> 
> On 9/28/18 7:59 AM, Qu Wenruo wrote:
>> Although we have tree level check at tree read runtime, it's completely
>> based on its parent level.
>> We still need to do accurate level check to avoid invalid tree blocks
>> sneak into kernel space.
>>
>> The check itself is simple, for leaf its level should always be 0.
>> For nodes its level should be in range [1, BTRFS_MAX_LEVEL - 1].
>>
>> Signed-off-by: Qu Wenruo <wqu@suse.com>
>> ---
>>   fs/btrfs/tree-checker.c | 14 ++++++++++++++
>>   1 file changed, 14 insertions(+)
>>
>> diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
>> index db835635372f..cab0b1f1f741 100644
>> --- a/fs/btrfs/tree-checker.c
>> +++ b/fs/btrfs/tree-checker.c
>> @@ -487,6 +487,13 @@ static int check_leaf(struct btrfs_fs_info
>> *fs_info, struct extent_buffer *leaf,
>>       u32 nritems = btrfs_header_nritems(leaf);
>>       int slot;
>>   +    if (btrfs_header_level(leaf) != 0) {
>> +        generic_err(fs_info, leaf, 0,
>> +            "invalid level for leaf, have %d expect 0",
>> +            btrfs_header_level(leaf));
>> +        return -EUCLEAN;
>> +    }
>> +
> BTW, output more info(bytenr, root) of the corrupted node/leaf may be
> better?

That's what will be outputted by generic_err() function.

Thanks,
Qu

> 
>>       /*
>>        * Extent buffers from a relocation tree have a owner field that
>>        * corresponds to the subvolume tree they are based on. So just
>> from an
>> @@ -645,9 +652,16 @@ int btrfs_check_node(struct btrfs_fs_info
>> *fs_info, struct extent_buffer *node)
>>       unsigned long nr = btrfs_header_nritems(node);
>>       struct btrfs_key key, next_key;
>>       int slot;
>> +    int level = btrfs_header_level(node);
>>       u64 bytenr;
>>       int ret = 0;
>>   +    if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
>> +        generic_err(fs_info, node, 0,
>> +            "invalid level for node, have %d expect [1, %d]",
>> +            level, BTRFS_MAX_LEVEL - 1);
>> +        return -EUCLEAN;
>> +    }
>>       if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) {
>>           btrfs_crit(fs_info,
>>   "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect
>> range [1,%u]",
>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: tree-checker: Check level for leaves and nodes
  2018-09-27 23:59 [PATCH] btrfs: tree-checker: Check level for leaves and nodes Qu Wenruo
  2018-09-28  0:32 ` Su Yue
@ 2018-09-28  1:08 ` Su Yue
  2018-09-28  1:03   ` Qu Wenruo
  2018-10-02 13:13 ` David Sterba
  2 siblings, 1 reply; 5+ messages in thread
From: Su Yue @ 2018-09-28  1:08 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs



On 9/28/18 7:59 AM, Qu Wenruo wrote:
> Although we have tree level check at tree read runtime, it's completely
> based on its parent level.
> We still need to do accurate level check to avoid invalid tree blocks
> sneak into kernel space.
> 
> The check itself is simple, for leaf its level should always be 0.
> For nodes its level should be in range [1, BTRFS_MAX_LEVEL - 1].
> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>   fs/btrfs/tree-checker.c | 14 ++++++++++++++
>   1 file changed, 14 insertions(+)
> 
> diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
> index db835635372f..cab0b1f1f741 100644
> --- a/fs/btrfs/tree-checker.c
> +++ b/fs/btrfs/tree-checker.c
> @@ -487,6 +487,13 @@ static int check_leaf(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf,
>   	u32 nritems = btrfs_header_nritems(leaf);
>   	int slot;
>   
> +	if (btrfs_header_level(leaf) != 0) {
> +		generic_err(fs_info, leaf, 0,
> +			"invalid level for leaf, have %d expect 0",
> +			btrfs_header_level(leaf));
> +		return -EUCLEAN;
> +	}
> +
BTW, output more info(bytenr, root) of the corrupted node/leaf may be 
better?

>   	/*
>   	 * Extent buffers from a relocation tree have a owner field that
>   	 * corresponds to the subvolume tree they are based on. So just from an
> @@ -645,9 +652,16 @@ int btrfs_check_node(struct btrfs_fs_info *fs_info, struct extent_buffer *node)
>   	unsigned long nr = btrfs_header_nritems(node);
>   	struct btrfs_key key, next_key;
>   	int slot;
> +	int level = btrfs_header_level(node);
>   	u64 bytenr;
>   	int ret = 0;
>   
> +	if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
> +		generic_err(fs_info, node, 0,
> +			"invalid level for node, have %d expect [1, %d]",
> +			level, BTRFS_MAX_LEVEL - 1);
> +		return -EUCLEAN;
> +	}
>   	if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) {
>   		btrfs_crit(fs_info,
>   "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]",
> 



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: tree-checker: Check level for leaves and nodes
  2018-09-27 23:59 [PATCH] btrfs: tree-checker: Check level for leaves and nodes Qu Wenruo
  2018-09-28  0:32 ` Su Yue
  2018-09-28  1:08 ` Su Yue
@ 2018-10-02 13:13 ` David Sterba
  2 siblings, 0 replies; 5+ messages in thread
From: David Sterba @ 2018-10-02 13:13 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs

On Fri, Sep 28, 2018 at 07:59:34AM +0800, Qu Wenruo wrote:
> Although we have tree level check at tree read runtime, it's completely
> based on its parent level.
> We still need to do accurate level check to avoid invalid tree blocks
> sneak into kernel space.
> 
> The check itself is simple, for leaf its level should always be 0.
> For nodes its level should be in range [1, BTRFS_MAX_LEVEL - 1].
> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>

Reviewed-by: David Sterba <dsterba@suse.com>

Added to misc-next.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-10-02 13:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-27 23:59 [PATCH] btrfs: tree-checker: Check level for leaves and nodes Qu Wenruo
2018-09-28  0:32 ` Su Yue
2018-09-28  1:08 ` Su Yue
2018-09-28  1:03   ` Qu Wenruo
2018-10-02 13:13 ` David Sterba

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).