Re: [PATCH] hpfs: add array bounds validation in hpfs_bplus_lookup

From: Mikulas Patocka

Date: Tue Mar 31 2026 - 07:18:10 EST




On Tue, 31 Mar 2026, Deepanshu Kartikey wrote:

> On Sat, Jan 17, 2026 at 11:10 AM Deepanshu Kartikey
> <kartikey406@xxxxxxxxx> wrote:
> >
> > When traversing a corrupted HPFS filesystem, the n_used_nodes field in
> > the btree header can contain a value larger than what fits in the
> > allocated buffer. This causes out-of-bounds array access when iterating
> > through btree->u.internal[] or btree->u.external[] arrays, leading to
> > a KASAN-detected use-after-free.
> >
> > Validate that n_used_nodes does not exceed the maximum number of nodes
> > that can fit in the buffer before accessing the arrays.
> >
> > Reported-by: syzbot+8debf4b3f7c7391cd8eb@xxxxxxxxxxxxxxxxxxxxxxxxx
> > Closes: https://syzkaller.appspot.com/bug?extid=8debf4b3f7c7391cd8eb
> > Tested-by: syzbot+8debf4b3f7c7391cd8eb@xxxxxxxxxxxxxxxxxxxxxxxxx
> > Signed-off-by: Deepanshu Kartikey <kartikey406@xxxxxxxxx>
> > ---
> > fs/hpfs/anode.c | 23 +++++++++++++++++++++++
> > 1 file changed, 23 insertions(+)
> >
> > diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c
> > index a4f5321eafae..6e1b43f5c9cf 100644
> > --- a/fs/hpfs/anode.c
> > +++ b/fs/hpfs/anode.c
> > @@ -21,6 +22,31 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
> > int c1, c2 = 0;
> > go_down:
> > if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1;
> > +
> > + if (bp_internal(btree)) {
> > + unsigned int max_internal_nodes;
> > +
> > + max_internal_nodes = (bh->b_size - ((char *)btree->u.internal - (char *)bh->b_data))
> > + / sizeof(btree->u.internal[0]);
> > + if (btree->n_used_nodes > max_internal_nodes) {
> > + hpfs_error(s, "btree->n_used_nodes = %u, but max for internal node is %u",
> > + btree->n_used_nodes, max_internal_nodes);
> > + brelse(bh);
> > + return -1;
> > + }
> > + } else {
> > + unsigned int max_external_nodes;
> > +
> > + max_external_nodes = (bh->b_size - ((char *)btree->u.external - (char *)bh->b_data))
> > + / sizeof(btree->u.external[0]);
> > + if (btree->n_used_nodes > max_external_nodes) {
> > + hpfs_error(s, "btree->n_used_nodes = %u, but max for external node is %u",
> > + btree->n_used_nodes, max_external_nodes);
> > + brelse(bh);
> > + return -1;
> > + }
> > + }
> > +
> > if (bp_internal(btree)) {
> > for (i = 0; i < btree->n_used_nodes; i++)
> > if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
> > --
> > 2.43.0
> >
>
> Hi Mikulas,
>
> Gentle ping on this patch . I have submitted this patch on 17th jan 2026
>
> Please let me know if anything else required
>
> Thanks
> Deepanshu

Hi

This test is already done in hpfs_map_anode and hpfs_map_fnode. But you
disabled the checking with "check=none" mount option, so the checking is
not done - this is expected behavior, it's not a bug in the HPFS driver.

Please, fix the fuzzer to not use the "check=none" option.

Mikulas