Re: [f2fs-dev] [PATCH v2] f2fs: validate ACL entry sizes in f2fs_acl_from_disk()

Chao Yu via Linux-f2fs-devel <[email protected]>
Newsgroups net.sourceforge.lists.linux-f2fs-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 6/13/26 19:05, Zhang Cen wrote:
> f2fs_acl_count() only validates the aggregate ACL xattr length. A
> malformed ACL can still place ACL_USER or ACL_GROUP in a slot that only
> contains struct f2fs_acl_entry_short bytes, and f2fs_acl_from_disk()
> then reads entry->e_id before verifying that a full entry fits.
> 
> Require a short entry before reading e_tag and e_perm, and require a
> full entry before reading e_id for ACL_USER and ACL_GROUP. Return
> -EFSCORRUPTED for malformed on-disk ACL blobs so corrupted ACL xattrs
> are reported as filesystem corruption instead of generic invalid
> arguments.
> 
> Validation reproduced this kernel report:
> KASAN slab-out-of-bounds in __f2fs_get_acl+0x6fb/0x7e0
> RIP: 0033:0x7f4b835ea7aa
> The buggy address belongs to the object at ffff888114589960 which belongs
> to the cache kmalloc-8 of size 8
> The buggy address is located 0 bytes to the right of allocated 8-byte
> region [ffff888114589960, ffff888114589968)
> Read of size 4
> Call trace:
>   dump_stack_lvl+0x66/0xa0 (?:?)
>   print_report+0xce/0x630 (?:?)
>   __f2fs_get_acl+0x6fb/0x7e0 (fs/f2fs/acl.c:169)
>   srso_alias_return_thunk+0x5/0xfbef5 (?:?)
>   __virt_addr_valid+0x224/0x430 (?:?)
>   kasan_report+0xe0/0x110 (?:?)
>   __f2fs_get_acl+0x5/0x7e0 (fs/f2fs/acl.c:169)
>   __get_acl+0x281/0x380 (?:?)
>   vfs_get_acl+0x10b/0x190 (?:?)
>   do_get_acl+0x2a/0x410 (?:?)
>   do_get_acl+0x9/0x410 (?:?)
>   do_getxattr+0xe8/0x260 (?:?)
>   filename_getxattr+0xd1/0x140 (?:?)
>   do_getname+0x2d/0x2d0 (?:?)
>   path_getxattrat+0x16c/0x200 (?:?)
>   lock_release+0xc8/0x290 (?:?)
>   cgroup_update_frozen+0x9d/0x320 (?:?)
>   lockdep_hardirqs_on_prepare+0xea/0x1a0 (?:?)
>   trace_hardirqs_on+0x1a/0x170 (?:?)
>   _raw_spin_unlock_irq+0x28/0x50 (?:?)
>   do_syscall_64+0x115/0x6a0 (arch/x86/entry/syscall_64.c:87)
>   entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?)
> 
> Fixes: af48b85b8cd3 ("f2fs: add xattr and acl functionalities")
> 
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Zhang Cen <[email protected]>
> ---
> Changes in v2:
> - Wrap the new ACL entry-size checks in unlikely().
> - Return -EFSCORRUPTED for malformed on-disk ACL blobs.
> 
>  fs/f2fs/acl.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
> index fa8d81a30fb91..e62ce979be0b7 100644
> --- a/fs/f2fs/acl.c
> +++ b/fs/f2fs/acl.c
> @@ -53,14 +53,14 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
>  	const char *end = value + size;
>  
>  	if (size < sizeof(struct f2fs_acl_header))
> -		return ERR_PTR(-EINVAL);
> +		return ERR_PTR(-EFSCORRUPTED);

The change is not related to this patch, right? I suspect you only give the
hint to let LLM to replace EINVAL w/ EFSCORRUPTED in f2fs_acl_from_disk(),
rather than replacing in newly added lines.

>  
>  	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION))
> -		return ERR_PTR(-EINVAL);
> +		return ERR_PTR(-EFSCORRUPTED);

Ditto,

>  
>  	count = f2fs_acl_count(size);
>  	if (count < 0)
> -		return ERR_PTR(-EINVAL);
> +		return ERR_PTR(-EFSCORRUPTED);

Ditto,

>  	if (count == 0)
>  		return NULL;
>  
> @@ -70,7 +70,8 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
>  
>  	for (i = 0; i < count; i++) {
>  
> -		if ((char *)entry > end)
> +		if (unlikely((char *)entry +
> +			     sizeof(struct f2fs_acl_entry_short) > end))
>  			goto fail;
>  
>  		acl->a_entries[i].e_tag  = le16_to_cpu(entry->e_tag);
> @@ -86,6 +87,9 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
>  			break;
>  
>  		case ACL_USER:
> +			if (unlikely((char *)entry +
> +				     sizeof(struct f2fs_acl_entry) > end))
> +				goto fail;
>  			acl->a_entries[i].e_uid =
>  				make_kuid(&init_user_ns,
>  						le32_to_cpu(entry->e_id));
> @@ -93,6 +97,9 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
>  					sizeof(struct f2fs_acl_entry));
>  			break;
>  		case ACL_GROUP:
> +			if (unlikely((char *)entry +
> +				     sizeof(struct f2fs_acl_entry) > end))
> +				goto fail;
>  			acl->a_entries[i].e_gid =
>  				make_kgid(&init_user_ns,
>  						le32_to_cpu(entry->e_id));
> @@ -108,7 +115,7 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
>  	return acl;
>  fail:
>  	posix_acl_release(acl);
> -	return ERR_PTR(-EINVAL);
> +	return ERR_PTR(-EFSCORRUPTED);

Ditto,

Thanks,

>  }
>  
>  static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi,



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.