* [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info
@ 2026-09-09 2:39 Lucas Jeffrey
2026-09-09 2:54 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Lucas Jeffrey @ 2026-09-09 2:39 UTC (permalink / raw)
To: dwmw2
Cc: richard, linux-mtd, linux-kernel, Lucas Jeffrey,
syzbot+3a8099322b09d8d073d1
When a jffs2_inode_info is allocated via new_inode(), due to memory reuse it
can retain stale values from its previous use.
If the new jffs2_inode_info object allocated retains an old reference to a
freed inocache, the function jffs2_new_inode may crash if either
jffs2_init_acl_pre or jffs2_do_new_inode returns an error value because
when calling iput() with the inode it will eventually attempt to free again
the inocache.
Reported-by: syzbot+3a8099322b09d8d073d1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3a8099322b09d8d073d1
Signed-off-by: Lucas Jeffrey <luquijeffrey@gmail.com>
---
fs/jffs2/os-linux.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 86ab014a349c..40f17218a276 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -52,6 +52,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
{
f->highest_version = 0;
f->fragtree = RB_ROOT;
+ f->inocache = NULL;
f->metadata = NULL;
f->dents = NULL;
f->target = NULL;
--
2.43.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info
2026-09-09 2:39 [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info Lucas Jeffrey
@ 2026-09-09 2:54 ` sashiko-bot
2026-09-09 5:57 ` AW: " Richard Weinberger
2026-09-09 5:33 ` AW: " Richard Weinberger
2026-09-10 3:19 ` [PATCH v2] jffs2: initialize inocache and target to NULL when allocating and initializing an jffs2_inode_info Lucas Jeffrey
2 siblings, 1 reply; 6+ messages in thread
From: sashiko-bot @ 2026-09-09 2:54 UTC (permalink / raw)
To: Lucas Jeffrey, dwmw2
Cc: richard, linux-mtd, linux-kernel, syzbot+3a8099322b09d8d073d1
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Double free of `f->target` on early VFS failure paths due to uninitialized slab memory.
--
commit 9fd2012cfec1b8d15df193fea97deabda99aa5e5
Author: Lucas Jeffrey <luquijeffrey@gmail.com>
jffs: initialize inocache to NULL when initializing a jffs2_inode_info
When a jffs2_inode_info is allocated via new_inode(), due to memory reuse it
can retain stale values from its previous use.
If the new jffs2_inode_info object allocated retains an old reference to a
freed inocache, the function jffs2_new_inode may crash if either
jffs2_init_acl_pre or jffs2_do_new_inode returns an error value because
when calling iput() with the inode it will eventually attempt to free again
the inocache.
Reported-by: syzbot+3a8099322b09d8d073d1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3a8099322b09d8d073d1
Signed-off-by: Lucas Jeffrey <luquijeffrey@gmail.com>
> diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
> index 86ab014a349c5..40f17218a276b 100644
> --- a/fs/jffs2/os-linux.h
> +++ b/fs/jffs2/os-linux.h
> @@ -52,6 +52,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
> {
> f->highest_version = 0;
> f->fragtree = RB_ROOT;
> + f->inocache = NULL;
> f->metadata = NULL;
> f->dents = NULL;
> f->target = NULL;
[Severity: Critical]
This isn't a bug introduced by this patch, but doesn't f->target suffer from
a similar issue due to uninitialized slab memory on early VFS failure paths?
When the VFS allocates a new inode via jffs2_alloc_inode() in
fs/jffs2/super.c, the object is returned from the SLAB cache without
__GFP_ZERO. It retains stale values from its previous lifecycle, including
a dangling pointer in f->target, because jffs2_free_inode() frees f->target
but does not nullify it.
JFFS2 defers initializing f->target = NULL to jffs2_init_inode_info(), which
is called after VFS initialization completes. If the VFS fails early (e.g.,
inode_init_always() fails due to an LSM memory allocation, or iget_locked()
in fs/inode.c encounters a hash collision race and drops the newly allocated
inode), the VFS destroys the inode via jffs2_free_inode() before JFFS2 ever
initializes it.
This causes a double free when kfree(f->target) executes again on the
dangling pointer:
fs/jffs2/super.c:jffs2_free_inode() {
...
kfree(f->target);
kmem_cache_free(jffs2_inode_cachep, f);
}
Userspace can reliably trigger the iget_locked() hash collision race by
performing concurrent lookups (e.g., stat() or open()) on the same
non-resident inode:
fs/inode.c:iget_locked() {
...
if (unlikely(test_bit(__I_NEW, &inode->i_state))) {
/* Uhhuh, somebody else created the same inode under us... */
spin_unlock(&inode_hash_lock);
destroy_inode(inode);
...
}
Would it be safer to zero these fields in jffs2_alloc_inode() or ensure
jffs2_free_inode() nullifies them before returning the object to the slab
cache?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260909023955.1642244-1-luquijeffrey@gmail.com?part=1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 6+ messages in thread
* AW: [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info
2026-09-09 2:39 [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info Lucas Jeffrey
2026-09-09 2:54 ` sashiko-bot
@ 2026-09-09 5:33 ` Richard Weinberger
2026-09-10 3:19 ` [PATCH v2] jffs2: initialize inocache and target to NULL when allocating and initializing an jffs2_inode_info Lucas Jeffrey
2 siblings, 0 replies; 6+ messages in thread
From: Richard Weinberger @ 2026-09-09 5:33 UTC (permalink / raw)
To: Lucas Jeffrey, dwmw2
Cc: linux-mtd, linux-kernel, Lucas Jeffrey,
syzbot+3a8099322b09d8d073d1
Am Wed, Sep 9, 2026, 04:40 schrieb Lucas Jeffrey <luquijeffrey@gmail.com>:
> When a jffs2_inode_info is allocated via new_inode(), due to memory reuse it
> can retain stale values from its previous use.
>
> If the new jffs2_inode_info object allocated retains an old reference to a
> freed inocache, the function jffs2_new_inode may crash if either
> jffs2_init_acl_pre or jffs2_do_new_inode returns an error value because
> when calling iput() with the inode it will eventually attempt to free again
> the inocache.
>
> Reported-by: syzbot+3a8099322b09d8d073d1@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=3a8099322b09d8d073d1
> Signed-off-by: Lucas Jeffrey <luquijeffrey@gmail.com>
This was reported earlier but the reporter went silent.
https://lore.kernel.org/linux-mtd/849183271.921.1787173413104.JavaMail.zimbra@nod.at/
Thanks,
//richard
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 6+ messages in thread
* AW: [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info
2026-09-09 2:54 ` sashiko-bot
@ 2026-09-09 5:57 ` Richard Weinberger
2026-09-10 2:53 ` Lucas Jeffrey
0 siblings, 1 reply; 6+ messages in thread
From: Richard Weinberger @ 2026-09-09 5:57 UTC (permalink / raw)
To: sashiko-reviews, Lucas Jeffrey, dwmw2
Cc: linux-mtd, linux-kernel, syzbot+3a8099322b09d8d073d1
Lucas,
Am Wed, Sep 9, 2026, 04:54 schrieb sashiko-bot@kernel.org:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [Critical] Double free of `f->target` on early VFS failure paths due to uninitialized slab memory.
> --
>
> commit 9fd2012cfec1b8d15df193fea97deabda99aa5e5
> Author: Lucas Jeffrey <luquijeffrey@gmail.com>
>
> jffs: initialize inocache to NULL when initializing a jffs2_inode_info
>
> When a jffs2_inode_info is allocated via new_inode(), due to memory reuse it
> can retain stale values from its previous use.
>
> If the new jffs2_inode_info object allocated retains an old reference to a
> freed inocache, the function jffs2_new_inode may crash if either
> jffs2_init_acl_pre or jffs2_do_new_inode returns an error value because
> when calling iput() with the inode it will eventually attempt to free again
> the inocache.
>
> Reported-by: syzbot+3a8099322b09d8d073d1@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=3a8099322b09d8d073d1
> Signed-off-by: Lucas Jeffrey <luquijeffrey@gmail.com>
>
> > diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
> > index 86ab014a349c5..40f17218a276b 100644
> > --- a/fs/jffs2/os-linux.h
> > +++ b/fs/jffs2/os-linux.h
> > @@ -52,6 +52,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
> > {
> > f->highest_version = 0;
> > f->fragtree = RB_ROOT;
> > + f->inocache = NULL;
> > f->metadata = NULL;
> > f->dents = NULL;
> > f->target = NULL;
>
> [Severity: Critical]
> This isn't a bug introduced by this patch, but doesn't f->target suffer from
> a similar issue due to uninitialized slab memory on early VFS failure paths?
>
> When the VFS allocates a new inode via jffs2_alloc_inode() in
> fs/jffs2/super.c, the object is returned from the SLAB cache without
> __GFP_ZERO. It retains stale values from its previous lifecycle, including
> a dangling pointer in f->target, because jffs2_free_inode() frees f->target
> but does not nullify it.
>
> JFFS2 defers initializing f->target = NULL to jffs2_init_inode_info(), which
> is called after VFS initialization completes. If the VFS fails early (e.g.,
> inode_init_always() fails due to an LSM memory allocation, or iget_locked()
> in fs/inode.c encounters a hash collision race and drops the newly allocated
> inode), the VFS destroys the inode via jffs2_free_inode() before JFFS2 ever
> initializes it.
>
> This causes a double free when kfree(f->target) executes again on the
> dangling pointer:
>
> fs/jffs2/super.c:jffs2_free_inode() {
> ...
> kfree(f->target);
> kmem_cache_free(jffs2_inode_cachep, f);
> }
>
> Userspace can reliably trigger the iget_locked() hash collision race by
> performing concurrent lookups (e.g., stat() or open()) on the same
> non-resident inode:
>
> fs/inode.c:iget_locked() {
> ...
> if (unlikely(test_bit(__I_NEW, &inode->i_state))) {
> /* Uhhuh, somebody else created the same inode under us... */
> spin_unlock(&inode_hash_lock);
> destroy_inode(inode);
> ...
> }
>
> Would it be safer to zero these fields in jffs2_alloc_inode() or ensure
> jffs2_free_inode() nullifies them before returning the object to the slab
> cache?
I think this is a legit bug pointed out by Sashiko.
Do you want to double check and (if needed) fix it?
Thanks,
//richard
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info
2026-09-09 5:57 ` AW: " Richard Weinberger
@ 2026-09-10 2:53 ` Lucas Jeffrey
0 siblings, 0 replies; 6+ messages in thread
From: Lucas Jeffrey @ 2026-09-10 2:53 UTC (permalink / raw)
To: Richard Weinberger, linux-mtd, linux-kernel
Hi richard
I've sort of manually confirmed the crash pointed out by Sashiko,
while not exactly the failure path mentioned in the review,
I found that if immediately after returning a new inode from
jffs2_alloc_inode, if allocation fails in 'security_inode_alloc',
then an ENOMEM is propagated to inode_init_always_gfp and then to
alloc_inode, and enters this failure path:
struct inode *alloc_inode(...) {
...
if (unlikely(inode_init_always(sb, inode))) {
if (ops->destroy_inode) {
ops->destroy_inode(inode);
if (!ops->free_inode)
return NULL;
}
inode->free_inode = ops->free_inode;
i_callback(&inode->i_rcu); //Here it ends up calling jffs2_free_inode
which frees f->target, double free/UAF if f->target != NULL
return NULL;
}
...
}
Here's the report
[ 104.928161] ==================================================================
[ 104.931812] BUG: KASAN: double-free in jffs2_free_inode+0x31/0x50
[ 104.935737] Free of addr ffff88800ad5eb80 by task repro/76
[ 104.936013]
[ 104.937388] CPU: 0 UID: 0 PID: 76 Comm: repro Not tainted
7.3.0-rc2-00028-g692c6ca486c3-dirty #16 PREEMPT(lazy)
[ 104.937872] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX,
arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 104.938350] Call Trace:
[ 104.939517] <TASK>
[ 104.939999] dump_stack_lvl+0x53/0x70
[ 104.940358] print_report+0xd0/0x630
[ 104.940415] ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[ 104.940459] ? jffs2_free_inode+0x31/0x50
[ 104.940486] ? jffs2_free_inode+0x31/0x50
[ 104.940509] kasan_report_invalid_free+0xa2/0xd0
[ 104.940542] ? jffs2_free_inode+0x31/0x50
[ 104.940570] ? jffs2_free_inode+0x31/0x50
[ 104.940595] check_slab_allocation+0xd9/0x100
[ 104.940625] kfree+0xfc/0x390
[ 104.940657] jffs2_free_inode+0x31/0x50
[ 104.940684] ? __pfx_jffs2_free_inode+0x10/0x10
[ 104.940715] alloc_inode+0x135/0x1f0
[ 104.940755] new_inode+0x13/0x140
[ 104.940790] jffs2_new_inode+0x77/0xa00
[ 104.940828] jffs2_create+0x8a/0x340
[ 104.940860] lookup_open+0xa90/0x18d0
[ 104.940906] path_openat+0x1257/0x2280
[ 104.940949] ? __pfx_path_openat+0x10/0x10
[ 104.940984] do_file_open+0x1cd/0x400
[ 104.941013] ? __pfx_do_file_open+0x10/0x10
[ 104.941061] ? alloc_fd+0x331/0x5b0
[ 104.941103] ? do_getname+0x66/0x2c0
[ 104.941138] do_sys_openat2+0xd9/0x170
[ 104.941168] ? __pfx_do_sys_openat2+0x10/0x10
[ 104.941203] __x64_sys_openat+0x11d/0x1d0
[ 104.941229] ? kasan_save_track+0x14/0x30
[ 104.941256] ? __pfx___x64_sys_openat+0x10/0x10
[ 104.941283] ? kmem_cache_free+0xba/0x3a0
[ 104.941310] ? fpregs_restore_userregs+0xe0/0x230
[ 104.941362] do_syscall_64+0xdd/0x4a0
[ 104.941400] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 104.941872] RIP: 0033:0x420f77
[ 104.942862] Code: 55 9c 48 89 75 a0 89 7d a8 44 89 55 ac e8 71 f0
02 00 44 8b 55 ac 8b 55 9c 41 89 c0 48 8b 75 a0 8b 7d a8 b8 01 01 00
00 0f 05 <48> 3d 00 f0 ff ff 77 31 44 89 c7 89 45 ac e8 c6 f0 02 00 8b
45 ac
[ 104.943373] RSP: 002b:00007f1ef5c4e570 EFLAGS: 00000293 ORIG_RAX:
0000000000000101
[ 104.944349] RAX: ffffffffffffffda RBX: 000000000a413220 RCX: 0000000000420f77
[ 104.944401] RDX: 00000000000000c2 RSI: 00007f1ef5c4e600 RDI: 00000000ffffff9c
[ 104.944447] RBP: 00007f1ef5c4e5e0 R08: 0000000000000000 R09: 0000000000000000
[ 104.944491] R10: 00000000000001a4 R11: 0000000000000293 R12: 0000000000000483
[ 104.944533] R13: 0000000000000007 R14: 00007f1ef5c4ea00 R15: 000000000a413224
[ 104.944619] </TASK>
[ 104.944813]
[ 104.944856] Allocated by task 78:
[ 104.945202] kasan_save_stack+0x33/0x60
[ 104.945489] kasan_save_track+0x14/0x30
[ 104.945515] __kasan_kmalloc+0x8f/0xa0
[ 104.945538] __kmalloc_node_track_caller_noprof+0x1bc/0x480
[ 104.945564] kmemdup_noprof+0x20/0x50
[ 104.945600] jffs2_symlink+0x520/0x1080
[ 104.945624] vfs_symlink+0x132/0x420
[ 104.945645] filename_symlinkat+0x139/0x3d0
[ 104.945670] __x64_sys_symlink+0x74/0xa0
[ 104.945694] do_syscall_64+0xdd/0x4a0
[ 104.945720] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 104.945778]
[ 104.945804] Freed by task 80:
[ 104.945932] kasan_save_stack+0x33/0x60
[ 104.945984] kasan_save_track+0x14/0x30
[ 104.946074] kasan_save_free_info+0x3b/0x60
[ 104.946101] __kasan_slab_free+0x43/0x70
[ 104.946126] kfree+0x121/0x390
[ 104.946146] jffs2_free_inode+0x31/0x50
[ 104.946167] rcu_core+0x55a/0x1870
[ 104.946192] handle_softirqs+0x182/0x5a0
[ 104.946226] __irq_exit_rcu+0x63/0x140
[ 104.946248] sysvec_apic_timer_interrupt+0x6b/0x80
[ 104.946273] asm_sysvec_apic_timer_interrupt+0x1a/0x20
[ 104.946314]
[ 104.946386] The buggy address belongs to the object at ffff88800ad5eb80
[ 104.946386] which belongs to the cache kmalloc-64 of size 64
[ 104.946519] The buggy address is located 0 bytes inside of
[ 104.946519] 64-byte region [ffff88800ad5eb80, ffff88800ad5ebc0)
[ 104.946573]
[ 104.946800] The buggy address belongs to the physical page:
[ 104.947880] page: refcount:0 mapcount:0 mapping:0000000000000000
index:0x0 pfn:0xad5e
[ 104.948383] flags: 0x100000000000000(node=0|zone=1)
[ 104.949052] page_type: f5(slab)
[ 104.949572] raw: 0100000000000000 ffff8880070418c0 dead000000000100
dead000000000122
[ 104.949623] raw: 0000000000000000 0000000000200020 00000000f5000000
0000000000000000
[ 104.949710] page dumped because: kasan: bad access detected
[ 104.949727]
[ 104.949743] Memory state around the buggy address:
[ 104.950194] ffff88800ad5ea80: 00 00 00 00 00 03 fc fc fc fc fc fc
fc fc fc fc
[ 104.950242] ffff88800ad5eb00: 00 00 00 00 00 00 03 fc fc fc fc fc
fc fc fc fc
[ 104.950282] >ffff88800ad5eb80: fa fb fb fb fb fb fb fb fc fc fc fc
fc fc fc fc
[ 104.950315] ^
[ 104.950381] ffff88800ad5ec00: 00 00 00 00 00 00 03 fc fc fc fc fc
fc fc fc fc
[ 104.950397] ffff88800ad5ec80: 00 00 00 00 00 00 03 fc fc fc fc fc
fc fc fc fc
[ 104.950439] ==================================================================
[ 104.968624] Disabling lock debugging due to kernel taint
i'll send a V2 patch that also initializes f->target = NULL when
allocating the inode
Thanks,
Lucas J.
On Wed, Sep 9, 2026 at 2:57 AM Richard Weinberger <richard@nod.at> wrote:
>
> Lucas,
>
> Am Wed, Sep 9, 2026, 04:54 schrieb sashiko-bot@kernel.org:
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> >
> > Pre-existing issues:
> > - [Critical] Double free of `f->target` on early VFS failure paths due to uninitialized slab memory.
> > --
> >
> > commit 9fd2012cfec1b8d15df193fea97deabda99aa5e5
> > Author: Lucas Jeffrey <luquijeffrey@gmail.com>
> >
> > jffs: initialize inocache to NULL when initializing a jffs2_inode_info
> >
> > When a jffs2_inode_info is allocated via new_inode(), due to memory reuse it
> > can retain stale values from its previous use.
> >
> > If the new jffs2_inode_info object allocated retains an old reference to a
> > freed inocache, the function jffs2_new_inode may crash if either
> > jffs2_init_acl_pre or jffs2_do_new_inode returns an error value because
> > when calling iput() with the inode it will eventually attempt to free again
> > the inocache.
> >
> > Reported-by: syzbot+3a8099322b09d8d073d1@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=3a8099322b09d8d073d1
> > Signed-off-by: Lucas Jeffrey <luquijeffrey@gmail.com>
> >
> > > diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
> > > index 86ab014a349c5..40f17218a276b 100644
> > > --- a/fs/jffs2/os-linux.h
> > > +++ b/fs/jffs2/os-linux.h
> > > @@ -52,6 +52,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
> > > {
> > > f->highest_version = 0;
> > > f->fragtree = RB_ROOT;
> > > + f->inocache = NULL;
> > > f->metadata = NULL;
> > > f->dents = NULL;
> > > f->target = NULL;
> >
> > [Severity: Critical]
> > This isn't a bug introduced by this patch, but doesn't f->target suffer from
> > a similar issue due to uninitialized slab memory on early VFS failure paths?
> >
> > When the VFS allocates a new inode via jffs2_alloc_inode() in
> > fs/jffs2/super.c, the object is returned from the SLAB cache without
> > __GFP_ZERO. It retains stale values from its previous lifecycle, including
> > a dangling pointer in f->target, because jffs2_free_inode() frees f->target
> > but does not nullify it.
> >
> > JFFS2 defers initializing f->target = NULL to jffs2_init_inode_info(), which
> > is called after VFS initialization completes. If the VFS fails early (e.g.,
> > inode_init_always() fails due to an LSM memory allocation, or iget_locked()
> > in fs/inode.c encounters a hash collision race and drops the newly allocated
> > inode), the VFS destroys the inode via jffs2_free_inode() before JFFS2 ever
> > initializes it.
> >
> > This causes a double free when kfree(f->target) executes again on the
> > dangling pointer:
> >
> > fs/jffs2/super.c:jffs2_free_inode() {
> > ...
> > kfree(f->target);
> > kmem_cache_free(jffs2_inode_cachep, f);
> > }
> >
> > Userspace can reliably trigger the iget_locked() hash collision race by
> > performing concurrent lookups (e.g., stat() or open()) on the same
> > non-resident inode:
> >
> > fs/inode.c:iget_locked() {
> > ...
> > if (unlikely(test_bit(__I_NEW, &inode->i_state))) {
> > /* Uhhuh, somebody else created the same inode under us... */
> > spin_unlock(&inode_hash_lock);
> > destroy_inode(inode);
> > ...
> > }
> >
> > Would it be safer to zero these fields in jffs2_alloc_inode() or ensure
> > jffs2_free_inode() nullifies them before returning the object to the slab
> > cache?
>
> I think this is a legit bug pointed out by Sashiko.
> Do you want to double check and (if needed) fix it?
>
> Thanks,
> //richard
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2] jffs2: initialize inocache and target to NULL when allocating and initializing an jffs2_inode_info
2026-09-09 2:39 [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info Lucas Jeffrey
2026-09-09 2:54 ` sashiko-bot
2026-09-09 5:33 ` AW: " Richard Weinberger
@ 2026-09-10 3:19 ` Lucas Jeffrey
2 siblings, 0 replies; 6+ messages in thread
From: Lucas Jeffrey @ 2026-09-10 3:19 UTC (permalink / raw)
To: dwmw2
Cc: richard, linux-mtd, linux-kernel, syzbot+3a8099322b09d8d073d1,
Lucas Jeffrey
When a jffs2_inode_info is allocated via new_inode(), due to memory reuse it
can retain stale values from its previous use.
If the new jffs2_inode_info object allocated retains an old reference to a
freed inocache, the function jffs2_new_inode may crash if either
jffs2_init_acl_pre or jffs2_do_new_inode returns an error value because
when calling iput() with the inode it will eventually attempt to free again
the inocache.
There is another failure path which is, if target is not null when allocating
the object in jffs2_alloc_inode, and immediately after returning the newly allocated object,
and if the 'inode_init_always' returns an error value (allocation failure for example)
then the vfs will attempt to free the inode and jffs2_free_inode will attempt to free f->target,
which can be a stale value from a previous allocation, generating a double free/use after free.
Reported-by: syzbot+3a8099322b09d8d073d1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3a8099322b09d8d073d1
Signed-off-by: Lucas Jeffrey <luquijeffrey@gmail.com>
---
Changes in V2: initializing target field to NULL in jffs2_alloc_inode
---
fs/jffs2/os-linux.h | 1 +
fs/jffs2/super.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 86ab014a349c..40f17218a276 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -52,6 +52,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
{
f->highest_version = 0;
f->fragtree = RB_ROOT;
+ f->inocache = NULL;
f->metadata = NULL;
f->dents = NULL;
f->target = NULL;
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 81396a092ba8..2343c21b49e6 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -42,6 +42,8 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb)
f = alloc_inode_sb(sb, jffs2_inode_cachep, GFP_KERNEL);
if (!f)
return NULL;
+
+ f->target = NULL;
return &f->vfs_inode;
}
--
2.43.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-10 3:19 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 2:39 [PATCH] jffs: initialize inocache to NULL when initializing a jffs2_inode_info Lucas Jeffrey
2026-09-09 2:54 ` sashiko-bot
2026-09-09 5:57 ` AW: " Richard Weinberger
2026-09-10 2:53 ` Lucas Jeffrey
2026-09-09 5:33 ` AW: " Richard Weinberger
2026-09-10 3:19 ` [PATCH v2] jffs2: initialize inocache and target to NULL when allocating and initializing an jffs2_inode_info Lucas Jeffrey
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.