lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210916140046.GH10610@quack2.suse.cz>
Date:   Thu, 16 Sep 2021 16:00:46 +0200
From:   Jan Kara <jack@...e.cz>
To:     yangerkun <yangerkun@...wei.com>
Cc:     tytso@....edu, jack@...e.cz, linux-ext4@...r.kernel.org,
        yukuai3@...wei.com
Subject: Re: [PATCH] ext4: update last_pos for the case ext4_htree_fill_tree
 return fail

On Tue 14-09-21 19:14:15, yangerkun wrote:
> Or the ls for ext4 dir can run into a deadloop since info->last_pos !=
> ctx->pos which will reset the world and start read the entry which has
> already got before. Details see below:
> 
> 1. a dx_dir which has 3 block, block 0 as dx_root block, block 1/2 as
>    leaf block which own the ext4_dir_entry_2
> 2. block 1 read ok and call_filldir which will fill the dirent and update
>    the ctx->pos
> 3. block 2 read fail, but we has already fill some dirent, so we will
>    return back to userspace will a positive return val(see ksys_getdents64)
> 4. the second ext4_dx_readdir will reset the world since info->last_pos
>    != ctx->pos, and will also init the curr_hash which pos to block 1
> 5. So we will read block1 too, and once block2 still read fail, we can
>    only fill one dirent because the hash of the entry in block1(besides
>    the last one) won't greater than curr_hash
> 6. this time, we forget update last_pos too since the read for block2
>    will fail, and since we has got the one entry, ksys_getdents64 can
>    return success
> 7. Latter we will trapped in a loop with step 4~6
> 
> Fix it by update last_pos too once ext4_htree_fill_tree return fail.
> 
> Signed-off-by: yangerkun <yangerkun@...wei.com>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@...e.cz>

								Honza

> ---
>  fs/ext4/dir.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
> index ffb295aa891c..74b172a4adda 100644
> --- a/fs/ext4/dir.c
> +++ b/fs/ext4/dir.c
> @@ -551,7 +551,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
>  	struct dir_private_info *info = file->private_data;
>  	struct inode *inode = file_inode(file);
>  	struct fname *fname;
> -	int	ret;
> +	int ret = 0;
>  
>  	if (!info) {
>  		info = ext4_htree_create_dir_info(file, ctx->pos);
> @@ -599,7 +599,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
>  						   info->curr_minor_hash,
>  						   &info->next_hash);
>  			if (ret < 0)
> -				return ret;
> +				goto finished;
>  			if (ret == 0) {
>  				ctx->pos = ext4_get_htree_eof(file);
>  				break;
> @@ -630,7 +630,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
>  	}
>  finished:
>  	info->last_pos = ctx->pos;
> -	return 0;
> +	return ret < 0 ? ret : 0;
>  }
>  
>  static int ext4_release_dir(struct inode *inode, struct file *filp)
> -- 
> 2.31.1
> 
-- 
Jan Kara <jack@...e.com>
SUSE Labs, CR

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ