public inbox for linux-ext4@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ext4: Verify fast symlink length
@ 2025-02-06  9:44 Jan Kara
  2025-02-06 15:24 ` Theodore Ts'o
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Jan Kara @ 2025-02-06  9:44 UTC (permalink / raw)
  To: Ted Tso; +Cc: linux-ext4, Jan Kara, syzbot+48a99e426f29859818c0,
	Darrick J. Wong

Verify fast symlink length stored in inode->i_size matches the string
stored in the inode to avoid surprises from corrupted filesystems.

Reported-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
Tested-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
Fixes: bae80473f7b0 ("ext4: use inode_set_cached_link()")
Suggested-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext4/inode.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 7c54ae5fcbd4..64e280fed911 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5007,8 +5007,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
 			inode->i_op = &ext4_encrypted_symlink_inode_operations;
 		} else if (ext4_inode_is_fast_symlink(inode)) {
 			inode->i_op = &ext4_fast_symlink_inode_operations;
-			nd_terminate_link(ei->i_data, inode->i_size,
-				sizeof(ei->i_data) - 1);
+			if (inode->i_size == 0 ||
+			    inode->i_size >= sizeof(ei->i_data) ||
+			    strnlen((char *)ei->i_data, inode->i_size + 1) !=
+								inode->i_size) {
+				ext4_error_inode(inode, function, line, 0,
+					"invalid fast symlink length %llu",
+					 (unsigned long long)inode->i_size);
+				ret = -EFSCORRUPTED;
+				goto bad_inode;
+			}
 			inode_set_cached_link(inode, (char *)ei->i_data,
 					      inode->i_size);
 		} else {
-- 
2.43.0


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

* Re: [PATCH] ext4: Verify fast symlink length
  2025-02-06  9:44 [PATCH] ext4: Verify fast symlink length Jan Kara
@ 2025-02-06 15:24 ` Theodore Ts'o
  2025-02-06 16:04   ` Eric Biggers
  2025-02-07 12:54   ` Jan Kara
  2025-02-06 15:34 ` Darrick J. Wong
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 7+ messages in thread
From: Theodore Ts'o @ 2025-02-06 15:24 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-ext4, syzbot+48a99e426f29859818c0, Darrick J. Wong

On Thu, Feb 06, 2025 at 10:44:55AM +0100, Jan Kara wrote:
> Verify fast symlink length stored in inode->i_size matches the string
> stored in the inode to avoid surprises from corrupted filesystems.
> 
> Reported-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> Tested-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> Fixes: bae80473f7b0 ("ext4: use inode_set_cached_link()")
> Suggested-by: "Darrick J. Wong" <djwong@kernel.org>
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
>  fs/ext4/inode.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 7c54ae5fcbd4..64e280fed911 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5007,8 +5007,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
>  			inode->i_op = &ext4_encrypted_symlink_inode_operations;
>  		} else if (ext4_inode_is_fast_symlink(inode)) {
>  			inode->i_op = &ext4_fast_symlink_inode_operations;
> -			nd_terminate_link(ei->i_data, inode->i_size,
> -				sizeof(ei->i_data) - 1);
> +			if (inode->i_size == 0 ||
> +			    inode->i_size >= sizeof(ei->i_data) ||
> +			    strnlen((char *)ei->i_data, inode->i_size + 1) !=
> +								inode->i_size) {
> +				ext4_error_inode(inode, function, line, 0,
> +					"invalid fast symlink length %llu",
> +					 (unsigned long long)inode->i_size);
> +				ret = -EFSCORRUPTED;
> +				goto bad_inode;
> +			}
>  			inode_set_cached_link(inode, (char *)ei->i_data,
>  					      inode->i_size);


I don't think this will do the right thing if the fast symlink is
encrypted.  See ext4_encrypted_get_link() in fs/ext4/symlink.c in the
kernel sources, and also look at how e2fsck_pass1_check_symlink()
handles checking the size of an encrypted, fast symlink.

Thanks,

					- Ted

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

* Re: [PATCH] ext4: Verify fast symlink length
  2025-02-06  9:44 [PATCH] ext4: Verify fast symlink length Jan Kara
  2025-02-06 15:24 ` Theodore Ts'o
@ 2025-02-06 15:34 ` Darrick J. Wong
  2025-02-10 13:50 ` Baokun Li
  2025-03-18  3:41 ` Theodore Ts'o
  3 siblings, 0 replies; 7+ messages in thread
From: Darrick J. Wong @ 2025-02-06 15:34 UTC (permalink / raw)
  To: Jan Kara; +Cc: Ted Tso, linux-ext4, syzbot+48a99e426f29859818c0

On Thu, Feb 06, 2025 at 10:44:55AM +0100, Jan Kara wrote:
> Verify fast symlink length stored in inode->i_size matches the string
> stored in the inode to avoid surprises from corrupted filesystems.
> 
> Reported-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> Tested-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> Fixes: bae80473f7b0 ("ext4: use inode_set_cached_link()")
> Suggested-by: "Darrick J. Wong" <djwong@kernel.org>
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
>  fs/ext4/inode.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 7c54ae5fcbd4..64e280fed911 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5007,8 +5007,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
>  			inode->i_op = &ext4_encrypted_symlink_inode_operations;
>  		} else if (ext4_inode_is_fast_symlink(inode)) {
>  			inode->i_op = &ext4_fast_symlink_inode_operations;
> -			nd_terminate_link(ei->i_data, inode->i_size,
> -				sizeof(ei->i_data) - 1);
> +			if (inode->i_size == 0 ||
> +			    inode->i_size >= sizeof(ei->i_data) ||
> +			    strnlen((char *)ei->i_data, inode->i_size + 1) !=
> +								inode->i_size) {

Oooh, a validation I overlooked!  :D

Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>

--D


> +				ext4_error_inode(inode, function, line, 0,
> +					"invalid fast symlink length %llu",
> +					 (unsigned long long)inode->i_size);
> +				ret = -EFSCORRUPTED;
> +				goto bad_inode;
> +			}
>  			inode_set_cached_link(inode, (char *)ei->i_data,
>  					      inode->i_size);
>  		} else {
> -- 
> 2.43.0
> 

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

* Re: [PATCH] ext4: Verify fast symlink length
  2025-02-06 15:24 ` Theodore Ts'o
@ 2025-02-06 16:04   ` Eric Biggers
  2025-02-07 12:54   ` Jan Kara
  1 sibling, 0 replies; 7+ messages in thread
From: Eric Biggers @ 2025-02-06 16:04 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Jan Kara, linux-ext4, syzbot+48a99e426f29859818c0,
	Darrick J. Wong

On Thu, Feb 06, 2025 at 10:24:19AM -0500, Theodore Ts'o wrote:
> On Thu, Feb 06, 2025 at 10:44:55AM +0100, Jan Kara wrote:
> > Verify fast symlink length stored in inode->i_size matches the string
> > stored in the inode to avoid surprises from corrupted filesystems.
> > 
> > Reported-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> > Tested-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> > Fixes: bae80473f7b0 ("ext4: use inode_set_cached_link()")
> > Suggested-by: "Darrick J. Wong" <djwong@kernel.org>
> > Signed-off-by: Jan Kara <jack@suse.cz>
> > ---
> >  fs/ext4/inode.c | 12 ++++++++++--
> >  1 file changed, 10 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> > index 7c54ae5fcbd4..64e280fed911 100644
> > --- a/fs/ext4/inode.c
> > +++ b/fs/ext4/inode.c
> > @@ -5007,8 +5007,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
> >  			inode->i_op = &ext4_encrypted_symlink_inode_operations;
> >  		} else if (ext4_inode_is_fast_symlink(inode)) {
> >  			inode->i_op = &ext4_fast_symlink_inode_operations;
> > -			nd_terminate_link(ei->i_data, inode->i_size,
> > -				sizeof(ei->i_data) - 1);
> > +			if (inode->i_size == 0 ||
> > +			    inode->i_size >= sizeof(ei->i_data) ||
> > +			    strnlen((char *)ei->i_data, inode->i_size + 1) !=
> > +								inode->i_size) {
> > +				ext4_error_inode(inode, function, line, 0,
> > +					"invalid fast symlink length %llu",
> > +					 (unsigned long long)inode->i_size);
> > +				ret = -EFSCORRUPTED;
> > +				goto bad_inode;
> > +			}
> >  			inode_set_cached_link(inode, (char *)ei->i_data,
> >  					      inode->i_size);
> 
> 
> I don't think this will do the right thing if the fast symlink is
> encrypted.  See ext4_encrypted_get_link() in fs/ext4/symlink.c in the
> kernel sources, and also look at how e2fsck_pass1_check_symlink()
> handles checking the size of an encrypted, fast symlink.
> 

Encrypted symlinks are handled separately just a couple lines above.

- Eric

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

* Re: [PATCH] ext4: Verify fast symlink length
  2025-02-06 15:24 ` Theodore Ts'o
  2025-02-06 16:04   ` Eric Biggers
@ 2025-02-07 12:54   ` Jan Kara
  1 sibling, 0 replies; 7+ messages in thread
From: Jan Kara @ 2025-02-07 12:54 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Jan Kara, linux-ext4, syzbot+48a99e426f29859818c0,
	Darrick J. Wong

On Thu 06-02-25 10:24:19, Theodore Ts'o wrote:
> On Thu, Feb 06, 2025 at 10:44:55AM +0100, Jan Kara wrote:
> > diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> > index 7c54ae5fcbd4..64e280fed911 100644
> > --- a/fs/ext4/inode.c
> > +++ b/fs/ext4/inode.c
> > @@ -5007,8 +5007,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
> >  			inode->i_op = &ext4_encrypted_symlink_inode_operations;
> >  		} else if (ext4_inode_is_fast_symlink(inode)) {
> >  			inode->i_op = &ext4_fast_symlink_inode_operations;
> > -			nd_terminate_link(ei->i_data, inode->i_size,
> > -				sizeof(ei->i_data) - 1);
> > +			if (inode->i_size == 0 ||
> > +			    inode->i_size >= sizeof(ei->i_data) ||
> > +			    strnlen((char *)ei->i_data, inode->i_size + 1) !=
> > +								inode->i_size) {
> > +				ext4_error_inode(inode, function, line, 0,
> > +					"invalid fast symlink length %llu",
> > +					 (unsigned long long)inode->i_size);
> > +				ret = -EFSCORRUPTED;
> > +				goto bad_inode;
> > +			}
> >  			inode_set_cached_link(inode, (char *)ei->i_data,
> >  					      inode->i_size);
> 
> 
> I don't think this will do the right thing if the fast symlink is
> encrypted.  See ext4_encrypted_get_link() in fs/ext4/symlink.c in the
> kernel sources, and also look at how e2fsck_pass1_check_symlink()
> handles checking the size of an encrypted, fast symlink.

Thanks for having a look but as Eric writes, there's:

                if (IS_ENCRYPTED(inode)) {
                        inode->i_op = &ext4_encrypted_symlink_inode_operations;
		} else if (ext4_inode_is_fast_symlink(inode)) {

just above the context of this hunk so I *think* encrypted symlinks cannot
get into this code?

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH] ext4: Verify fast symlink length
  2025-02-06  9:44 [PATCH] ext4: Verify fast symlink length Jan Kara
  2025-02-06 15:24 ` Theodore Ts'o
  2025-02-06 15:34 ` Darrick J. Wong
@ 2025-02-10 13:50 ` Baokun Li
  2025-03-18  3:41 ` Theodore Ts'o
  3 siblings, 0 replies; 7+ messages in thread
From: Baokun Li @ 2025-02-10 13:50 UTC (permalink / raw)
  To: Jan Kara
  Cc: Ted Tso, linux-ext4, syzbot+48a99e426f29859818c0, Darrick J. Wong,
	Yang Erkun

On 2025/2/6 17:44, Jan Kara wrote:
> Verify fast symlink length stored in inode->i_size matches the string
> stored in the inode to avoid surprises from corrupted filesystems.
>
> Reported-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> Tested-by: syzbot+48a99e426f29859818c0@syzkaller.appspotmail.com
> Fixes: bae80473f7b0 ("ext4: use inode_set_cached_link()")
> Suggested-by: "Darrick J. Wong" <djwong@kernel.org>
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
Looks good to me, thanks for the patch!

Reviewed-by: Baokun Li <libaokun1@huawei.com>
>   fs/ext4/inode.c | 12 ++++++++++--
>   1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 7c54ae5fcbd4..64e280fed911 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5007,8 +5007,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
>   			inode->i_op = &ext4_encrypted_symlink_inode_operations;
>   		} else if (ext4_inode_is_fast_symlink(inode)) {
>   			inode->i_op = &ext4_fast_symlink_inode_operations;
> -			nd_terminate_link(ei->i_data, inode->i_size,
> -				sizeof(ei->i_data) - 1);
> +			if (inode->i_size == 0 ||
> +			    inode->i_size >= sizeof(ei->i_data) ||
> +			    strnlen((char *)ei->i_data, inode->i_size + 1) !=
> +								inode->i_size) {
> +				ext4_error_inode(inode, function, line, 0,
> +					"invalid fast symlink length %llu",
> +					 (unsigned long long)inode->i_size);
> +				ret = -EFSCORRUPTED;
> +				goto bad_inode;
> +			}
>   			inode_set_cached_link(inode, (char *)ei->i_data,
>   					      inode->i_size);
>   		} else {



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

* Re: [PATCH] ext4: Verify fast symlink length
  2025-02-06  9:44 [PATCH] ext4: Verify fast symlink length Jan Kara
                   ` (2 preceding siblings ...)
  2025-02-10 13:50 ` Baokun Li
@ 2025-03-18  3:41 ` Theodore Ts'o
  3 siblings, 0 replies; 7+ messages in thread
From: Theodore Ts'o @ 2025-03-18  3:41 UTC (permalink / raw)
  To: Jan Kara
  Cc: Theodore Ts'o, linux-ext4, syzbot+48a99e426f29859818c0,
	Darrick J. Wong


On Thu, 06 Feb 2025 10:44:55 +0100, Jan Kara wrote:
> Verify fast symlink length stored in inode->i_size matches the string
> stored in the inode to avoid surprises from corrupted filesystems.
> 
> 

Applied, thanks!

[1/1] ext4: Verify fast symlink length
      commit: 5f920d5d60839f7cbbb1ed50eac68d8bc0a73a7c

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

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

end of thread, other threads:[~2025-03-18  3:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-06  9:44 [PATCH] ext4: Verify fast symlink length Jan Kara
2025-02-06 15:24 ` Theodore Ts'o
2025-02-06 16:04   ` Eric Biggers
2025-02-07 12:54   ` Jan Kara
2025-02-06 15:34 ` Darrick J. Wong
2025-02-10 13:50 ` Baokun Li
2025-03-18  3:41 ` Theodore Ts'o

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox