| 0/0 |
2026/08/09 10:15 |
flow |
assessment-security |
38m
Results: map[DenialOfService:true Explanation:**Analysis and Reasoning:**
The bug is a race condition in the JFFS2 filesystem's garbage collection
mechanism.
When a file is deleted and its last reference is closed, the VFS evicts the
inode, which invokes `jffs2_do_clear_inode()`. This function temporarily sets
the inode's state in the JFFS2 inode cache to `INO_STATE_CLEARING` (value 6)
while it cleans up the inode's resources.
Concurrently, the JFFS2 background garbage collection thread (`jffs2_gcd_mtd0`)
periodically runs `jffs2_garbage_collect_pass()`. This function iterates over
the inode cache hash table to find inodes that need to be garbage collected.
When it checks the state of an inode, it uses a `switch(ic->state)` statement.
However, this switch statement does not handle the `INO_STATE_CLEARING` state.
If the garbage collector encounters an inode in this state, it falls through to
the `default:` case, which explicitly calls `BUG()`.
1. **Exploitable:** False. The bug triggers an explicit `BUG()` macro, which on
x86 translates to an invalid opcode (`ud2`). This immediately traps and causes a
kernel oops/panic. There is no memory corruption, out-of-bounds access, or
information leak involved.
2. **Denial of Service:** True. Triggering the `BUG()` will either panic the
entire system or kill the JFFS2 garbage collection kernel thread (which will
eventually render the filesystem unusable and hang tasks). Both scenarios result
in a Denial of Service.
3. **Accessible From Unprivileged Processes / User Namespaces:** True. If a
JFFS2 filesystem is already mounted and an unprivileged user has write access to
any directory within it, they can repeatedly create and delete files. This
forces inode evictions while the background garbage collector is running,
allowing them to win the race condition and crash the system.
4. **Malicious Filesystem Trigger:** True. An attacker could provide a specially
crafted JFFS2 image designed to maximize the race window (e.g., by containing a
massive number of inodes) to reliably trigger the crash upon mounting and
interacting with it.
5. **VM Guest Trigger:** True. A VM guest utilizing a JFFS2 filesystem can
trigger this bug within its own kernel.
6. **Other Triggers:** False. The bug is strictly isolated to the JFFS2
filesystem's internal garbage collection and inode eviction paths. It cannot be
triggered via network packets, remote protocols, or peripheral devices (unless a
peripheral contains a JFFS2 image that gets mounted). Exploitable:false FilesystemTrigger:true NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:true VMGuestTrigger:true VMHostTrigger:false]
|
| 1/1 |
2026/08/09 10:15 |
action |
syz-repro-to-c-repro |
0m
Results:
|
| 2/1 |
2026/08/09 10:15 |
action |
kernel-checkouter |
1m
Results: map[KernelSrc:/app/workdir/cache/src/23f34877926e4a8386855e646fda4dd9dccd99b9]
|
| 3/1 |
2026/08/09 10:17 |
action |
kernel-builder |
15m
Results: map[KernelObj:/app/workdir/cache/build/d3dbefe93dcdf062b6fd83442bb261c0aebcc946]
|
| 4/1 |
2026/08/09 10:32 |
action |
codesearch-prepare |
15m
Results: map[Index:codesearch-index]
|
| 5/1 |
2026/08/09 10:47 |
agent |
expert |
5m
Model:
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:true NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:true VMGuestTrigger:true VMHostTrigger:false]
Instruction: You are an experienced Linux kernel security engineer. Your task is to analyze given kernel bug report
and determine its security impact based on the following dimensions.
Use the provided tools to examine the source code, check for capability checks (e.g., capable(), ns_capable()),
and understand the nature of the bug. Analyze the given kernel build and configuration.
You can check the kernel config by grepping ".config" file; you can check kernel cmdline by grepping
".config" file for "CONFIG_CMDLINE=". Assume sysctl parameters have default values.
But analyze for the corresponding production build w/o debugging tools enabled (like KASAN, KMSAN, UBSAN).
Try different strategies when analyzing the bug:
- think of ways in which the vulnerable code is unreachable
- or the other way around: try to come up with different ideas of how an unprivileged user can reach the bug
If still unsure err on the side of the bug being non-exploitable/not-accessible.
In the final reply, provide a reasoning for your assessment.
Analysis dimensions:
* Exploitable:
Determine if the bug can result in memory corruption, elevated privileges, or an information leak.
Memory safety issues are almost always exploitable (KASAN or UBSAN reports for use-after-free, out-of-bounds;
refcounting issues, corrupted lists, etc). When kernel is crashing on a completely wild pointer access
(e.g. user-space address, or non-canonical address, but not on NULL or address corresponding to KASAN shadow
for NULL address), including both data accesses and control transfers, that also usually implies possibility
of exploitation. Such reports usually say "unable to handle kernel paging request".
Uses of uninitialized values detected by KMSAN may be exploitable b/c attacker frequently can affect uninit
values with spraying techniques. However, for these exploitability depends on how exactly the uninit value
is used in the code, and what it affects.
Information leaks are exploitable on their own and should be classified as such. A bug that copies kernel
memory contents to userspace (e.g. an out-of-bounds read whose result is returned to the caller, or
uninitialized stack/heap bytes written to a user buffer) is exploitable: it can reveal kernel pointer
values and defeat KASLR, expose sensitive data such as cryptographic keys or other processes' memory, and
serves as a necessary building block in most modern kernel privilege-escalation exploit chains. Do not classify
an information leak as non-exploitable solely because it does not directly cause a memory write or control-flow
hijack; the leak itself is the exploit primitive.
Think of what happens after the bug is triggered. Some bugs cause kernel panic and halt execution,
they are harder to exploit. For example, BUG reports halts the kernel. However, WARNING reports don't halt
execution in production builds. Debug bug detection tools (like KASAN, KMSAN, KCSAN, UBSAN) are also not enabled
in production builds, so attacker can freely exploit these bugs w/o being detected by these tools.
If you see an integer overflow, think how the overflowed value used later (if it's used as allocation size,
or an array index). If you see an out-of-bounds read, think if it's followed by an out-of-bounds write as well.
Some KCSAN data-races may be exploitable by skilled attackers as well. Think what data structures got corrupted
as the result of data races and how. However, note that kernel has lots of "benign" data races that don't lead
to any runtime misbehavior at all.
* Denial Of Service:
Determine if the bug can result in denial-of-service. Most bugs can, since they cause system crash,
hangs, deadlocks, or resource leaks. This is mostly applicable to WARNING bugs that won't cause system crash
in production. For these think what will be consequences of the violation of the kernel assumptions flagged
by the WARNING. In some cases the unexpected condition is also properly handled by the normal control flow
(e.g. with "if (WARN_ON(...))"), these won't cause denial-of-service. If the condition is not handled,
then it may or may not cause denial-of-service.
* Accessible From Unprivileged Processes:
Determine if the bug can be reached from a typical (non-root) user process that does NOT have any special capabilities
(like CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON) or access to device nodes restricted to root.
Assume that unprivileged_bpf_disabled=1, that is eBPF loading is not accessible. However, cBPF (classical BPF)
is still accessible to non-root processes.
Assume that user namespaces are not accessible, that is, the process cannot get the mentioned capabilities even
within a new user namespace (checked by ns_capable() function in the kernel sources).
* Accessible From User Namespaces:
Determine if the bug can be reached within a user-namespace where the process has all capabilities
(including CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON). Such capabilities are checked with ns_capable()
function in the kernel sources.
* VM Guest Trigger:
Determine if the bug can be triggered from the context of a typical KVM guest (e.g., set up by a QEMU VMM).
Consider accesses to standard Linux host paravirtualized features (virtio-blk, virtio-net, etc.),
and handling of VM exits in the KVM code.
* VM Host Trigger in The Confidential Computing Context:
Determine if the bug can be triggered in a confidential computing guest kernel from the context of a KVM host.
Consider access to standard Linux guest paravirtualized features (virtio-blk, virtio-net, etc.).
* Ethernet Network Trigger:
Determine if the bug can be triggered by processing ingress network Ethernet traffic, either directly (network stack)
or via drivers exposed to network data.
* Other Remote Trigger:
Determine if the bug can be triggered by processing remote traffic other than Ethernet (Wifi, Bluetooth, NFC, etc).
* Peripheral Trigger:
Determine if the bug can be triggered via an untrusted peripheral device that can be physically plugged
into a system, such as a USB device or a niche hardware driver handling external hardware inputs.
This is particularly important for mobile and desktop environments where users can plug in unknown devices.
* Malicious Filesystem Trigger:
Determine if the bug can be triggered by the kernel mounting and parsing a malicious filesystem image.
This is highly critical for Desktop and Mobile environments where external media or downloaded images
might be auto-mounted.
Don't make assumptions about the kernel source code (it may be different from what you assume it is).
Extensively use the provided code access tools (codesearch-*, git-*, grepper, etc)
to examine the actual source code, and confirm any assumptions.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt:
The kernel bug report is:
------------[ cut here ]------------
kernel BUG at fs/jffs2/gc.c:226!
Oops: invalid opcode: 0000 [#1] SMP KASAN PTI
CPU: 0 UID: 0 PID: 7620 Comm: jffs2_gcd_mtd0 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
RIP: 0010:jffs2_garbage_collect_pass+0x20e7/0x2170 fs/jffs2/gc.c:226
Code: 6b f7 fd 48 8b 7c 24 20 e8 06 6b 16 08 90 0f 0b e8 de de 95 fe bf 02 00 00 00 e8 34 44 64 fe e9 9d e7 ff ff e8 ca de 95 fe 90 <0f> 0b e8 c2 de 95 fe bf 02 00 00 00 e8 18 44 64 fe e9 7a f8 ff ff
RSP: 0018:ffffc900041b7aa0 EFLAGS: 00010293
RAX: ffffffff832ffa76 RBX: 0000000000000006 RCX: ffff888029738000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffffc900041b7c70 R08: ffff888029738000 R09: 0000000000000006
R10: 0000000000000100 R11: 0000000000000005 R12: ffff8880357c6410
R13: ffff88805f5ef700 R14: 1ffff1100bebdee2 R15: ffff88805f5ef712
FS: 0000000000000000(0000) GS:ffff888125c3e000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f06a384fffc CR3: 0000000056094000 CR4: 00000000003526f0
Call Trace:
<TASK>
jffs2_garbage_collect_thread+0x634/0x6c0 fs/jffs2/background.c:155
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:jffs2_garbage_collect_pass+0x20e7/0x2170 fs/jffs2/gc.c:226
Code: 6b f7 fd 48 8b 7c 24 20 e8 06 6b 16 08 90 0f 0b e8 de de 95 fe bf 02 00 00 00 e8 34 44 64 fe e9 9d e7 ff ff e8 ca de 95 fe 90 <0f> 0b e8 c2 de 95 fe bf 02 00 00 00 e8 18 44 64 fe e9 7a f8 ff ff
RSP: 0018:ffffc900041b7aa0 EFLAGS: 00010293
RAX: ffffffff832ffa76 RBX: 0000000000000006 RCX: ffff888029738000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffffc900041b7c70 R08: ffff888029738000 R09: 0000000000000006
R10: 0000000000000100 R11: 0000000000000005 R12: ffff8880357c6410
R13: ffff88805f5ef700 R14: 1ffff1100bebdee2 R15: ffff88805f5ef712
FS: 0000000000000000(0000) GS:ffff888125c3e000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f06a384fffc CR3: 0000000056094000 CR4: 00000000003526f0
Reply: **Analysis and Reasoning:**
The bug is a race condition in the JFFS2 filesystem's garbage collection mechanism.
When a file is deleted and its last reference is closed, the VFS evicts the inode, which invokes `jffs2_do_clear_inode()`. This function temporarily sets the inode's state in the JFFS2 inode cache to `INO_STATE_CLEARING` (value 6) while it cleans up the inode's resources.
Concurrently, the JFFS2 background garbage collection thread (`jffs2_gcd_mtd0`) periodically runs `jffs2_garbage_collect_pass()`. This function iterates over the inode cache hash table to find inodes that need to be garbage collected. When it checks the state of an inode, it uses a `switch(ic->state)` statement. However, this switch statement does not handle the `INO_STATE_CLEARING` state. If the garbage collector encounters an inode in this state, it falls through to the `default:` case, which explicitly calls `BUG()`.
1. **Exploitable:** False. The bug triggers an explicit `BUG()` macro, which on x86 translates to an invalid opcode (`ud2`). This immediately traps and causes a kernel oops/panic. There is no memory corruption, out-of-bounds access, or information leak involved.
2. **Denial of Service:** True. Triggering the `BUG()` will either panic the entire system or kill the JFFS2 garbage collection kernel thread (which will eventually render the filesystem unusable and hang tasks). Both scenarios result in a Denial of Service.
3. **Accessible From Unprivileged Processes / User Namespaces:** True. If a JFFS2 filesystem is already mounted and an unprivileged user has write access to any directory within it, they can repeatedly create and delete files. This forces inode evictions while the background garbage collector is running, allowing them to win the race condition and crash the system.
4. **Malicious Filesystem Trigger:** True. An attacker could provide a specially crafted JFFS2 image designed to maximize the race window (e.g., by containing a massive number of inodes) to reliably trigger the crash upon mounting and interacting with it.
5. **VM Guest Trigger:** True. A VM guest utilizing a JFFS2 filesystem can trigger this bug within its own kernel.
6. **Other Triggers:** False. The bug is strictly isolated to the JFFS2 filesystem's internal garbage collection and inode eviction paths. It cannot be triggered via network packets, remote protocols, or peripheral devices (unless a peripheral contains a JFFS2 image that gets mounted).
|
| 6/2 |
2026/08/09 10:47 |
llm |
expert |
0m
Model:
Tokens:
input: 7364
output: 38
thoughts: 85
Thoughts: Here's my analysis of the situation:
**Investigating a JFFS2 Garbage Collection Bug**
Okay, so I've got a kernel bug report pointing directly to `fs/jffs2/gc.c:226`. My immediate thought is, let's dive into that code. It's in `jffs2_garbage_collect_pass`, and the stack trace clearly shows this function being called from `jffs2_garbage_collect_thread`. This narrows down the problem substantially. Time to open up that file, specifically around line 226, and start tracing the execution path. I need to understand *why* this specific line is triggering a kernel BUG. Is it a data corruption issue, a race condition, a memory allocation problem? The specifics are still unclear, but the starting point is defined - line 226 of `fs/jffs2/gc.c`. Let's get to work.
|
| 7/2 |
2026/08/09 10:48 |
tool |
read-file |
0m
Args: map[File:fs/jffs2/gc.c FirstLine:200 LineCount:50]
Results: map[Contents: 200: case INO_STATE_PRESENT:
201: spin_unlock(&c->inocache_lock);
202: continue;
203:
204: case INO_STATE_GC:
205: case INO_STATE_CHECKING:
206: pr_warn("Inode #%u is in state %d during CRC check phase!\n",
207: ic->ino, ic->state);
208: spin_unlock(&c->inocache_lock);
209: BUG();
210:
211: case INO_STATE_READING:
212: /* We need to wait for it to finish, lest we move on
213: and trigger the BUG() above while we haven't yet
214: finished checking all its nodes */
215: jffs2_dbg(1, "Waiting for ino #%u to finish reading\n",
216: ic->ino);
217: /* We need to come back again for the _same_ inode. We've
218: made no progress in this case, but that should be OK */
219: c->check_ino = ic->ino;
220:
221: mutex_unlock(&c->alloc_sem);
222: sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
223: return 0;
224:
225: default:
226: BUG();
227:
228: case INO_STATE_UNCHECKED:
229: ;
230: }
231: ic->state = INO_STATE_CHECKING;
232: spin_unlock(&c->inocache_lock);
233:
234: jffs2_dbg(1, "%s(): triggering inode scan of ino#%u\n",
235: __func__, ic->ino);
236:
237: ret = jffs2_do_crccheck_inode(c, ic);
238: if (ret)
239: pr_warn("Returned error for crccheck of ino #%u. Expect badness...\n",
240: ic->ino);
241:
242: jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);
243: mutex_unlock(&c->alloc_sem);
244: return ret;
245: }
246:
247: /* If there are any blocks which need erasing, erase them now */
248: if (!list_empty(&c->erase_complete_list) ||
249: !list_empty(&c->erase_pending_list)) {
]
|
| 8/2 |
2026/08/09 10:48 |
llm |
expert |
0m
Model:
Tokens:
input: 8400
output: 31
thoughts: 345
Thoughts: **Debugging a JFFS2 Garbage Collection Bug**
Okay, so I've got a `BUG()` on my hands, specifically in `fs/jffs2/gc.c` at line 226. Let's dive in. It looks like this is within the `jffs2_garbage_collect_pass` function. I see the code is handling different states related to inode caching, it seems to be in the garbage collection process.
Now, that `BUG()` is triggered when `ic->state` has a value unexpected by the code. The code expects the following `ic->state` values: `INO_STATE_PRESENT`, `INO_STATE_GC`, `INO_STATE_CHECKING`, `INO_STATE_READING`, and `INO_STATE_UNCHECKED`. My first task is to understand under what circumstances `ic->state` can take on any other value that causes the bug. The `default:` case is clearly the culprit here. I'll need to figure out how `ic->state` is set and when it gets modified to diagnose this correctly, and find what code path is causing the invalid state. I'll also need to consider possible race conditions, given the locking and sleeping in this area. Time to trace the code and see what leads to that unexpected state.
|
| 9/2 |
2026/08/09 10:48 |
tool |
grepper |
0m
Args: map[Expression:INO_STATE_ PathPrefix:fs/jffs2/]
Results: map[Output:fs/jffs2/fs.c=623=struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
--
fs/jffs2/fs.c-656- }
fs/jffs2/fs.c:657: if (ic->state != INO_STATE_CHECKEDABSENT) {
fs/jffs2/fs.c-658- /* Wait for progress. Don't just loop */
--
fs/jffs2/gc.c=124=int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
--
fs/jffs2/gc.c-162-
fs/jffs2/gc.c:163: if (ic->state != INO_STATE_CHECKEDABSENT &&
fs/jffs2/gc.c:164: ic->state != INO_STATE_PRESENT)
fs/jffs2/gc.c-165- goto got_next; /* with inocache_lock held */
--
fs/jffs2/gc.c-198- switch(ic->state) {
fs/jffs2/gc.c:199: case INO_STATE_CHECKEDABSENT:
fs/jffs2/gc.c:200: case INO_STATE_PRESENT:
fs/jffs2/gc.c-201- spin_unlock(&c->inocache_lock);
--
fs/jffs2/gc.c-203-
fs/jffs2/gc.c:204: case INO_STATE_GC:
fs/jffs2/gc.c:205: case INO_STATE_CHECKING:
fs/jffs2/gc.c-206- pr_warn("Inode #%u is in state %d during CRC check phase!\n",
--
fs/jffs2/gc.c-210-
fs/jffs2/gc.c:211: case INO_STATE_READING:
fs/jffs2/gc.c-212- /* We need to wait for it to finish, lest we move on
--
fs/jffs2/gc.c-227-
fs/jffs2/gc.c:228: case INO_STATE_UNCHECKED:
fs/jffs2/gc.c-229- ;
fs/jffs2/gc.c-230- }
fs/jffs2/gc.c:231: ic->state = INO_STATE_CHECKING;
fs/jffs2/gc.c-232- spin_unlock(&c->inocache_lock);
--
fs/jffs2/gc.c-241-
fs/jffs2/gc.c:242: jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);
fs/jffs2/gc.c-243- mutex_unlock(&c->alloc_sem);
--
fs/jffs2/gc.c-365- switch(ic->state) {
fs/jffs2/gc.c:366: case INO_STATE_CHECKEDABSENT:
fs/jffs2/gc.c-367- /* It's been checked, but it's not currently in-core.
--
fs/jffs2/gc.c-371- if (ref_flags(raw) == REF_PRISTINE)
fs/jffs2/gc.c:372: ic->state = INO_STATE_GC;
fs/jffs2/gc.c-373- else {
--
fs/jffs2/gc.c-378-
fs/jffs2/gc.c:379: case INO_STATE_PRESENT:
fs/jffs2/gc.c-380- /* It's in-core. GC must iget() it. */
--
fs/jffs2/gc.c-382-
fs/jffs2/gc.c:383: case INO_STATE_UNCHECKED:
fs/jffs2/gc.c:384: case INO_STATE_CHECKING:
fs/jffs2/gc.c:385: case INO_STATE_GC:
fs/jffs2/gc.c-386- /* Should never happen. We should have finished checking
--
fs/jffs2/gc.c-396-
fs/jffs2/gc.c:397: case INO_STATE_READING:
fs/jffs2/gc.c-398- /* Someone's currently trying to read it. We must wait for
--
fs/jffs2/gc.c-411-
fs/jffs2/gc.c:412: Q: What are the chances that the inode is back in INO_STATE_READING
fs/jffs2/gc.c-413- again by the time we next enter this function? And that this happens
--
fs/jffs2/gc.c-420-
fs/jffs2/gc.c:421: /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the
fs/jffs2/gc.c-422- node intact, and we don't have to muck about with the fragtree etc.
--
fs/jffs2/gc.c-425-
fs/jffs2/gc.c:426: if (ic->state == INO_STATE_GC) {
fs/jffs2/gc.c-427- spin_unlock(&c->inocache_lock);
--
fs/jffs2/gc.c-431- spin_lock(&c->inocache_lock);
fs/jffs2/gc.c:432: ic->state = INO_STATE_CHECKEDABSENT;
fs/jffs2/gc.c-433- wake_up(&c->inocache_wq);
--
fs/jffs2/nodelist.c=457=void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
--
fs/jffs2/nodelist.c-480- for themselves. */
fs/jffs2/nodelist.c:481: if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING)
fs/jffs2/nodelist.c-482- jffs2_free_inode_cache(old);
--
fs/jffs2/nodelist.h=158=struct jffs2_inode_cache {
--
fs/jffs2/nodelist.h-187- node without going through all the iget() nonsense */
fs/jffs2/nodelist.h:188:#define INO_STATE_UNCHECKED 0 /* CRC checks not yet done */
fs/jffs2/nodelist.h:189:#define INO_STATE_CHECKING 1 /* CRC checks in progress */
fs/jffs2/nodelist.h:190:#define INO_STATE_PRESENT 2 /* In core */
fs/jffs2/nodelist.h:191:#define INO_STATE_CHECKEDABSENT 3 /* Checked, cleared again */
fs/jffs2/nodelist.h:192:#define INO_STATE_GC 4 /* GCing a 'pristine' node */
fs/jffs2/nodelist.h:193:#define INO_STATE_READING 5 /* In read_inode() */
fs/jffs2/nodelist.h:194:#define INO_STATE_CLEARING 6 /* In clear_inode() */
fs/jffs2/nodelist.h-195-
--
fs/jffs2/readinode.c=1145=static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
--
fs/jffs2/readinode.c-1163- JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
fs/jffs2/readinode.c:1164: if (f->inocache->state == INO_STATE_READING)
fs/jffs2/readinode.c:1165: jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
fs/jffs2/readinode.c-1166- return ret;
--
fs/jffs2/readinode.c-1172- f->inocache->ino, ret);
fs/jffs2/readinode.c:1173: if (f->inocache->state == INO_STATE_READING)
fs/jffs2/readinode.c:1174: jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
fs/jffs2/readinode.c-1175- jffs2_free_tmp_dnode_info_list(&rii.tn_root);
--
fs/jffs2/readinode.c-1203- if (!rii.fds) {
fs/jffs2/readinode.c:1204: if (f->inocache->state == INO_STATE_READING)
fs/jffs2/readinode.c:1205: jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
fs/jffs2/readinode.c-1206- return -EIO;
--
fs/jffs2/readinode.c-1215- latest_node->uid = cpu_to_je16(0);
fs/jffs2/readinode.c:1216: if (f->inocache->state == INO_STATE_READING)
fs/jffs2/readinode.c:1217: jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
fs/jffs2/readinode.c-1218- return 0;
--
fs/jffs2/readinode.c-1263-
fs/jffs2/readinode.c:1264: if (f->inocache->state != INO_STATE_CHECKING) {
fs/jffs2/readinode.c-1265- /* Symlink's inode data is the target path. Read it and
--
fs/jffs2/readinode.c-1320- }
fs/jffs2/readinode.c:1321: if (f->inocache->state == INO_STATE_READING)
fs/jffs2/readinode.c:1322: jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
fs/jffs2/readinode.c-1323-
--
fs/jffs2/readinode.c=1328=int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
--
fs/jffs2/readinode.c-1339- switch(f->inocache->state) {
fs/jffs2/readinode.c:1340: case INO_STATE_UNCHECKED:
fs/jffs2/readinode.c:1341: case INO_STATE_CHECKEDABSENT:
fs/jffs2/readinode.c:1342: f->inocache->state = INO_STATE_READING;
fs/jffs2/readinode.c-1343- break;
fs/jffs2/readinode.c-1344-
fs/jffs2/readinode.c:1345: case INO_STATE_CHECKING:
fs/jffs2/readinode.c:1346: case INO_STATE_GC:
fs/jffs2/readinode.c-1347- /* If it's in either of these states, we need
--
fs/jffs2/readinode.c-1353-
fs/jffs2/readinode.c:1354: case INO_STATE_READING:
fs/jffs2/readinode.c:1355: case INO_STATE_PRESENT:
fs/jffs2/readinode.c-1356- /* Eep. This should never happen. It can
--
fs/jffs2/readinode.c-1380- f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
fs/jffs2/readinode.c:1381: f->inocache->state = INO_STATE_READING;
fs/jffs2/readinode.c-1382- jffs2_add_ino_cache(c, f->inocache);
--
fs/jffs2/readinode.c=1413=void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
--
fs/jffs2/readinode.c-1421-
fs/jffs2/readinode.c:1422: if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
fs/jffs2/readinode.c:1423: jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
fs/jffs2/readinode.c-1424-
--
fs/jffs2/readinode.c-1439-
fs/jffs2/readinode.c:1440: if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
fs/jffs2/readinode.c:1441: jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
fs/jffs2/readinode.c-1442- if (f->inocache->nodes == (void *)f->inocache)
--
fs/jffs2/wbuf.c=275=static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
--
fs/jffs2/wbuf.c-500-
fs/jffs2/wbuf.c:501: if (ic->state == INO_STATE_PRESENT && !ref_obsolete(raw)) {
fs/jffs2/wbuf.c-502- /* If it's an in-core inode, then we have to adjust any
--
fs/jffs2/wbuf.c-518- (void *)(buf?:c->wbuf) + (ref_offset(raw) - start));
fs/jffs2/wbuf.c:519: } else if (unlikely(ic->state != INO_STATE_PRESENT &&
fs/jffs2/wbuf.c:520: ic->state != INO_STATE_CHECKEDABSENT &&
fs/jffs2/wbuf.c:521: ic->state != INO_STATE_GC)) {
fs/jffs2/wbuf.c-522- JFFS2_ERROR("Inode #%u is in strange state %d!\n", ic->ino, ic->state);
--
fs/jffs2/write.c=23=int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
--
fs/jffs2/write.c-37- f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
fs/jffs2/write.c:38: f->inocache->state = INO_STATE_PRESENT;
fs/jffs2/write.c-39-
]
|
| 10/2 |
2026/08/09 10:48 |
llm |
expert |
0m
Model:
Tokens:
input: 12973
output: 46
thoughts: 2132
Thoughts: **JFFS2 Garbage Collection Race Condition Analysis**
Okay, so I've got a `BUG()` in `fs/jffs2/gc.c:226`. It's happening inside `jffs2_garbage_collect_pass`. Let's break this down. The code in question is a `switch` statement that checks the state of an inode cache entry (`ic->state`). The default case, which triggers the `BUG()`, is hit when `ic->state` isn't one of the explicitly handled states. A quick look at the possible states reveals that `INO_STATE_CLEARING` (6) is not handled. The other states handled are `INO_STATE_UNCHECKED`, `INO_STATE_CHECKING`, `INO_STATE_PRESENT`, `INO_STATE_CHECKEDABSENT`, `INO_STATE_GC` and `INO_STATE_READING`.
The stack trace confirms it's the `default: BUG();` branch. The question then becomes: how does `ic->state` get into an `INO_STATE_CLEARING` state when the garbage collector is running? I see that `INO_STATE_CLEARING` is set in `jffs2_do_clear_inode`. That function is called when an inode is being evicted from the VFS cache (using `evict_inode`). Aha! I'm seeing a race condition here. `jffs2_do_clear_inode` sets the state to `INO_STATE_CLEARING`, does its work, and *then* sets it to `INO_STATE_CHECKEDABSENT`. If the garbage collection thread, running concurrently in the background, hits an inode in the `INO_STATE_CLEARING` state *before* it gets to `INO_STATE_CHECKEDABSENT`, BAM! `BUG()`.
The garbage collection is done by a background thread, while `jffs2_do_clear_inode` is triggered by inode eviction. This is definitely a race condition between the garbage collector and inode eviction. So, is this exploitable? It's a `BUG()`, so it's a kernel panic, a denial-of-service, plain and simple. Can a malicious JFFS2 image trigger it? Yes, assuming the kernel is compiled without the `BUG()` macro, which is unlikely. Can an unprivileged user trigger it? Hmm... If they can create and delete files on a JFFS2 filesystem, they can trigger inode eviction. The GC thread runs in the background. If the JFFS2 filesystem is mountable by unprivileged users, they can cause the race condition and DoS. However, a normal file system mount generally requires `CAP_SYS_ADMIN`. Still, if they *do* have that access, then, yes, it's exploitable by an unprivileged user, causing a DoS. Since it's a `BUG()` the kernel will panic. It is not an exploitable vulnerability for privilege escalation or info leak. Let's make sure it hasn't been handled in more recent versions of the kernel. Looking at the existing reports I think this is a known bug. So, in the present implementation, a concurrent state invalidates the inode state, causing an assert.
|
| 11/2 |
2026/08/09 10:49 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/jffs2/readinode.c Name:jffs2_set_inocache_state]
Results: map[SourceCode: 408: void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state)
409: {
410: spin_lock(&c->inocache_lock);
411: ic->state = state;
412: wake_up(&c->inocache_wq);
413: spin_unlock(&c->inocache_lock);
414: }
SourceFile:fs/jffs2/nodelist.c]
|
| 12/2 |
2026/08/09 10:49 |
llm |
expert |
0m
Model:
Tokens:
input: 13879
output: 38
thoughts: 0
|
| 13/2 |
2026/08/09 10:49 |
tool |
read-file |
0m
Args: map[File:fs/jffs2/gc.c FirstLine:180 LineCount:50]
Results: map[Contents: 180: c->unchecked_size);
181: jffs2_dbg_dump_block_lists_nolock(c);
182: mutex_unlock(&c->alloc_sem);
183: return -ENOSPC;
184:
185: got_next:
186: /* For next time round the loop, we want c->checked_ino to indicate
187: * the *next* one we want to check. And since we're walking the
188: * buckets rather than doing it sequentially, it's: */
189: c->check_ino = ic->ino + c->inocache_hashsize;
190:
191: if (!ic->pino_nlink) {
192: jffs2_dbg(1, "Skipping check of ino #%d with nlink/pino zero\n",
193: ic->ino);
194: spin_unlock(&c->inocache_lock);
195: jffs2_xattr_delete_inode(c, ic);
196: continue;
197: }
198: switch(ic->state) {
199: case INO_STATE_CHECKEDABSENT:
200: case INO_STATE_PRESENT:
201: spin_unlock(&c->inocache_lock);
202: continue;
203:
204: case INO_STATE_GC:
205: case INO_STATE_CHECKING:
206: pr_warn("Inode #%u is in state %d during CRC check phase!\n",
207: ic->ino, ic->state);
208: spin_unlock(&c->inocache_lock);
209: BUG();
210:
211: case INO_STATE_READING:
212: /* We need to wait for it to finish, lest we move on
213: and trigger the BUG() above while we haven't yet
214: finished checking all its nodes */
215: jffs2_dbg(1, "Waiting for ino #%u to finish reading\n",
216: ic->ino);
217: /* We need to come back again for the _same_ inode. We've
218: made no progress in this case, but that should be OK */
219: c->check_ino = ic->ino;
220:
221: mutex_unlock(&c->alloc_sem);
222: sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
223: return 0;
224:
225: default:
226: BUG();
227:
228: case INO_STATE_UNCHECKED:
229: ;
]
|
| 14/2 |
2026/08/09 10:49 |
llm |
expert |
0m
Model:
Tokens:
input: 14722
output: 38
thoughts: 0
|
| 15/2 |
2026/08/09 10:49 |
tool |
read-file |
0m
Args: map[File:fs/jffs2/gc.c FirstLine:140 LineCount:50]
Results: map[Contents: 140: the node CRCs etc. */
141: int bucket, want_ino;
142:
143: spin_lock(&c->erase_completion_lock);
144: if (!c->unchecked_size)
145: break;
146: spin_unlock(&c->erase_completion_lock);
147:
148: if (!xattr)
149: xattr = jffs2_verify_xattr(c);
150:
151: spin_lock(&c->inocache_lock);
152: /* Instead of doing the inodes in numeric order, doing a lookup
153: * in the hash for each possible number, just walk the hash
154: * buckets of *existing* inodes. This means that we process
155: * them out-of-order, but it can be a lot faster if there's
156: * a sparse inode# space. Which there often is. */
157: want_ino = c->check_ino;
158: for (bucket = c->check_ino % c->inocache_hashsize ; bucket < c->inocache_hashsize; bucket++) {
159: for (ic = c->inocache_list[bucket]; ic; ic = ic->next) {
160: if (ic->ino < want_ino)
161: continue;
162:
163: if (ic->state != INO_STATE_CHECKEDABSENT &&
164: ic->state != INO_STATE_PRESENT)
165: goto got_next; /* with inocache_lock held */
166:
167: jffs2_dbg(1, "Skipping ino #%u already checked\n",
168: ic->ino);
169: }
170: want_ino = 0;
171: }
172:
173: /* Point c->check_ino past the end of the last bucket. */
174: c->check_ino = ((c->highest_ino + c->inocache_hashsize + 1) &
175: ~c->inocache_hashsize) - 1;
176:
177: spin_unlock(&c->inocache_lock);
178:
179: pr_crit("Checked all inodes but still 0x%x bytes of unchecked space?\n",
180: c->unchecked_size);
181: jffs2_dbg_dump_block_lists_nolock(c);
182: mutex_unlock(&c->alloc_sem);
183: return -ENOSPC;
184:
185: got_next:
186: /* For next time round the loop, we want c->checked_ino to indicate
187: * the *next* one we want to check. And since we're walking the
188: * buckets rather than doing it sequentially, it's: */
189: c->check_ino = ic->ino + c->inocache_hashsize;
]
|
| 16/2 |
2026/08/09 10:49 |
llm |
expert |
1m
Model:
Tokens:
input: 15621
output: 42
thoughts: 0
|
| 17/2 |
2026/08/09 10:50 |
tool |
git-log |
0m
Args: map[CodeRegexp:BUG\(\) Count:10 PathPrefix:fs/jffs2/gc.c]
Results: map[Output:44b998e1eb25 [JFFS2] Improve failure mode if inode checking leaves unchecked space.
182ec4eee397 [JFFS2] Clean up trailing white spaces
e0c8e42f8f21 [JFFS2] Debug code clean up - step 3
1da177e4c3f4 Linux-2.6.12-rc2
]
|
| 18/2 |
2026/08/09 10:50 |
llm |
expert |
0m
Model:
Tokens:
input: 15775
output: 26
thoughts: 0
|
| 19/2 |
2026/08/09 10:50 |
tool |
git-show |
0m
Args:
Results: map[Output:commit 44b998e1eb254edc87177819ee693690fac68b7f
Author: David Woodhouse <dwmw2@infradead.org>
Date: Mon Apr 23 12:11:46 2007 +0100
[JFFS2] Improve failure mode if inode checking leaves unchecked space.
We should never find the unchecked size is non-zero after we've finished
checking all inodes. If it happens, used to BUG(), leaving the alloc_sem
held and deadlocking. Instead, just return -ENOSPC after complaining. The
GC thread will die, but read-only operation should be able to continue and
the file system should be unmountable.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 3a3cf225981f..e92cf0f02529 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -144,7 +144,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
c->unchecked_size);
jffs2_dbg_dump_block_lists_nolock(c);
spin_unlock(&c->erase_completion_lock);
- BUG();
+ up(&c->alloc_sem);
+ return -ENOSPC;
}
spin_unlock(&c->erase_completion_lock);
]
|
| 20/2 |
2026/08/09 10:50 |
llm |
expert |
0m
Model:
Tokens:
input: 16247
output: 34
thoughts: 1184
Thoughts: **Analyzing a JFFS2 Garbage Collection Bug**
Okay, so I'm looking at this bug report. It points to a `BUG()` in `fs/jffs2/gc.c` at line 226. Let's dig in. The code snippet shows a switch statement on `ic->state` within the `jffs2_garbage_collect_pass` function. The `BUG()` is triggered in the `default:` case of this switch. My initial thought is to figure out under what conditions this `default` is hit.
The switch handles several states, and it seems the `BUG()` is hit when `ic->state` isn't one of the expected values, or specifically, if it's `INO_STATE_GC` or `INO_STATE_CHECKING`, it triggers a warning and a `BUG()`. I need to figure out the value that actually hits the bug.
I quickly check the enum definitions for `INO_STATE_*`. Okay, the states are: `INO_STATE_UNCHECKED`, `INO_STATE_CHECKING`, `INO_STATE_PRESENT`, `INO_STATE_CHECKEDABSENT`, `INO_STATE_GC`, `INO_STATE_READING`, and `INO_STATE_CLEARING`. Line 226 is `default: BUG()`. Wait, `INO_STATE_CLEARING` is 6! It's not handled.
It seems the debugger shows that register `RBX` is 6, which likely corresponds to `ic->state`. So, the `BUG()` is triggered when `ic->state` is `INO_STATE_CLEARING`. This means the garbage collector is trying to process an inode that's in the process of being cleared (evicted from memory). That's a definite oversight, I should look into the reason for this.
The `jffs2_garbage_collect_pass` function is called by the `jffs2_garbage_collect_thread`. That's the background garbage collection thread. If an inode is in the `INO_STATE_CLEARING` state, it means it's being cleared. Let's look at where that state is set. Bingo, `jffs2_do_clear_inode` sets the state to `INO_STATE_CLEARING`.
So, the race condition is between inode eviction (clear) and garbage collection. This is a classic race condition issue.
Since this involves a filesystem, this requires a mounted JFFS2 image. Can this be triggered by a malicious image? Yes, I'd say so. Or even by normal file operations on a JFFS2 filesystem if the timings are just right.
Exploitable? Well, it's a `BUG()` which will halt the kernel, so a Denial of Service. Not memory corruption, which is less severe, but still, a crash.
Can unprivileged processes trigger it? Mounting generally requires `CAP_SYS_ADMIN`, but what about user namespaces? Oh, wait... JFFS2 doesn't have the `FS_USERNS_MOUNT` flag, so that's not a concern. Still, mounting requires elevated privileges. But, the bug exists, and the kernel would halt, so it's a serious flaw.
|
| 21/2 |
2026/08/09 10:50 |
tool |
grepper |
0m
Error:
Args: map[Expression:FS_USERNS_MOUNT PathPrefix:fs/jffs2/]
Results:
|
| 22/2 |
2026/08/09 10:50 |
llm |
expert |
0m
Model:
Tokens:
input: 20742
output: 41
thoughts: 406
Thoughts: **Analyzing the JFFS2 DoS Vulnerability**
Okay, so the initial takeaway is that JFFS2 doesn't support `FS_USERNS_MOUNT`, meaning it can't be mounted within a user namespace. That limits the attack surface somewhat. But, can an unprivileged user still trigger this on a system where JFFS2 is already mounted? And the answer is yes, unfortunately. If an unprivileged user has access to a JFFS2 filesystem – like on an embedded device where the root or home directory uses it – simple operations like creating and deleting files can trigger inode eviction. This, in turn, kicks off the garbage collection (GC) thread, and that's where the race condition resides, leading to a denial-of-service, a kernel panic.
The next question: Is this something I need to worry about for privilege escalation? No. It's a `BUG()`, so this is a DoS, which is a different class of problem. Can this be triggered by a malicious filesystem image? Yes, someone could create a malicious JFFS2 image and trick a victim into mounting it, which is definitely a concern. However, I need to remind myself that this bug isn't solely dependent on malicious images. It can occur during normal operation, just amplified with a crafted malicious image with a lot of inodes which widens the window for the race condition.
I need to explore the attack vectors further. Is there any other way to trigger this? The fact that it is a DoS makes this an important issue. Can a VM guest trigger it? If the guest itself is running JFFS2, sure, but that's within the guest. Can it affect the host? No, JFFS2 is a local filesystem. What about network access? No, that's not a path. Via a peripheral? Ah, yes, if a USB drive contains a JFFS2 image and the system auto-mounts it, then there's an exposure.
Let's dive into the exploitability. The code snippet is a straightforward `BUG()`. It's not a memory corruption, which is one less thing to analyze. The code just hits an explicit `BUG()`. It’s a DoS, plain and simple.
Now, let me just check the patch history… to see if this has been addressed.
|
| 23/2 |
2026/08/09 10:51 |
tool |
git-log |
0m
Args: map[CodeRegexp:INO_STATE_CLEARING Count:10 PathPrefix:fs/jffs2/]
Results: map[Output:67e345d17ff8 [JFFS2] Prevent ino cache removal for inodes in use
]
|
| 24/2 |
2026/08/09 10:51 |
llm |
expert |
0m
Model:
Tokens:
input: 21724
output: 26
thoughts: 0
|
| 25/2 |
2026/08/09 10:51 |
tool |
git-show |
0m
Args:
Results: map[Output:commit 67e345d17ff8c2085a54c293001ae548f7be7b21
Author: David Woodhouse <dwmw2@infradead.org>
Date: Sun Feb 27 23:01:36 2005 +0000
[JFFS2] Prevent ino cache removal for inodes in use
Don't remove inocache for inodes which are in read_inode() or
clear_inode() until they're done.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index a3c6cc150497..d1ae565352a6 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -7,7 +7,7 @@
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: erase.c,v 1.71 2005/02/09 09:17:40 pavlov Exp $
+ * $Id: erase.c,v 1.72 2005/02/27 23:01:32 dwmw2 Exp $
*
*/
@@ -277,11 +277,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
printk("\n");
});
- if (ic->nodes == (void *)ic) {
- D1(printk(KERN_DEBUG "inocache for ino #%u is all gone now. Freeing\n", ic->ino));
+ if (ic->nodes == (void *)ic)
jffs2_del_ino_cache(c, ic);
- jffs2_free_inode_cache(ic);
- }
}
static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 3c6d93c8ea0a..b835a8652623 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -7,7 +7,7 @@
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: nodelist.c,v 1.92 2005/01/19 19:22:00 tpoynor Exp $
+ * $Id: nodelist.c,v 1.93 2005/02/27 23:01:32 dwmw2 Exp $
*
*/
@@ -506,7 +506,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
{
struct jffs2_inode_cache **prev;
- D2(printk(KERN_DEBUG "jffs2_del_ino_cache: Del %p (ino #%u)\n", old, old->ino));
+ D1(printk(KERN_DEBUG "jffs2_del_ino_cache: Del %p (ino #%u)\n", old, old->ino));
spin_lock(&c->inocache_lock);
prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE];
@@ -518,6 +518,14 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
*prev = old->next;
}
+ /* Free it now unless it's in READING or CLEARING state, which
+ are the transitions upon read_inode() and clear_inode(). The
+ rest of the time we know nobody else is looking at it, and
+ if it's held by read_inode() or clear_inode() they'll free it
+ for themselves. */
+ if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING)
+ jffs2_free_inode_cache(old);
+
spin_unlock(&c->inocache_lock);
}
@@ -530,7 +538,6 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
this = c->inocache_list[i];
while (this) {
next = this->next;
- D2(printk(KERN_DEBUG "jffs2_free_ino_caches: Freeing ino #%u at %p\n", this->ino, this));
jffs2_free_inode_cache(this);
this = next;
}
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 8c122838bf6d..57f675c2c97f 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -7,7 +7,7 @@
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: nodelist.h,v 1.127 2005/02/09 09:23:53 pavlov Exp $
+ * $Id: nodelist.h,v 1.128 2005/02/27 23:01:32 dwmw2 Exp $
*
*/
@@ -135,6 +135,7 @@ struct jffs2_inode_cache {
#define INO_STATE_CHECKEDABSENT 3 /* Checked, cleared again */
#define INO_STATE_GC 4 /* GCing a 'pristine' node */
#define INO_STATE_READING 5 /* In read_inode() */
+#define INO_STATE_CLEARING 6 /* In clear_inode() */
#define INOCACHE_HASHSIZE 128
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 5e1e8caf54e8..f9dcac1415ac 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -7,7 +7,7 @@
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: nodemgmt.c,v 1.117 2005/01/25 20:11:11 hammache Exp $
+ * $Id: nodemgmt.c,v 1.118 2005/02/27 23:01:32 dwmw2 Exp $
*
*/
@@ -593,11 +593,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
*p = ref->next_in_ino;
ref->next_in_ino = NULL;
- if (ic->nodes == (void *)ic) {
- D1(printk(KERN_DEBUG "inocache for ino #%u is all gone now. Freeing\n", ic->ino));
+ if (ic->nodes == (void *)ic)
jffs2_del_ino_cache(c, ic);
- jffs2_free_inode_cache(ic);
- }
spin_unlock(&c->erase_completion_lock);
}
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index aca4a0b17bcd..a1980a9da531 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -7,7 +7,7 @@
*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: readinode.c,v 1.117 2004/11/20 18:06:54 dwmw2 Exp $
+ * $Id: readinode.c,v 1.118 2005/02/27 23:01:33 dwmw2 Exp $
*
*/
@@ -672,6 +672,9 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
down(&f->sem);
deleted = f->inocache && !f->inocache->nlink;
+ if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
+ jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
+
if (f->metadata) {
if (deleted)
jffs2_mark_node_obsolete(c, f->metadata->raw);
@@ -688,8 +691,11 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
jffs2_free_full_dirent(fd);
}
- if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
+ if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
+ if (f->inocache->nodes == (void *)f->inocache)
+ jffs2_del_ino_cache(c, f->inocache);
+ }
up(&f->sem);
}
]
|
| 26/2 |
2026/08/09 10:51 |
llm |
expert |
0m
Model:
Tokens:
input: 24571
output: 44
thoughts: 1495
Thoughts: **Analyzing a Potential Race Condition in JFFS2 Garbage Collection**
Okay, so I'm looking at this JFFS2 code and it's got my attention. `INO_STATE_CLEARING` was introduced back in 2005, and it looks like `jffs2_garbage_collect_pass` wasn't updated to properly handle it. My initial thought was that if `jffs2_garbage_collect_pass` encounters an inode in the `INO_STATE_CLEARING` state, it'll hit a `BUG()`.
Let's dig deeper: I see that `jffs2_garbage_collect_pass` has a `switch` statement on `ic->state`, and the `default` case *is* a `BUG()`! The code specifically checks for `INO_STATE_CHECKEDABSENT`, `INO_STATE_PRESENT`, `INO_STATE_GC`, `INO_STATE_CHECKING`, and `INO_STATE_READING`. So that `BUG()` will be hit if the state is anything else.
Now, could `jffs2_garbage_collect_pass` *actually* see `INO_STATE_CLEARING`? Let's see: `jffs2_do_clear_inode` sets the inode state to `INO_STATE_CLEARING` and then proceeds to do stuff like freeing nodes. The crucial thing is that this happens *without* holding `c->inocache_lock`, but it *does* hold `f->sem` for file operations. Also, `jffs2_set_inocache_state` acquires and releases `c->inocache_lock`, so changes to `ic->state` are visible to other threads.
So the garbage collector acquires `c->inocache_lock` and reads the state; if it's `INO_STATE_CLEARING`, boom, `BUG()`. This seems like a textbook race condition. Is this a known bug? Yes, it seems like others have run into it.
I'm starting to visualize the sequence. The garbage collection has a loop, and inside that loop, it encounters an inode. If the inode is in `INO_STATE_CLEARING`, it skips a few checks via `goto got_next`. Then, right after `got_next` there's another `switch(ic->state)`. If the inode's `pino_nlink` is non-zero, it means the inode is still linked, and the state will be checked again, which will hit the `BUG()`!
The `jffs2_do_clear_inode` function is called when an inode is evicted from the VFS cache. If an inode is evicted, `jffs2_evict_inode` is called, which calls `jffs2_do_clear_inode`. If an inode is closed and then evicted from the VFS cache due to memory pressure, it means `pino_nlink` is non-zero (it's *linked*), `INO_STATE_CLEARING` is set, and *then* the garbage collector comes along, and kaboom! We've got a race.
This seems frighteningly easy to trigger: cause a bit of memory pressure and trigger a garbage collection at the same time. How has this not been fixed yet? Time to check the patch database...
|
| 27/2 |
2026/08/09 10:51 |
tool |
git-log |
0m
Args: map[CodeRegexp:INO_STATE_CLEARING Count:10 PathPrefix:fs/jffs2/gc.c]
Results:
|
| 28/2 |
2026/08/09 10:51 |
llm |
expert |
0m
Model:
Tokens:
input: 26857
output: 36
thoughts: 58
Thoughts: **Investigating `INO_STATE_CLEARING` in JFFS2 Garbage Collection**
Okay, so I'm looking at `fs/jffs2/gc.c` and I'm not seeing any direct references to `INO_STATE_CLEARING` in the current patch set. That's a bit odd, so my next move is to verify whether or not this state is actually *handled* within the garbage collection logic in the latest kernel version. It's possible the state is used elsewhere and the gc interacts through another mechanism, or that it is handled in the latest kernel in a way that is not immediately apparent. I need to dig deeper into the current code and consider how `INO_STATE_CLEARING` impacts the overall JFFS2 garbage collection process to determine whether any changes or further investigation is required.
|
| 29/2 |
2026/08/09 10:51 |
tool |
grepper |
0m
Error:
Args: map[Expression:INO_STATE_CLEARING PathPrefix:fs/jffs2/gc.c]
Results:
|
| 30/2 |
2026/08/09 10:51 |
llm |
expert |
0m
Model:
Tokens:
input: 21436
output: 33
thoughts: 0
|
| 31/2 |
2026/08/09 10:51 |
tool |
grepper |
0m
Args: map[Expression:INO_STATE_CLEARING PathPrefix:fs/jffs2/]
Results: map[Output:fs/jffs2/nodelist.c=457=void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
--
fs/jffs2/nodelist.c-480- for themselves. */
fs/jffs2/nodelist.c:481: if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING)
fs/jffs2/nodelist.c-482- jffs2_free_inode_cache(old);
--
fs/jffs2/nodelist.h=158=struct jffs2_inode_cache {
--
fs/jffs2/nodelist.h-193-#define INO_STATE_READING 5 /* In read_inode() */
fs/jffs2/nodelist.h:194:#define INO_STATE_CLEARING 6 /* In clear_inode() */
fs/jffs2/nodelist.h-195-
--
fs/jffs2/readinode.c=1413=void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
--
fs/jffs2/readinode.c-1422- if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
fs/jffs2/readinode.c:1423: jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
fs/jffs2/readinode.c-1424-
]
|
| 32/2 |
2026/08/09 10:51 |
llm |
expert |
0m
Model:
Tokens:
input: 21923
output: 32
thoughts: 3080
Thoughts: **Analysis of JFFS2 Inode State Race Condition**
Okay, so I've got a `BUG()` in `fs/jffs2/gc.c` at line 226. It's triggered by a `default:` case in a `switch` statement that handles the inode cache (`inocache`) states. The offending code specifically doesn't account for the `INO_STATE_CLEARING` state, which was introduced in commit `67e345d17ff8c2085a54c293001ae548f7be7b21`. Essentially, the garbage collector thread (`jffs2_garbage_collect_thread`) is iterating through the inode cache and, due to a race condition, encounters an inode that is currently being cleared (in `INO_STATE_CLEARING` within `jffs2_do_clear_inode`). `jffs2_do_clear_inode` sets the state to `INO_STATE_CLEARING`, does some work, and then sets it to `INO_STATE_CHECKEDABSENT`. The GC thread doesn't expect `INO_STATE_CLEARING`, so it hits `BUG()`.
This is a DoS, obviously, since the kernel panics. It isn't a memory corruption issue, but a logic error. Crucially, it's triggered by the concurrency between inode clearing and garbage collection.
Now, can an unprivileged user trigger this? Potentially, yes. JFFS2 is a flash filesystem commonly used in embedded devices. While unprivileged users *typically* cannot mount a JFFS2 filesystem, this depends on the configuration. If the filesystem is already mounted (likely by root or a privileged user), and the user has write access to create/delete files, they can trigger the race condition by deleting files, which leads to inodes being cleared and, concurrently, the garbage collector running. Deleting a file drops its link count to 0, and when the last file descriptor is closed, `jffs2_do_clear_inode` is called. The garbage collector thread is always running in the background.
So, while mounting a specifically malicious image isn't required (though, providing a JFFS2 image could be a path to trigger it), normal filesystem operations (creating and deleting files) can expose this vulnerability if the JFFS2 filesystem is mounted and accessible for write by a given user. This also implies it is exploitable in a UserNamespace and potentially VM Guest as well. The bug is exposed through normal operations on an already mounted JFFS2 filesystem.
Let's quickly recap: If `ic->state` is `INO_STATE_CLEARING`, and the garbage collector runs the `switch` statement with that state, it hits `default: BUG();` This will cause a kernel panic, leading to a denial of service (DoS). Even with the `!ic->pino_nlink` check, we hit the `switch` statement.
|
| 33/2 |
2026/08/09 10:52 |
tool |
grepper |
0m
Args: map[Expression:pino_nlink PathPrefix:fs/jffs2/]
Results: map[Output:fs/jffs2/build.c=52=static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
--
fs/jffs2/build.c-79- fd->ic = child_ic;
fs/jffs2/build.c:80: child_ic->pino_nlink++;
fs/jffs2/build.c-81- /* If we appear (at this stage) to have hard-linked directories,
--
fs/jffs2/build.c-84- child_ic->flags |= INO_FLAGS_IS_DIR;
fs/jffs2/build.c:85: if (child_ic->pino_nlink > 1)
fs/jffs2/build.c-86- *dir_hardlinks = 1;
--
fs/jffs2/build.c=99=static int jffs2_build_filesystem(struct jffs2_sb_info *c)
--
fs/jffs2/build.c-139- for_each_inode(i, c, ic) {
fs/jffs2/build.c:140: if (ic->pino_nlink)
fs/jffs2/build.c-141- continue;
--
fs/jffs2/build.c-166- * around and not yet garbage-collected, but which have
fs/jffs2/build.c:167: * been discarded above. So clear the pino_nlink field
fs/jffs2/build.c-168- * in each directory, so that the final scan below can
--
fs/jffs2/build.c-171- if (ic->flags & INO_FLAGS_IS_DIR)
fs/jffs2/build.c:172: ic->pino_nlink = 0;
fs/jffs2/build.c-173- }
--
fs/jffs2/build.c-181- ic->scan_dents = fd->next;
fs/jffs2/build.c:182: /* We do use the pino_nlink field to count nlink of
fs/jffs2/build.c-183- * directories during fs build, so set it to the
--
fs/jffs2/build.c-195-
fs/jffs2/build.c:196: /* We clear ic->pino_nlink ∀ directories' ic *only* if dir_hardlinks
fs/jffs2/build.c-197- * is set. Otherwise, we know this should never trigger anyway, so
fs/jffs2/build.c:198: * we don't do the check. And ic->pino_nlink still contains the nlink
fs/jffs2/build.c-199- * value (which is 1). */
fs/jffs2/build.c:200: if (dir_hardlinks && fd->ic->pino_nlink) {
fs/jffs2/build.c-201- JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n",
fs/jffs2/build.c:202: fd->name, fd->ino, ic->ino, fd->ic->pino_nlink);
fs/jffs2/build.c-203- /* Should we unlink it from its previous parent? */
--
fs/jffs2/build.c-205-
fs/jffs2/build.c:206: /* For directories, ic->pino_nlink holds that parent inode # */
fs/jffs2/build.c:207: fd->ic->pino_nlink = ic->ino;
fs/jffs2/build.c-208- }
--
fs/jffs2/build.c=242=static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c,
--
fs/jffs2/build.c-289- dead_fds list to be cleaned up later. Else just free the fd */
fs/jffs2/build.c:290: child_ic->pino_nlink--;
fs/jffs2/build.c-291-
fs/jffs2/build.c:292: if (!child_ic->pino_nlink) {
fs/jffs2/build.c-293- dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
--
fs/jffs2/build.c-298- dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
fs/jffs2/build.c:299: fd->ino, fd->name, child_ic->pino_nlink);
fs/jffs2/build.c-300- jffs2_free_full_dirent(fd);
--
fs/jffs2/dir.c=165=static int jffs2_create(struct mnt_idmap *idmap, struct inode *dir_i,
--
fs/jffs2/dir.c-215- __func__, inode->i_ino, inode->i_mode, inode->i_nlink,
fs/jffs2/dir.c:216: f->inocache->pino_nlink, inode->i_mapping->nrpages);
fs/jffs2/dir.c-217-
--
fs/jffs2/dir.c=230=static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
--
fs/jffs2/dir.c-240- if (dead_f->inocache)
fs/jffs2/dir.c:241: set_nlink(d_inode(dentry), dead_f->inocache->pino_nlink);
fs/jffs2/dir.c-242- if (!ret)
--
fs/jffs2/dir.c=250=static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
--
fs/jffs2/dir.c-274- mutex_lock(&f->sem);
fs/jffs2/dir.c:275: set_nlink(d_inode(old_dentry), ++f->inocache->pino_nlink);
fs/jffs2/dir.c-276- mutex_unlock(&f->sem);
--
fs/jffs2/dir.c=451=static struct dentry *jffs2_mkdir (struct mnt_idmap *idmap, struct inode *dir_i,
--
fs/jffs2/dir.c-499- set_nlink(inode, 2);
fs/jffs2/dir.c:500: /* but ic->pino_nlink is the parent ino# */
fs/jffs2/dir.c:501: f->inocache->pino_nlink = dir_i->i_ino;
fs/jffs2/dir.c-502-
--
fs/jffs2/dir.c=774=static int jffs2_rename (struct mnt_idmap *idmap,
--
fs/jffs2/dir.c-838- if (d_is_dir(new_dentry))
fs/jffs2/dir.c:839: victim_f->inocache->pino_nlink = 0;
fs/jffs2/dir.c-840- else
fs/jffs2/dir.c:841: victim_f->inocache->pino_nlink--;
fs/jffs2/dir.c-842- mutex_unlock(&victim_f->sem);
--
fs/jffs2/dir.c-862- if (f->inocache && !d_is_dir(old_dentry))
fs/jffs2/dir.c:863: f->inocache->pino_nlink++;
fs/jffs2/dir.c-864- mutex_unlock(&f->sem);
--
fs/jffs2/erase.c=206=static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
--
fs/jffs2/erase.c-281- default:
fs/jffs2/erase.c:282: if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
fs/jffs2/erase.c-283- jffs2_del_ino_cache(c, ic);
--
fs/jffs2/fs.c=253=struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
--
fs/jffs2/fs.c-288-
fs/jffs2/fs.c:289: set_nlink(inode, f->inocache->pino_nlink);
fs/jffs2/fs.c-290-
--
fs/jffs2/gc.c=124=int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
--
fs/jffs2/gc.c-190-
fs/jffs2/gc.c:191: if (!ic->pino_nlink) {
fs/jffs2/gc.c-192- jffs2_dbg(1, "Skipping check of ino #%d with nlink/pino zero\n",
--
fs/jffs2/gc.c-450- inum = ic->ino;
fs/jffs2/gc.c:451: nlink = ic->pino_nlink;
fs/jffs2/gc.c-452- spin_unlock(&c->inocache_lock);
--
fs/jffs2/nodelist.h=158=struct jffs2_inode_cache {
--
fs/jffs2/nodelist.h-178-#endif
fs/jffs2/nodelist.h:179: uint32_t pino_nlink; /* Directories store parent inode
fs/jffs2/nodelist.h-180- here; other inodes store nlink.
--
fs/jffs2/nodemgmt.c=586=void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref)
--
fs/jffs2/nodemgmt.c-832- default:
fs/jffs2/nodemgmt.c:833: if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
fs/jffs2/nodemgmt.c-834- jffs2_del_ino_cache(c, ic);
--
fs/jffs2/readinode.c=1145=static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
--
fs/jffs2/readinode.c-1154- dbg_readinode("ino #%u pino/nlink is %d\n", f->inocache->ino,
fs/jffs2/readinode.c:1155: f->inocache->pino_nlink);
fs/jffs2/readinode.c-1156-
--
fs/jffs2/readinode.c=1328=int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
--
fs/jffs2/readinode.c-1378- memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
fs/jffs2/readinode.c:1379: f->inocache->ino = f->inocache->pino_nlink = 1;
fs/jffs2/readinode.c-1380- f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
--
fs/jffs2/readinode.c=1413=void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
--
fs/jffs2/readinode.c-1419- mutex_lock(&f->sem);
fs/jffs2/readinode.c:1420: deleted = f->inocache && !f->inocache->pino_nlink;
fs/jffs2/readinode.c-1421-
--
fs/jffs2/scan.c=967=struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino)
--
fs/jffs2/scan.c-988- if (ino == 1)
fs/jffs2/scan.c:989: ic->pino_nlink = 1;
fs/jffs2/scan.c-990- return ic;
--
fs/jffs2/super.c=136=static struct dentry *jffs2_get_parent(struct dentry *child)
--
fs/jffs2/super.c-144-
fs/jffs2/super.c:145: pino = f->inocache->pino_nlink;
fs/jffs2/super.c-146-
--
fs/jffs2/wbuf.c=275=static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
--
fs/jffs2/wbuf.c-504- new version instead of the old */
fs/jffs2/wbuf.c:505: f = jffs2_gc_fetch_inode(c, ic->ino, !ic->pino_nlink);
fs/jffs2/wbuf.c-506- if (IS_ERR(f)) {
--
fs/jffs2/write.c=23=int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
--
fs/jffs2/write.c-35- f->inocache = ic;
fs/jffs2/write.c:36: f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
fs/jffs2/write.c-37- f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
--
fs/jffs2/write.c=547=int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
--
fs/jffs2/write.c-655- }
fs/jffs2/write.c:656: dead_f->inocache->pino_nlink = 0;
fs/jffs2/write.c-657- } else
fs/jffs2/write.c:658: dead_f->inocache->pino_nlink--;
fs/jffs2/write.c-659- /* NB: Caller must set inode nlink if appropriate */
--
fs/jffs2/xattr.c=596=void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
--
fs/jffs2/xattr.c-601-
fs/jffs2/xattr.c:602: if (!ic || ic->pino_nlink > 0)
fs/jffs2/xattr.c-603- return;
--
fs/jffs2/xattr.c=775=int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
--
fs/jffs2/xattr.c-844- ic = jffs2_get_ino_cache(c, ref->ino);
fs/jffs2/xattr.c:845: if (!xd || !ic || !ic->pino_nlink) {
fs/jffs2/xattr.c-846- dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
]
|
| 34/2 |
2026/08/09 10:52 |
llm |
expert |
0m
Model:
Tokens:
input: 26994
output: 42
thoughts: 0
|
| 35/2 |
2026/08/09 10:52 |
tool |
git-log |
0m
Args: map[CodeRegexp:BUG\(\) Count:10 PathPrefix:fs/jffs2/gc.c]
Results: map[Output:44b998e1eb25 [JFFS2] Improve failure mode if inode checking leaves unchecked space.
182ec4eee397 [JFFS2] Clean up trailing white spaces
e0c8e42f8f21 [JFFS2] Debug code clean up - step 3
1da177e4c3f4 Linux-2.6.12-rc2
]
|
| 36/2 |
2026/08/09 10:52 |
llm |
expert |
0m
Model:
Tokens:
input: 27148
output: 26
thoughts: 0
|
| 37/2 |
2026/08/09 10:52 |
tool |
git-show |
0m
Args:
Results: map[Output:
Full output is too long, showing 1000 out of 6822520 lines.
[commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2
Author: Linus Torvalds <torvalds@ppc970.osdl.org>
Date: Sat Apr 16 15:20:36 2005 -0700
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
diff --git a/COPYING b/COPYING
new file mode 100644
index 000000000000..2a7e338ec2fc
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,356 @@
+
+ NOTE! This copyright does *not* cover user programs that use kernel
+ services by normal system calls - this is merely considered normal use
+ of the kernel, and does *not* fall under the heading of "derived work".
+ Also note that the GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (the Linux
+ kernel) is copyrighted by me and others who actually wrote it.
+
+ Also note that the only valid version of the GPL as far as the kernel
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+
+ Linus Torvalds
+
+----------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 000000000000..671e9c2d31fe
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,3743 @@
+ This is at least a partial credits-file of people that have
+ contributed to the Linux project. It is sorted by name and
+ formatted to allow easy grepping and beautification by
+ scripts. The fields are: name (N), email (E), web-address
+ (W), PGP key ID and fingerprint (P), description (D), and
+ snail-mail address (S).
+ Thanks,
+
+ Linus
+----------
+
+N: Matti Aarnio
+E: mea@nic.funet.fi
+D: Alpha systems hacking, IPv6 and other network related stuff
+D: One of assisting postmasters for vger.kernel.org's lists
+S: (ask for current address)
+S: Finland
+
+N: Dragos Acostachioaie
+E: dragos@iname.com
+W: http://www.arbornet.org/~dragos
+D: /proc/sysvipc
+S: C. Negri 6, bl. D3
+S: Iasi 6600
+S: Romania
+
+N: Monalisa Agrawal
+E: magrawal@nortelnetworks.com
+D: Basic Interphase 5575 driver with UBR and ABR support.
+S: 75 Donald St, Apt 42
+S: Weymouth, MA 02188
+
+N: Dave Airlie
+E: airlied@linux.ie
+W: http://www.csn.ul.ie/~airlied
+D: NFS over TCP patches
+D: in-kernel DRM Maintainer
+S: Longford, Ireland
+S: Sydney, Australia
+
+N: Tigran A. Aivazian
+E: tigran@veritas.com
+W: http://www.moses.uklinux.net/patches
+D: BFS filesystem
+D: Intel IA32 CPU microcode update support
+D: Various kernel patches
+S: United Kingdom
+
+N: Werner Almesberger
+E: werner@almesberger.net
+W: http://www.almesberger.net/
+D: dosfs, LILO, some fd features, ATM, various other hacks here and there
+S: Buenos Aires
+S: Argentina
+
+N: Tim Alpaerts
+E: tim_alpaerts@toyota-motor-europe.com
+D: 802.2 class II logical link control layer,
+D: the humble start of an opening towards the IBM SNA protocols
+S: Klaproosstraat 72 c 10
+S: B-2610 Wilrijk-Antwerpen
+S: Belgium
+
+N: Anton Altaparmakov
+E: aia21@cantab.net
+W: http://www-stu.christs.cam.ac.uk/~aia21/
+D: Author of new NTFS driver, various other kernel hacks.
+S: Christ's College
+S: Cambridge CB2 3BU
+S: United Kingdom
+
+N: C. Scott Ananian
+E: cananian@alumni.princeton.edu
+W: http://www.pdos.lcs.mit.edu/~cananian
+P: 1024/85AD9EED AD C0 49 08 91 67 DF D7 FA 04 1A EE 09 E8 44 B0
+D: Unix98 pty support.
+D: APM update to 1.2 spec.
+D: /devfs hacking.
+S: 7 Kiwi Loop
+S: Howell, NJ 07731
+S: USA
+
+N: Erik Andersen
+E: andersen@codepoet.org
+W: http://www.codepoet.org/
+P: 1024D/30D39057 1BC4 2742 E885 E4DE 9301 0C82 5F9B 643E 30D3 9057
+D: Maintainer of ide-cd and Uniform CD-ROM driver,
+D: ATAPI CD-Changer support, Major 2.1.x CD-ROM update.
+S: 352 North 525 East
+S: Springville, Utah 84663
+S: USA
+
+N: Michael Ang
+E: mang@subcarrier.org
+W: http://www.subcarrier.org/mang
+D: Linux/PA-RISC hacker
+S: 85 Frank St.
+S: Ottawa, Ontario
+S: Canada K2P 0X3
+
+N: H. Peter Anvin
+E: hpa@zytor.com
+W: http://www.zytor.com/~hpa/
+P: 2047/2A960705 BA 03 D3 2C 14 A8 A8 BD 1E DF FE 69 EE 35 BD 74
+D: Author of the SYSLINUX boot loader, maintainer of the linux.* news
+D: hierarchy and the Linux Device List; various kernel hacks
+S: 4390 Albany Drive #46
+S: San Jose, California 95129
+S: USA
+
+N: Andrea Arcangeli
+E: andrea@suse.de
+W: http://www.kernel.org/pub/linux/kernel/people/andrea/
+P: 1024D/68B9CB43 13D9 8355 295F 4823 7C49 C012 DFA1 686E 68B9 CB43
+P: 1024R/CB4660B9 CC A0 71 81 F4 A0 63 AC C0 4B 81 1D 8C 15 C8 E5
+D: Parport hacker
+D: Implemented a workaround for some interrupt buggy printers
+D: Author of pscan that helps to fix lp/parport bugs
+D: Author of lil (Linux Interrupt Latency benchmark)
+D: Fixed the shm swap deallocation at swapoff time (try_to_unuse message)
+D: VM hacker
+D: Various other kernel hacks
+S: Via Cicalini 26
+S: Imola 40026
+S: Italy
+
+N: Derek Atkins
+E: warlord@MIT.EDU
+D: Linux-AFS Port, random kernel hacker,
+D: VFS fixes (new notify_change in particular)
+D: Moving all VFS access checks into the file systems
+S: MIT Room E15-341
+S: 20 Ames Street
+S: Cambridge, Massachusetts 02139
+S: USA
+
+N: Michel Aubry
+E: giovanni <giovanni@sudfr.com>
+D: Aladdin 1533/1543(C) chipset IDE
+D: VIA MVP-3/TX Pro III chipset IDE
+
+N: Jens Axboe
+E: axboe@suse.de
+D: Linux CD-ROM maintainer, DVD support
+D: elevator + block layer rewrites
+D: highmem I/O support
+D: misc hacking on IDE, SCSI, block drivers, etc
+S: Peter Bangs Vej 258, 2TH
+S: 2500 Valby
+S: Denmark
+
+N: John Aycock
+E: aycock@cpsc.ucalgary.ca
+D: Adaptec 274x driver
+S: Department of Computer Science
+S: University of Calgary
+S: Calgary, Alberta
+S: Canada
+
+N: Miles Bader
+E: miles@gnu.org
+D: v850 port (uClinux)
+S: NEC Corporation
+S: 1753 Shimonumabe, Nakahara-ku
+S: Kawasaki 211-8666
+S: Japan
+
+N: Ralf Baechle
+E: ralf@gnu.org
+P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE C8 BA 9C FC 88 DE 32 C3
+D: Linux/MIPS port
+D: Linux/68k hacker
+S: Hauptstrasse 19
+S: 79837 St. Blasien
+S: Germany
+
+N: Krishna Balasubramanian
+E: balasub@cis.ohio-state.edu
+D: Wrote SYS V IPC (part of standard kernel since 0.99.10)
+
+N: Dario Ballabio
+E: ballabio_dario@emc.com
+E: dario.ballabio@tiscalinet.it
+E: dario.ballabio@inwind.it
+D: Author and maintainer of the Ultrastor 14F/34F SCSI driver
+D: Author and maintainer of the EATA ISA/EISA/PCI SCSI driver
+S: EMC Corporation
+S: Milano
+S: Italy
+
+N: Paul Bame
+E: bame@debian.org
+E: bame@puffin.external.hp.com
+E: paul_bame@hp.com
+W: http://www.parisc-linux.org
+D: PA-RISC 32 and 64-bit early boot, firmware interface, interrupts, misc
+S: MS42
+S: Hewlett-Packard
+S: 3404 E Harmony Rd
+S: Fort Collins, CO 80525
+
+N: Arindam Banerji
+E: axb@cse.nd.edu
+D: Contributed ESDI driver routines needed to port LINUX to the PS/2 MCA.
+S: Department of Computer Science & Eng.
+S: University of Notre Dame
+S: Notre Dame, Indiana
+S: USA
+
+N: Greg Banks
+E: gnb@alphalink.com.au
+D: IDT77105 ATM network driver
+D: some SuperH port work
+D: some trivial futzing with kconfig
+
+N: James Banks
+E: james@sovereign.org
+D: TLAN network driver
+D: Logitech Busmouse driver
+
+N: Krzysztof G. Baranowski
+E: kgb@manjak.knm.org.pl
+P: 1024/FA6F16D1 96 D1 1A CF 5F CA 69 EC F9 4F 36 1F 6D 60 7B DA
+D: Maintainer of the System V file system.
+D: System V fs update for 2.1.x dcache.
+D: Forward ported a couple of SCSI drivers.
+D: Various bugfixes.
+S: ul. Koscielna 12a
+S: 62-300 Wrzesnia
+S: Poland
+
+N: Fred Barnes
+E: frmb2@ukc.ac.uk
+D: Various parport/ppdev hacks and fixes
+S: Computing Lab, The University
+S: Canterbury, KENT
+S: CT2 7NF
+S: England
+
+N: Paul Barton-Davis
+E: pbd@op.net
+D: Driver for WaveFront soundcards (Turtle Beach Maui, Tropez, Tropez+)
+D: Various bugfixes and changes to sound drivers
+S: USA
+
+N: Carlos Henrique Bauer
+E: chbauer@acm.org
+E: bauer@atlas.unisinos.br
+D: Some new sysctl entries for the parport driver.
+D: New sysctl function for handling unsigned longs
+S: Universidade do Vale do Rio dos Sinos - UNISINOS
+S: DSI/IDASI
+S: Av. Unisinos, 950
+S: 93022000 Sao Leopoldo RS
+S: Brazil
+
+N: Peter Bauer
+E: 100136.3530@compuserve.com
+D: Driver for depca-ethernet-board
+S: 69259 Wilhemsfeld
+S: Rainweg 15
+S: Germany
+
+N: Fred Baumgarten
+E: dc6iq@insl1.etec.uni-karlsruhe.de
+E: dc6iq@adacom.org
+E: dc6iq@db0ais.#hes.deu.eu (packet radio)
+D: NET-2 & netstat(8)
+S: Soevener Strasse 11
+S: 53773 Hennef
+S: Germany
+
+N: Donald Becker
+E: becker@cesdis.gsfc.nasa.gov
+D: General low-level networking hacker
+D: Most of the ethercard drivers
+D: Original author of the NFS server
+S: USRA Center of Excellence in Space Data and Information Sciences
+S: Code 930.5, Goddard Space Flight Center
+S: Greenbelt, Maryland 20771
+S: USA
+
+N: Adam Belay
+E: ambx1@neo.rr.com
+D: Linux Plug and Play Support
+S: USA
+
+N: Daniele Bellucci
+E: bellucda@tiscali.it
+D: Various Janitor work.
+W: http://web.tiscali.it/bellucda
+S: Via Delle Palme, 9
+S: Terni 05100
+S: Italy
+
+N: Krzysztof Benedyczak
+E: golbi@mat.uni.torun.pl
+W: http://www.mat.uni.torun.pl/~golbi
+D: POSIX message queues fs (with M. Wronski)
+S: ul. Podmiejska 52
+S: Radunica
+S: 83-000 Pruszcz Gdanski
+S: Poland
+
+N: Randolph Bentson
+E: bentson@grieg.seaslug.org
+W: http://www.aa.net/~bentson/
+P: 1024/39ED5729 5C A8 7A F4 B2 7A D1 3E B5 3B 81 CF 47 30 11 71
+D: Author of driver for Cyclom-Y and Cyclades-Z async mux
+S: 2322 37th Ave SW
+S: Seattle, Washington 98126-2010
+S: USA
+
+N: Stephen R. van den Berg (AKA BuGless)
+E: berg@pool.informatik.rwth-aachen.de
+D: General kernel, gcc, and libc hacker
+D: Specialisation: tweaking, ensuring portability, tweaking, cleaning,
+D: tweaking and occasionally debugging :-)
+S: Bouwensstraat 22
+S: 6369 BG Simpelveld
+S: The Netherlands
+
+N: Peter Berger
+E: pberger@brimson.com
+W: http://www.brimson.com
+D: Author/maintainer of Digi AccelePort USB driver
+S: 1549 Hiironen Rd.
+S: Brimson, MN 55602
+S: USA
+
+N: Hennus Bergman
+P: 1024/77D50909 76 99 FD 31 91 E1 96 1C 90 BB 22 80 62 F6 BD 63
+D: Author and maintainer of the QIC-02 tape driver
+S: The Netherlands
+
+N: Tomas Berndtsson
+E: tomas@nocrew.org
+W: http://tomas.nocrew.org/
+D: dsp56k device driver
+
+N: Ross Biro
+E: bir7@leland.Stanford.Edu
+D: Original author of the Linux networking code
+
+N: Anton Blanchard
+E: anton@samba.org
+W: http://samba.org/~anton/
+P: 1024/8462A731 4C 55 86 34 44 59 A7 99 2B 97 88 4A 88 9A 0D 97
+D: sun4 port, Sparc hacker
+
+N: Hugh Blemings
+E: hugh@misc.nu
+W: http://misc.nu/hugh/
+D: Author and maintainer of the Keyspan USB to Serial drivers
+S: Po Box 234
+S: Belconnen ACT 2616
+S: Australia
+
+N: Philip Blundell
+E: philb@gnu.org
+D: Linux/ARM hacker
+D: Device driver hacker (eexpress, 3c505, c-qcam, ...)
+D: m68k port to HP9000/300
+D: AUN network protocols
+D: Co-architect of the parallel port sharing system
+D: IPv6 netfilter
+S: FutureTV Labs Ltd
+S: Brunswick House, 61-69 Newmarket Rd, Cambridge CB5 8EG
+S: United Kingdom
+
+N: Thomas Bogend�rfer
+E: tsbogend@alpha.franken.de
+D: PCnet32 driver, SONIC driver, JAZZ_ESP driver
+D: newport abscon driver, g364 framebuffer driver
+D: strace for Linux/Alpha
+D: Linux/MIPS hacker
+S: Schafhofstr. 40
+S: 90556 Cadolzburg
+S: Germany
+
+N: Bill Bogstad
+E: bogstad@pobox.com
+D: wrote /proc/self hack, minor samba & dosemu patches
+
+N: Axel Boldt
+E: axel@uni-paderborn.de
+W: http://math-www.uni-paderborn.de/~axel/
+D: Configuration help text support
+D: Linux CD and Support Giveaway List
+
+N: Erik Inge Bols�
+E: knan@mo.himolde.no
+D: Misc kernel hacks
+
+N: Andreas E. Bombe
+E: andreas.bombe@munich.netsurf.de
+W: http://home.pages.de/~andreas.bombe/
+P: 1024/04880A44 72E5 7031 4414 2EB6 F6B4 4CBD 1181 7032 0488 0A44
+D: IEEE 1394 subsystem rewrite and maintainer
+D: Texas Instruments PCILynx IEEE 1394 driver
+
+N: Al Borchers
+E: alborchers@steinerpoint.com
+D: Author/maintainer of Digi AccelePort USB driver
+D: work on usbserial and keyspan_pda drivers
+S: 4912 Zenith Ave. S.
+S: Minneapolis, MN 55410
+S: USA
+
+N: Marc Boucher
+E: marc@mbsi.ca
+P: CA 67 A5 1A 38 CE B6 F2 D5 83 51 03 D2 9C 30 9E CE D2 DD 65
+D: Netfilter core
+D: IP policy routing by mark
+D: Various fixes (mostly networking)
+S: Montreal, Quebec
+S: Canada
+
+N: Zolt�n B�sz�rm�nyi
+E: zboszor@mail.externet.hu
+D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
+
+N: John Boyd
+E: boyd@cis.ohio-state.edu
+D: Co-author of wd7000 SCSI driver
+S: 101 Curl Drive #591
+S: Columbus, Ohio 43210
+S: USA
+
+N: Peter Braam
+E: braam@clusterfs.com
+W: http://www.clusterfs.com/
+D: Coda & InterMezzo filesystems
+S: 181 McNeil
+S: Canmore, AB
+S: Canada, T1W 2R9
+
+N: Ryan Bradetich
+E: rbradetich@uswest.net
+D: Linux/PA-RISC hacker
+S: 1200 Goldenrod Dr.
+S: Nampa, Idaho 83686
+
+N: Derrick J. Brashear
+E: shadow@dementia.org
+W: http://www.dementia.org/~shadow
+P: 512/71EC9367 C5 29 0F BC 83 51 B9 F0 BC 05 89 A0 4F 1F 30 05
+D: Author of Sparc CS4231 audio driver, random Sparc work
+S: 403 Gilmore Avenue
+S: Trafford, Pennsylvania 15085
+S: USA
+
+N: Dag Brattli
+E: dagb@cs.uit.no
+W: http://www.cs.uit.no/~dagb
+D: IrDA Subsystem
+S: 19. Wellington Road
+S: Lancaster, LA1 4DN
+S: UK, England
+
+N: Lars Brinkhoff
+E: lars@nocrew.org
+W: http://lars.nocrew.org/
+D: dsp56k device driver
+D: ptrace proxy in user mode kernel port
+S: Kopmansg 2
+S: 411 13 Goteborg
+S: Sweden
+
+N: Dominik Brodowski
+E: linux@brodo.de
+W: http://www.brodo.de/
+P: 1024D/725B37C6 190F 3E77 9C89 3B6D BECD 46EE 67C3 0308 725B 37C6
+D: parts of CPUFreq code, ACPI bugfixes
+S: Tuebingen, Germany
+
+N: Andries Brouwer
+E: aeb@cwi.nl
+D: random Linux hacker
+S: Bessemerstraat 21
+S: Amsterdam
+S: The Netherlands
+
+N: Zach Brown
+E: zab@zabbo.net
+D: maestro pci sound
+
+N: Gary Brubaker
+E: xavyer@ix.netcom.com
+D: USB Serial Empeg Empeg-car Mark I/II Driver
+
+N: Matthias Bruestle
+E: m@mbsks.franken.de
+D: REINER SCT cyberJack pinpad/e-com USB chipcard reader driver
+S: Germany
+
+N: Adrian Bunk
+E: bunk@stusta.de
+P: 1024D/4F12B400 B29C E71E FE19 6755 5C8A 84D4 99FC EA98 4F12 B400
+D: misc kernel hacking and testing
+S: Grasmeierstrasse 11
+S: 80805 Muenchen
+S: Germany
+
+N: Ray Burr
+E: ryb@nightmare.com
+D: Original author of Amiga FFS filesystem
+S: Orlando, Florida
+S: USA
+
+N: Lennert Buytenhek
+E: buytenh@gnu.org
+D: Rewrite of the ethernet bridging code
+S: Ravenhorst 58B
+S: 2317 AK Leiden
+S: The Netherlands
+
+N: Michael Callahan
+E: callahan@maths.ox.ac.uk
+D: PPP for Linux
+S: The Mathematical Institute
+S: 25-29 St Giles
+S: Oxford
+S: United Kingdom
+
+N: Luiz Fernando N. Capitulino
+E: lcapitulino@terra.com.br
+E: lcapitulino@prefeitura.sp.gov.br
+W: http://www.telecentros.sp.gov.br
+D: Little fixes and a lot of janitorial work
+S: E-GOV Telecentros SP
+S: Brazil
+
+N: Remy Card
+E: Remy.Card@masi.ibp.fr
+E: Remy.Card@linux.org
+D: Extended file system [defunct] designer and developer
+D: Second extended file system designer and developer
+S: Institut Blaise Pascal
+S: 4 Place Jussieu
+S: 75252 Paris Cedex 05
+S: France
+
+N: Ulf Carlsson
+D: SGI Indy audio (HAL2) drivers
+E: ulfc@bun.falkenberg.se
+
+N: Ed Carp
+E: ecarp@netcom.com
+D: uucp, elm, pine, pico port
+D: cron, at(1) developer
+S: 48287 Sawleaf
+S: Fremont, California 94539
+S: USA
+
+N: Florent Chabaud
+E: florent.chabaud@polytechnique.org
+D: software suspend
+S: SGDN/DCSSI/SDS/LTI
+S: 58, Bd Latour-Maubourg
+S: 75700 Paris 07 SP
+S: France
+
+N: Gordon Chaffee
+E: chaffee@cs.berkeley.edu
+W: http://bmrc.berkeley.edu/people/chaffee/
+D: vfat, fat32, joliet, native language support
+S: 3700 Warwick Road
+S: Fremont, California 94555
+S: USA
+
+N: Chih-Jen Chang
+E: chihjenc@scf.usc.edu
+E: chihjen@iis.sinica.edu.tw
+D: IGMP(Internet Group Management Protocol) version 2
+S: 3F, 65 Tajen street
+S: Tamsui town, Taipei county,
+S: Taiwan 251
+S: Republic of China
+
+N: Michael Elizabeth Chastain
+E: mec@shout.net
+D: Configure, Menuconfig, xconfig
+
+N: Raymond Chen
+E: raymondc@microsoft.com
+D: Author of Configure script
+S: 14509 NE 39th Street #1096
+S: Bellevue, Washington 98007
+S: USA
+
+N: Christopher L. Cheney
+E: ccheney@debian.org
+E: ccheney@cheney.cx
+W: http://www.cheney.cx
+P: 1024D/8E384AF2 2D31 1927 87D7 1F24 9FF9 1BC5 D106 5AB3 8E38 4AF2
+D: Vista Imaging usb webcam driver
+S: 314 Prince of Wales
+S: Conroe, TX 77304
+S: USA
+
+N: Stuart Cheshire
+E: cheshire@cs.stanford.edu
+D: Author of Starmode Radio IP (STRIP) driver
+D: Originator of design for new combined interrupt handlers
+S: William Gates Department
+S: Stanford University
+S: Stanford, California 94305
+S: USA
+
+N: Randolph Chung
+E: tausq@debian.org
+D: Linux/PA-RISC hacker
+S: Los Altos, CA 94022
+S: USA
+
+N: Juan Jose Ciarlante
]
]
|
| 38/2 |
2026/08/09 10:52 |
llm |
expert |
0m
Model:
Tokens:
input: 47826
output: 66
thoughts: 546
Thoughts: **My Assessment of the JFFS2 Race Condition Bug**
Okay, so here's what I've got on this JFFS2 bug. It looks like we have a race condition where the garbage collection (GC) thread encounters an inode that's in the process of being evicted (`INO_STATE_CLEARING`). The GC thread doesn't handle this state, and boom, we hit a `BUG()`. This is going to lead to a kernel panic, a straightforward Denial of Service (DoS).
The good news is, from what I can tell, it's *not* exploitable for privilege escalation or any kind of memory corruption. It's just a crash. However, it's definitely accessible to an unprivileged user, provided they have write access to a mounted JFFS2 filesystem. The user can create and delete files which will trigger the inode eviction. Also, if they're operating within a user namespace, and have access to the JFFS2, they can trigger it as well. Furthermore, a VM guest using JFFS2 is also at risk. The host system, network, peripherals, or remote interaction are not involved.
Let's quickly go over the trigger points:
* **Exploitable:** False (thankfully, no memory corruption)
* **DenialOfService:** True (kernel panic)
* **Unprivileged:** True (if filesystem is accessible)
* **UserNamespace:** True (same conditions apply)
* **VMGuestTrigger:** True (if JFFS2 is in use)
* **VMHostTrigger:** False
* **NetworkTrigger:** False
* **RemoteTrigger:** False
* **PeripheralTrigger:** False
* **FilesystemTrigger:** True (A filesystem image is needed for this, it doesn't have to be *malicious*, but it's *definitely* triggered by a filesystem image, which makes this technically a filesystem trigger)
Now, about that "malicious filesystem" question... Since this is a bug *in* JFFS2, a specifically crafted JFFS2 image could absolutely be used to trigger it. You could load a malicious JFFS2 image to exacerbate the race or simply by performing normal operations after it is mounted. So, yes, mounting a malicious JFFS2 image is a definite trigger. This makes the filesystem trigger effectively True.
The `BUG()` call is an explicit kernel panic, and in a production build, that translates to an oops, which, if `panic_on_oops` is set, or if it's happening in a kernel thread, will likely cause a full kernel panic. Even if it doesn't take down the entire system, it kills the garbage collection thread, which eventually cripples the filesystem.
So, in summary: Denial of Service, unprivileged, file system accessible. The user needs to trigger the inode eviction race. This isn't about privilege escalation or memory corruption. It's a DoS, plain and simple. Let's make sure our set-results call reflects that.
|
| 39/2 |
2026/08/09 10:53 |
tool |
set-results |
0m
Args: map[DenialOfService:true Exploitable:false FilesystemTrigger:true NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:true VMGuestTrigger:true VMHostTrigger:false]
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:true NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:true VMGuestTrigger:true VMHostTrigger:false]
|
| 40/2 |
2026/08/09 10:53 |
llm |
expert |
0m
Model:
Tokens:
input: 49155
output: 566
thoughts: 406
Thoughts: **My Analysis of the JFFS2 Garbage Collection Race Condition**
Okay, the results are in, and it's time to craft the final explanation of my analysis.
The core of the problem is a nasty race condition within the JFFS2 filesystem's garbage collection thread. I've narrowed it down: when the Virtual File System (VFS) cache evicts an inode, say, when a file gets deleted and its reference count hits zero, the `jffs2_do_clear_inode` function kicks in. This function helpfully marks the inode's status within the JFFS2 inode cache as `INO_STATE_CLEARING`, setting its state to 6.
Now, here's where the concurrency pain begins. Simultaneously, the JFFS2 garbage collection thread, running `jffs2_garbage_collect_thread`, might start a garbage collection pass (`jffs2_garbage_collect_pass`). This pass, as it iterates through the inode cache hash table, may encounter an inode with the `INO_STATE_CLEARING` flag. And that's where things go sideways – the code hits the `default:` case in a `switch` statement and calls `BUG()`. *That's* the culprit!
The good news, if you can call it that, is that it's a relatively "safe" bug in the sense that the `BUG()` is an explicit instruction that's designed to halt things. There's no sneaky memory corruption or privilege escalation possible; the `BUG()` just translates into an invalid opcode, like `ud2` on x86, which causes a kernel panic or the garbage collection thread to terminate. A Denial of Service, pure and simple.
From a practical standpoint, an unprivileged user can trigger this if they have write access to a mounted JFFS2 filesystem. Repeatedly creating and deleting files is enough to evict inodes, put them into the `INO_STATE_CLEARING` state, and then trigger the race. A malicious JFFS2 filesystem image is also a viable trigger. This makes it a filesystem trigger.
Finally, while this can be triggered from inside a VM guest using JFFS2, it's contained within the guest; the host system is safe. No network access or peripheral devices are involved here.
|
| 41/1 |
2026/08/09 10:53 |
action |
format-explanation |
0m
Results: map[Explanation:**Analysis and Reasoning:**
The bug is a race condition in the JFFS2 filesystem's garbage collection
mechanism.
When a file is deleted and its last reference is closed, the VFS evicts the
inode, which invokes `jffs2_do_clear_inode()`. This function temporarily sets
the inode's state in the JFFS2 inode cache to `INO_STATE_CLEARING` (value 6)
while it cleans up the inode's resources.
Concurrently, the JFFS2 background garbage collection thread (`jffs2_gcd_mtd0`)
periodically runs `jffs2_garbage_collect_pass()`. This function iterates over
the inode cache hash table to find inodes that need to be garbage collected.
When it checks the state of an inode, it uses a `switch(ic->state)` statement.
However, this switch statement does not handle the `INO_STATE_CLEARING` state.
If the garbage collector encounters an inode in this state, it falls through to
the `default:` case, which explicitly calls `BUG()`.
1. **Exploitable:** False. The bug triggers an explicit `BUG()` macro, which on
x86 translates to an invalid opcode (`ud2`). This immediately traps and causes a
kernel oops/panic. There is no memory corruption, out-of-bounds access, or
information leak involved.
2. **Denial of Service:** True. Triggering the `BUG()` will either panic the
entire system or kill the JFFS2 garbage collection kernel thread (which will
eventually render the filesystem unusable and hang tasks). Both scenarios result
in a Denial of Service.
3. **Accessible From Unprivileged Processes / User Namespaces:** True. If a
JFFS2 filesystem is already mounted and an unprivileged user has write access to
any directory within it, they can repeatedly create and delete files. This
forces inode evictions while the background garbage collector is running,
allowing them to win the race condition and crash the system.
4. **Malicious Filesystem Trigger:** True. An attacker could provide a specially
crafted JFFS2 image designed to maximize the race window (e.g., by containing a
massive number of inodes) to reliably trigger the crash upon mounting and
interacting with it.
5. **VM Guest Trigger:** True. A VM guest utilizing a JFFS2 filesystem can
trigger this bug within its own kernel.
6. **Other Triggers:** False. The bug is strictly isolated to the JFFS2
filesystem's internal garbage collection and inode eviction paths. It cannot be
triggered via network packets, remote protocols, or peripheral devices (unless a
peripheral contains a JFFS2 image that gets mounted).]
|