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: <20251013164625.nphymwx25fde5eyk@pali>
Date: Mon, 13 Oct 2025 18:46:25 +0200
From: Pali Rohár <pali@...nel.org>
To: Jeongjun Park <aha310510@...il.com>
Cc: Ethan Ferguson <ethan.ferguson@...ier.com>,
	Namjae Jeon <linkinjeon@...nel.org>,
	Sungjong Seo <sj1557.seo@...sung.com>,
	Yuezhang Mo <yuezhang.mo@...y.com>,
	Al Viro <viro@...iv.linux.org.uk>, linux-fsdevel@...r.kernel.org,
	linux-kernel@...r.kernel.org, stable@...r.kernel.org,
	syzbot+98cc76a76de46b3714d4@...kaller.appspotmail.com
Subject: Re: [PATCH v3] exfat: fix out-of-bounds in exfat_nls_to_ucs2()

On Monday 13 October 2025 22:47:08 Jeongjun Park wrote:
> Since the len argument value passed to exfat_ioctl_set_volume_label()
> from exfat_nls_to_utf16() is passed 1 too large, an out-of-bounds read
> occurs when dereferencing p_cstring in exfat_nls_to_ucs2() later.
> 
> And because of the NLS_NAME_OVERLEN macro, another error occurs when
> creating a file with a period at the end using utf8 and other iocharsets,
> so the NLS_NAME_OVERLEN macro should be removed and the len argument value
> should be passed as FSLABEL_MAX - 1.
> 
> Cc: <stable@...r.kernel.org>
> Reported-by: syzbot+98cc76a76de46b3714d4@...kaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=98cc76a76de46b3714d4
> Fixes: 370e812b3ec1 ("exfat: add nls operations")

Fixes: line is for sure wrong as the affected
exfat_ioctl_set_volume_label function is not available in the mentioned
commit.

I guess it should be commit d01579d590f72d2d91405b708e96f6169f24775a.

Now I have looked at that commit and I think I finally understood what
was the issue. exfat_nls_to_utf16() function is written in a way that
it expects null-term string and its strlen as 3rd argument.

This was achieved for all code paths except the new one introduced in
that commit. "label" is declared as char label[FSLABEL_MAX]; so the
FSLABEL_MAX argument in exfat_nls_to_utf16() is effectively
sizeof(label). And here comes the problem, it should have been
strlen(label) (or rather strnlen(label, sizeof(label)-1) in case
userspace pass non-nul term string).

So the change below to FSLABEL_MAX - 1 effectively fix the overflow
problem. But not the usage of exfat_nls_to_utf16.

API of FS_IOC_SETFSLABEL is defined to always take nul-term string:
https://man7.org/linux/man-pages/man2/fs_ioc_setfslabel.2const.html

And size of buffer is not the length of nul-term string. We should
discard anything after nul-term byte.

So in my opinion exfat_ioctl_set_volume_label() should be fixed in a way
it would call exfat_nls_to_utf16() with 3rd argument passed as:

  strnlen(label, sizeof(label) - 1)

or

  strnlen(label, FSLABEL_MAX - 1)

Or personally I prefer to store this length into new variable (e.g.
label_len) and then passing it to exfat_nls_to_utf16() function.
For example:

  ret = exfat_nls_to_utf16(sb, label, label_len, &uniname, &lossy);

Adding Ethan to CC as author of the mentioned commit.


And about NLS_NAME_OVERLEN, it is being used by the
__exfat_resolve_path() function. So removal of the "setting" of
NLS_NAME_OVERLEN bit but still checking if the NLS_NAME_OVERLEN bit is
set is quite wrong.


Namjae, could you re-check my analysis? Just to be sure that I have not
misunderstood something. It is better to do proper analysis than having
incomplete or incorrect fix.

> Signed-off-by: Jeongjun Park <aha310510@...il.com>
> ---
>  fs/exfat/file.c | 2 +-
>  fs/exfat/nls.c  | 3 ---
>  2 files changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/fs/exfat/file.c b/fs/exfat/file.c
> index f246cf439588..7ce0fb6f2564 100644
> --- a/fs/exfat/file.c
> +++ b/fs/exfat/file.c
> @@ -521,7 +521,7 @@ static int exfat_ioctl_set_volume_label(struct super_block *sb,
>  
>  	memset(&uniname, 0, sizeof(uniname));
>  	if (label[0]) {
> -		ret = exfat_nls_to_utf16(sb, label, FSLABEL_MAX,
> +		ret = exfat_nls_to_utf16(sb, label, FSLABEL_MAX - 1,
>  					 &uniname, &lossy);
>  		if (ret < 0)
>  			return ret;
> diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
> index 8243d94ceaf4..57db08a5271c 100644
> --- a/fs/exfat/nls.c
> +++ b/fs/exfat/nls.c
> @@ -616,9 +616,6 @@ static int exfat_nls_to_ucs2(struct super_block *sb,
>  		unilen++;
>  	}
>  
> -	if (p_cstring[i] != '\0')
> -		lossy |= NLS_NAME_OVERLEN;
> -
>  	*uniname = '\0';
>  	p_uniname->name_len = unilen;
>  	p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0,
> --

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ