* Re: [SECURITY] fs/nls/nls_cp932: Guard 2-byte output against boundlen == 1 in uni2char() (ZERO-368)
[not found] <CALMgpqZVwJBKVuJPXwhUYseE-MJRfozL73eXiGpqD7torhP9Wg@mail.gmail.com>
@ 2026-10-09 8:03 ` Willy Tarreau
0 siblings, 0 replies; only message in thread
From: Willy Tarreau @ 2026-10-09 8:03 UTC (permalink / raw)
To: Nikhil Agrawal; +Cc: security, linux-fsdevel
Hello,
Note, there's no need to Cc security@k.o when sending to public
lists.
On Fri, Oct 09, 2026 at 12:45:42PM +0530, Nikhil Agrawal wrote:
> Hello Linux Kernel Security Team and filesystem maintainers,
>
> I am Nikhil, a YC founder, and along with our security research team at
> Mettle Labs, we have been conducting systematic defensive code audits
> across Linux filesystem components.
>
> During our audit of native language support (NLS) character set drivers, we
> discovered an out-of-bounds write in `nls_cp932.c` reachable via crafted
> disk images or virtual machine shared folders.
>
> Below are the root cause analysis, reachability notes, and a proposed patch.
>
> ===================================================================
> 1. Vulnerability Summary
> ===================================================================
> In `fs/nls/nls_cp932.c`, `uni2char()` converts 16-bit Unicode characters
> into Shift-JIS (CP932) multi-byte sequences.
>
> When processing characters in the Latin-1 supplement range (`ch == 0 &&
> 0xA0 <= cl`), the function writes a 2-byte sequence (`out[0]` and `out[1]`)
> from the lookup table `u2c_00hi[]`. However, the function-level prologue
> only checks `if (boundlen <= 0) return -ENAMETOOLONG;`.
>
> If `boundlen == 1`, this check succeeds, and `uni2char()` writes both bytes
> into a 1-byte buffer, resulting in a 1-byte out-of-bounds write.
> Furthermore, `uni2char()` returns `2` (the number of bytes supposedly
> written). In callers like `fs/vboxsf/utils.c:465` (`vboxsf_nlscpy`), this
> causes `out_bound_len -= 2` to underflow an unsigned integer, escalating
> into an unbounded memory write.
>
> Sibling charset drivers (`nls_cp936`, `nls_cp949`, `nls_cp950`,
> `nls_euc-jp`) all explicitly check `boundlen < 2` before executing 2-byte
> writes. `nls_cp932` omitted this check on the `u2c_00hi` branch.
>
> ===================================================================
> 2. Affected Code & Root Cause
> ===================================================================
> Location: `fs/nls/nls_cp932.c` (around line 7866)
>
> ```c
> static int uni2char(const wchar_t uni, unsigned char *out, int boundlen)
> {
> unsigned char ch = (uni >> 8) & 0xff;
> unsigned char cl = uni & 0xff;
> ...
> if (boundlen <= 0)
> return -ENAMETOOLONG;
> ...
> if (ch == 0 && 0xA0 <= cl) {
> /* DEFECT: boundlen == 1 allows 2-byte write */
> out[0] = u2c_00hi[cl - 0xA0][0];
> out[1] = u2c_00hi[cl - 0xA0][1];
> return 2;
> }
> ```
>
> ===================================================================
> 3. Proposed Patch
> ===================================================================
> From: Nikhil Agrawal <nikhil@mettlelabs.ai>
> Subject: [PATCH] fs/nls/nls_cp932: Guard 2-byte output against boundlen ==
> 1 in uni2char()
>
> In nls_cp932.c, uni2char() converts characters in the Latin-1 supplement
> range (ch == 0 && 0xA0 <= cl) by writing 2 bytes from u2c_00hi into the
> output buffer. The function only checks 'boundlen <= 0' at entry.
>
> If boundlen is 1, uni2char() writes 2 bytes into a 1-byte space, causing
> a 1-byte out-of-bounds write and returning 2. In callers such as
> vboxsf_nlscpy(),
> this can cause unsigned bound length calculations to underflow.
>
> Add an explicit check that boundlen >= 2 before writing the 2-byte sequence,
> matching the behavior of other Asian multibyte NLS modules (cp936, cp949,
> cp950).
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Reported-by: Mettle Labs Security Team <security@mettlelabs.ai>
> Signed-off-by: Nikhil Agrawal <nikhil@mettlelabs.ai>
Same comments as for your other patches.
> ---
> fs/nls/nls_cp932.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c
> index 2e6236b..b1c2d3e 100644
> --- a/fs/nls/nls_cp932.c
> +++ b/fs/nls/nls_cp932.c
> @@ -7864,6 +7864,8 @@ static int uni2char(const wchar_t uni, unsigned char
> *out, int boundlen)
> return 1;
> }
> if (ch == 0 && 0xA0 <= cl) {
> + if (boundlen < 2)
> + return -ENAMETOOLONG;
> out[0] = u2c_00hi[cl - 0xA0][0];
> out[1] = u2c_00hi[cl - 0xA0][1];
> return 2;
> --
Same space mangling that needs fixing.
>
> ===================================================================
> 4. Coordination
> ===================================================================
> We adhere strictly to the Linux kernel 7-day coordinated disclosure policy.
> Please let us know if any further testing is required.
Since you sent to a public list there's no disclosure involved.
> Best regards,
> Nikhil Agrawal
> Mettle Labs
> mettlelabs.ai
Willy
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-09 8:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CALMgpqZVwJBKVuJPXwhUYseE-MJRfozL73eXiGpqD7torhP9Wg@mail.gmail.com>
2026-10-09 8:03 ` [SECURITY] fs/nls/nls_cp932: Guard 2-byte output against boundlen == 1 in uni2char() (ZERO-368) Willy Tarreau
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox