[rh7,1/3] ext4: Fix high probable use-after-free

Submitted by Kirill Tkhai on March 6, 2020, 12:32 p.m.

Details

Message ID 158349794130.710394.14172608453624419926.stgit@localhost.localdomain
State New
Series "Series without cover letter"
Headers show

Commit Message

Kirill Tkhai March 6, 2020, 12:32 p.m.
Here we have even worse race than in mainstream.

https://jira.sw.ru/browse/PSBM-101798

Fixes: 86521524314e "ext4: replace ext4_kvmalloc() with kvmalloc()"
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 fs/ext4/super.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7b77cabae690..3adeeb00f118 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2196,7 +2196,7 @@  int ext4_alloc_group_desc_bh_array(struct super_block *sb, ext4_group_t ngroup)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	unsigned long num_desc = DIV_ROUND_UP(ngroup,  EXT4_DESC_PER_BLOCK(sb));
-	struct buffer_head **n_group_desc;
+	struct buffer_head **o_group_desc, **n_group_desc;
 
 	if (num_desc <= sbi->s_gdb_count)
 		return 0;
@@ -2208,11 +2208,13 @@  int ext4_alloc_group_desc_bh_array(struct super_block *sb, ext4_group_t ngroup)
 		return -ENOMEM;
 	}
 
-	memcpy(n_group_desc, sbi->s_group_desc,
+	o_group_desc = sbi->s_group_desc;
+	memcpy(n_group_desc, o_group_desc,
 	       sbi->s_gdb_count * sizeof(struct buffer_head *));
-	kvfree(sbi->s_group_desc);
+	WRITE_ONCE(sbi->s_group_desc, n_group_desc);
 
-	sbi->s_group_desc = n_group_desc;
+	/* FIXME: rcu is needed here. See ms commit 1d0c3924a92e */
+	kvfree(o_group_desc);
 	return 0;
 }
 

Comments

Kirill Tkhai March 6, 2020, 12:37 p.m.
Please, ignore this. Patch 2 has wrong description.

On 06.03.2020 15:32, Kirill Tkhai wrote:
> Here we have even worse race than in mainstream.
> 
> https://jira.sw.ru/browse/PSBM-101798
> 
> Fixes: 86521524314e "ext4: replace ext4_kvmalloc() with kvmalloc()"
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  fs/ext4/super.c |   10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 7b77cabae690..3adeeb00f118 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -2196,7 +2196,7 @@ int ext4_alloc_group_desc_bh_array(struct super_block *sb, ext4_group_t ngroup)
>  {
>  	struct ext4_sb_info *sbi = EXT4_SB(sb);
>  	unsigned long num_desc = DIV_ROUND_UP(ngroup,  EXT4_DESC_PER_BLOCK(sb));
> -	struct buffer_head **n_group_desc;
> +	struct buffer_head **o_group_desc, **n_group_desc;
>  
>  	if (num_desc <= sbi->s_gdb_count)
>  		return 0;
> @@ -2208,11 +2208,13 @@ int ext4_alloc_group_desc_bh_array(struct super_block *sb, ext4_group_t ngroup)
>  		return -ENOMEM;
>  	}
>  
> -	memcpy(n_group_desc, sbi->s_group_desc,
> +	o_group_desc = sbi->s_group_desc;
> +	memcpy(n_group_desc, o_group_desc,
>  	       sbi->s_gdb_count * sizeof(struct buffer_head *));
> -	kvfree(sbi->s_group_desc);
> +	WRITE_ONCE(sbi->s_group_desc, n_group_desc);
>  
> -	sbi->s_group_desc = n_group_desc;
> +	/* FIXME: rcu is needed here. See ms commit 1d0c3924a92e */
> +	kvfree(o_group_desc);
>  	return 0;
>  }
>  
> 
>