From: Willy Tarreau <w@1wt.eu>
To: Nikhil Agrawal <nikhil.agrawal@pazago.com>
Cc: security@kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: [SECURITY] fs/nls/nls_cp932: Guard 2-byte output against boundlen == 1 in uni2char() (ZERO-368)
Date: Fri, 9 Oct 2026 10:03:24 +0200 [thread overview]
Message-ID: <asifzGJXas2HOm7E@1wt.eu> (raw)
In-Reply-To: <CALMgpqZVwJBKVuJPXwhUYseE-MJRfozL73eXiGpqD7torhP9Wg@mail.gmail.com>
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
parent reply other threads:[~2026-10-09 8:03 UTC|newest]
Thread overview: expand[flat|nested] mbox.gz Atom feed
[parent not found: <CALMgpqZVwJBKVuJPXwhUYseE-MJRfozL73eXiGpqD7torhP9Wg@mail.gmail.com>]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=asifzGJXas2HOm7E@1wt.eu \
--to=w@1wt.eu \
--cc=linux-fsdevel@vger.kernel.org \
--cc=nikhil.agrawal@pazago.com \
--cc=security@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.