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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <134eed9d-7679-4c03-81c0-ec6588ad377b@huaweicloud.com>
Date: Sat, 15 Mar 2025 15:19:59 +0800
From: Zhang Yi <yi.zhang@...weicloud.com>
To: Ojaswin Mujoo <ojaswin@...ux.ibm.com>, linux-ext4@...r.kernel.org
Cc: Jan Kara <jack@...e.cz>, Baokun Li <libaokun1@...wei.com>,
 Ritesh Harjani <ritesh.list@...il.com>, linux-kernel@...r.kernel.org,
 Theodore Ts'o <tytso@....edu>
Subject: Re: [PATCH] ext4: cache es->s_journal_inum in ext4_sb_info

On 2025/3/14 19:41, Ojaswin Mujoo wrote:
> Currently, we access journal ino through sbi->s_es->s_journal_inum,
> which directly reads from the ext4 sb buffer head. If someone modifies
> this underneath us then the s_journal_inum field might get corrupted.
> 
> Although direct block device modifications can be expected to cause
> issues in the FS, let's cache s_journal_inum in sbi->s_journal_ino so
> our checks can be more resillient.
> 
> Suggested-by: Baokun Li <libaokun1@...wei.com>
> Signed-off-by: Ojaswin Mujoo <ojaswin@...ux.ibm.com>
> ---
>  fs/ext4/block_validity.c | 23 ++++++++++++++++-------
>  fs/ext4/ext4.h           |  1 +
>  fs/ext4/inode.c          | 19 +++++++++++++++----
>  fs/ext4/super.c          |  5 ++++-
>  4 files changed, 36 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
> index 87ee3a17bd29..54e6f3499263 100644
> --- a/fs/ext4/block_validity.c
> +++ b/fs/ext4/block_validity.c
> @@ -247,9 +247,9 @@ int ext4_setup_system_zone(struct super_block *sb)
>  		if (ret)
>  			goto err;
>  	}
> -	if (ext4_has_feature_journal(sb) && sbi->s_es->s_journal_inum) {
> +	if (ext4_has_feature_journal(sb) && sbi->s_journal_ino) {
>  		ret = ext4_protect_reserved_inode(sb, system_blks,
> -				le32_to_cpu(sbi->s_es->s_journal_inum));
> +						  sbi->s_journal_ino);
>  		if (ret)
>  			goto err;
>  	}
> @@ -351,11 +351,20 @@ int ext4_check_blockref(const char *function, unsigned int line,
>  {
>  	__le32 *bref = p;
>  	unsigned int blk;
> -
> -	if (ext4_has_feature_journal(inode->i_sb) &&
> -	    (inode->i_ino ==
> -	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
> -		return 0;
> +	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
> +
> +	if (ext4_has_feature_journal(inode->i_sb)) {
> +		/* If we are called from journal init path then
> +		 * sbi->s_journal_ino would be 0
> +		 */
> +		u32 journal_ino = sbi->s_journal_ino ?
> +					  sbi->s_journal_ino :
> +					  sbi->s_es->s_journal_inum;
> +		WARN_ON_ONCE(journal_ino == 0);
> +
> +		if (inode->i_ino == journal_ino)
> +			return 0;
> +	}
>  

Hello Ojaswin,

I'd suggested to assign s_journal_ino in ext4_open_inode_journal(), so
that we can drop these two complex code snippets in ext4_check_blockref()
and __check_block_validity().

@@ -5856,6 +5856,7 @@ static journal_t *ext4_open_inode_journal(struct super_block *sb,
                return ERR_CAST(journal);
        }
        journal->j_private = sb;
+       EXT4_SB(sb)->s_journal_ino = journal_inum;
        journal->j_bmap = ext4_journal_bmap;
        ext4_init_journal_params(sb, journal);
        return journal;

Thanks,
Yi.

>  	while (bref < p+max) {
>  		blk = le32_to_cpu(*bref++);
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 2b7d781bfcad..648b0459e9fd 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -1556,6 +1556,7 @@ struct ext4_sb_info {
>  	u32 s_max_batch_time;
>  	u32 s_min_batch_time;
>  	struct file *s_journal_bdev_file;
> +	u32 s_journal_ino;
>  #ifdef CONFIG_QUOTA
>  	/* Names of quota files with journalled quota */
>  	char __rcu *s_qf_names[EXT4_MAXQUOTAS];
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 365d31004bd0..50961bc0c94d 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -384,10 +384,21 @@ static int __check_block_validity(struct inode *inode, const char *func,
>  				unsigned int line,
>  				struct ext4_map_blocks *map)
>  {
> -	if (ext4_has_feature_journal(inode->i_sb) &&
> -	    (inode->i_ino ==
> -	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
> -		return 0;
> +	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
> +
> +	if (ext4_has_feature_journal(inode->i_sb)) {
> +		/*
> +		 * If we are called from journal init path then
> +		 * sbi->s_journal_ino would be 0
> +		 */
> +		u32 journal_ino = sbi->s_journal_ino ?
> +					  sbi->s_journal_ino :
> +					  sbi->s_es->s_journal_inum;
> +		WARN_ON_ONCE(journal_ino == 0);
> +
> +		if (inode->i_ino == journal_ino)
> +			return 0;
> +	}
>  	if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) {
>  		ext4_error_inode(inode, func, line, map->m_pblk,
>  				 "lblock %lu mapped to illegal pblock %llu "
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index a963ffda692a..44e79db7f12a 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -4162,7 +4162,8 @@ int ext4_calculate_overhead(struct super_block *sb)
>  	struct ext4_sb_info *sbi = EXT4_SB(sb);
>  	struct ext4_super_block *es = sbi->s_es;
>  	struct inode *j_inode;
> -	unsigned int j_blocks, j_inum = le32_to_cpu(es->s_journal_inum);
> +	unsigned int j_blocks;
> +	u32 j_inum = sbi->s_journal_ino;
>  	ext4_group_t i, ngroups = ext4_get_groups_count(sb);
>  	ext4_fsblk_t overhead = 0;
>  	char *buf = (char *) get_zeroed_page(GFP_NOFS);
> @@ -6091,6 +6092,8 @@ static int ext4_load_journal(struct super_block *sb,
>  		ext4_commit_super(sb);
>  	}
>  
> +	EXT4_SB(sb)->s_journal_ino = le32_to_cpu(es->s_journal_inum);
> +
>  	return 0;
>  
>  err_out:


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ