| 0/0 |
2026/05/16 03:53 |
flow |
assessment-security |
42m
Results: map[DenialOfService:false Explanation:Based on the analysis of the provided KCSAN (Kernel Concurrency Sanitizer) bug
report and the kernel source code, here is the assessment of the bug:
### Bug Mechanism
The report highlights a data race on `dentry->d_flags` between a writer in
`d_make_discardable()` and a lockless reader in `d_managed()` (called during RCU
path walk via `step_into_slowpath()`).
1. **The Writer:** `d_make_discardable()` is called during the unlinking of a
file (e.g., in `shmem_unlink`). It modifies `dentry->d_flags` by clearing the
`DCACHE_PERSISTENT` bit (`BIT(27)`). Shortly after, `finish_dput()` is called,
which further modifies `d_flags` by setting `DCACHE_DENTRY_KILLED` (`BIT(14)`)
and clearing LRU/shrink list bits. These modifications are done while holding
the `dentry->d_lock`.
2. **The Reader:** `d_managed()` is called during a lockless RCU path walk. It
reads `dentry->d_flags` without holding the `d_lock` to check if any of the
`DCACHE_MANAGED_DENTRY` bits are set. `DCACHE_MANAGED_DENTRY` is defined as
`(DCACHE_MOUNTED | DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT)`, which
corresponds to `BIT(15)`, `BIT(16)`, and `BIT(17)`.
### Security Impact
**Not Exploitable & No Denial of Service:**
This is a classic, completely benign data race in the VFS subsystem.
- The bits being modified by the writer (`BIT(27)`, `BIT(14)`, etc.) are
strictly disjoint from the bits being checked by the reader (`BIT(15)`,
`BIT(16)`, `BIT(17)`).
- On all architectures supported by Linux, aligned 32-bit reads and writes are
atomic at the hardware level. The reader will never see a "torn" or corrupted
value that mixes up the bits.
- Regardless of whether `d_managed()` reads the `d_flags` just before or just
after the writer modifies the unrelated bits, the result of the bitwise AND
operation (`dentry->d_flags & DCACHE_MANAGED_DENTRY`) will remain perfectly
accurate.
- The VFS heavily relies on such lockless checks for performance during RCU path
walks. While it is technically undefined behavior in standard C (hence the KCSAN
report), it is practically safe and does not lead to memory corruption, crashes,
or incorrect control flow. Production kernels do not enable KCSAN, so this will
not even trigger a warning or panic in real-world environments.
### Reachability
- **Accessible From Unprivileged Processes / User Namespaces / VM Guests:** Yes.
Any unprivileged local user can easily trigger this race by having one thread
continuously unlink files (e.g., in a `tmpfs` or `shmem` mount) while another
thread concurrently performs path lookups (`readlink`, `open`, `stat`, etc.) on
the same paths.
- **Remote / Peripheral / Filesystem Trigger:** No. This is tied to local
syscall execution (`unlink` and `readlink`). Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:true VMGuestTrigger:true VMHostTrigger:false]
|
| 1/1 |
2026/05/16 03:53 |
action |
syz-repro-to-c-repro |
0m
Results:
|
| 2/1 |
2026/05/16 03:53 |
action |
kernel-checkouter |
1m
Results: map[KernelSrc:/app/workdir/cache/src/544276298cf27c4e033fe49d3c5d66a675e4b606]
|
| 3/1 |
2026/05/16 03:55 |
action |
kernel-builder |
18m
Results: map[KernelObj:/app/workdir/cache/build/f0a48793948b0a1ec12b4206a970ae253afe7f0b]
|
| 4/1 |
2026/05/16 04:14 |
action |
codesearch-prepare |
19m
Results: map[Index:codesearch-index]
|
| 5/1 |
2026/05/16 04:34 |
agent |
expert |
2m
Model:
Results: map[DenialOfService:false Exploitable:false FilesystemTrigger:false 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 greeping
".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).
Don't make assumptions; verify them with source code access. 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 or elevated privileges.
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 completly 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 tranfers, that's 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 exploitabability depends on how exactly the uninit value
is used in the code, and what it affects.
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 Confidetial 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.
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:
==================================================================
BUG: KCSAN: data-race in d_make_discardable / step_into_slowpath
write to 0xffff88810d046840 of 4 bytes by task 3286 on cpu 1:
d_make_discardable+0x4f/0xa0 fs/dcache.c:984
simple_unlink+0x68/0x80 fs/libfs.c:808
shmem_unlink+0x12d/0x140 mm/shmem.c:3981
vfs_unlink+0x1c7/0x490 fs/namei.c:5498
filename_unlinkat+0x1e2/0x410 fs/namei.c:5568
__do_sys_unlink fs/namei.c:5603 [inline]
__se_sys_unlink+0x2b/0xe0 fs/namei.c:5600
__x64_sys_unlink+0x1f/0x30 fs/namei.c:5600
x64_sys_call+0x2eb6/0x3020 arch/x86/include/generated/asm/syscalls_64.h:88
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x12c/0x3b0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
read to 0xffff88810d046840 of 4 bytes by task 2980 on cpu 0:
d_managed include/linux/dcache.h:416 [inline]
handle_mounts fs/namei.c:1733 [inline]
step_into_slowpath+0xea/0x4c0 fs/namei.c:2100
step_into fs/namei.c:2148 [inline]
walk_component fs/namei.c:2284 [inline]
lookup_last fs/namei.c:2785 [inline]
path_lookupat+0x330/0x500 fs/namei.c:2809
filename_lookup+0x190/0x390 fs/namei.c:2838
do_readlinkat+0x74/0x2f0 fs/stat.c:571
__do_sys_readlink fs/stat.c:605 [inline]
__se_sys_readlink fs/stat.c:602 [inline]
__x64_sys_readlink+0x47/0x60 fs/stat.c:602
x64_sys_call+0x2b51/0x3020 arch/x86/include/generated/asm/syscalls_64.h:90
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x12c/0x3b0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
value changed: 0x08300080 -> 0x00004080
Reported by Kernel Concurrency Sanitizer on:
CPU: 0 UID: 0 PID: 2980 Comm: udevd Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
==================================================================
Reply: Based on the analysis of the provided KCSAN (Kernel Concurrency Sanitizer) bug report and the kernel source code, here is the assessment of the bug:
### Bug Mechanism
The report highlights a data race on `dentry->d_flags` between a writer in `d_make_discardable()` and a lockless reader in `d_managed()` (called during RCU path walk via `step_into_slowpath()`).
1. **The Writer:** `d_make_discardable()` is called during the unlinking of a file (e.g., in `shmem_unlink`). It modifies `dentry->d_flags` by clearing the `DCACHE_PERSISTENT` bit (`BIT(27)`). Shortly after, `finish_dput()` is called, which further modifies `d_flags` by setting `DCACHE_DENTRY_KILLED` (`BIT(14)`) and clearing LRU/shrink list bits. These modifications are done while holding the `dentry->d_lock`.
2. **The Reader:** `d_managed()` is called during a lockless RCU path walk. It reads `dentry->d_flags` without holding the `d_lock` to check if any of the `DCACHE_MANAGED_DENTRY` bits are set. `DCACHE_MANAGED_DENTRY` is defined as `(DCACHE_MOUNTED | DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT)`, which corresponds to `BIT(15)`, `BIT(16)`, and `BIT(17)`.
### Security Impact
**Not Exploitable & No Denial of Service:**
This is a classic, completely benign data race in the VFS subsystem.
- The bits being modified by the writer (`BIT(27)`, `BIT(14)`, etc.) are strictly disjoint from the bits being checked by the reader (`BIT(15)`, `BIT(16)`, `BIT(17)`).
- On all architectures supported by Linux, aligned 32-bit reads and writes are atomic at the hardware level. The reader will never see a "torn" or corrupted value that mixes up the bits.
- Regardless of whether `d_managed()` reads the `d_flags` just before or just after the writer modifies the unrelated bits, the result of the bitwise AND operation (`dentry->d_flags & DCACHE_MANAGED_DENTRY`) will remain perfectly accurate.
- The VFS heavily relies on such lockless checks for performance during RCU path walks. While it is technically undefined behavior in standard C (hence the KCSAN report), it is practically safe and does not lead to memory corruption, crashes, or incorrect control flow. Production kernels do not enable KCSAN, so this will not even trigger a warning or panic in real-world environments.
### Reachability
- **Accessible From Unprivileged Processes / User Namespaces / VM Guests:** Yes. Any unprivileged local user can easily trigger this race by having one thread continuously unlink files (e.g., in a `tmpfs` or `shmem` mount) while another thread concurrently performs path lookups (`readlink`, `open`, `stat`, etc.) on the same paths.
- **Remote / Peripheral / Filesystem Trigger:** No. This is tied to local syscall execution (`unlink` and `readlink`).
|
| 6/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 5327
output: 122
thoughts: 113
Thoughts: **Analyzing a KCSAN Data-Race Report**
Okay, so I've got this KCSAN data-race report flagging a potential issue. The core of it seems to be centered around `d_make_discardable` and `step_into_slowpath`. The report pinpoints the write in `d_make_discardable`, specifically line 984 within `fs/dcache.c`. Then, the corresponding read is occurring within `d_managed`, which is defined in `include/linux/dcache.h` at line 416. This `d_managed` call is originating from `step_into_slowpath` at line 2100 in `fs/namei.c`.
My immediate next step is to dive into the source code for each of those functions, to understand the interactions. I'll need to examine the context of that write in `d_make_discardable` and determine exactly what data is being modified, paying close attention to any synchronization primitives. Simultaneously, I'll scrutinize how `d_managed` is being used within `step_into_slowpath`, focusing on the access patterns and any potential race conditions involving the same data written by `d_make_discardable`. This is probably something related to dcache management, and I need to figure out the implications.
|
| 7/2 |
2026/05/16 04:34 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/dcache.c IncludeLines:true Name:d_make_discardable]
Results: map[SourceCode: 980: void d_make_discardable(struct dentry *dentry)
981: {
982: spin_lock(&dentry->d_lock);
983: WARN_ON(!(dentry->d_flags & DCACHE_PERSISTENT));
984: dentry->d_flags &= ~DCACHE_PERSISTENT;
985: dentry->d_lockref.count--;
986: rcu_read_lock();
987: finish_dput(dentry);
988: }
SourceFile:fs/dcache.c]
|
| 8/2 |
2026/05/16 04:34 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/namei.c IncludeLines:true Name:step_into_slowpath]
Results: map[SourceCode:2085: /*
2086: * Do we need to follow links? We _really_ want to be able
2087: * to do this check without having to look at inode->i_op,
2088: * so we keep a cache of "no, this doesn't need follow_link"
2089: * for the common case.
2090: *
2091: * NOTE: dentry must be what nd->next_seq had been sampled from.
2092: */
2093: static noinline const char *step_into_slowpath(struct nameidata *nd, int flags,
2094: struct dentry *dentry)
2095: {
2096: struct path path;
2097: struct inode *inode;
2098: int err;
2099:
2100: err = handle_mounts(nd, dentry, &path);
2101: if (unlikely(err < 0))
2102: return ERR_PTR(err);
2103: inode = path.dentry->d_inode;
2104: if (likely(!d_is_symlink(path.dentry)) ||
2105: ((flags & WALK_TRAILING) && !(nd->flags & LOOKUP_FOLLOW)) ||
2106: (flags & WALK_NOFOLLOW)) {
2107: /* not a symlink or should not follow */
2108: if (nd->flags & LOOKUP_RCU) {
2109: if (read_seqcount_retry(&path.dentry->d_seq, nd->next_seq))
2110: return ERR_PTR(-ECHILD);
2111: if (unlikely(!inode))
2112: return ERR_PTR(-ENOENT);
2113: } else {
2114: dput(nd->path.dentry);
2115: if (nd->path.mnt != path.mnt)
2116: mntput(nd->path.mnt);
2117: }
2118: nd->path = path;
2119: nd->inode = inode;
2120: nd->seq = nd->next_seq;
2121: return NULL;
2122: }
2123: return pick_link(nd, &path, inode, flags);
2124: }
SourceFile:fs/namei.c]
|
| 9/2 |
2026/05/16 04:34 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:include/linux/dcache.h IncludeLines:true Name:d_managed]
Results: map[SourceCode: 414: static inline bool d_managed(const struct dentry *dentry)
415: {
416: return dentry->d_flags & DCACHE_MANAGED_DENTRY;
417: }
SourceFile:include/linux/dcache.h]
|
| 10/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 6780
output: 39
thoughts: 84
Thoughts: **Analyzing Dentry Flags in the Filesystem Cache**
Okay, so I'm looking at this code and trying to understand how the filesystem cache is behaving with these dentries. Specifically, the write operation is setting `dentry->d_flags &= ~DCACHE_PERSISTENT;` within the `d_make_discardable` function. I recognize that as a clear instruction to remove the `DCACHE_PERSISTENT` flag from the dentry's flag field. The opposite check, the read operation, happens when `dentry->d_flags & DCACHE_MANAGED_DENTRY;` is evaluated in the `d_managed` function. This makes me consider what conditions cause that evaluation, and why. I know `DCACHE_MANAGED_DENTRY` is a bitmask, which is standard practice in these types of flag implementations, so I need to understand what it means for it to be set or not. I'll need to examine the other flags as well. I'm going to quickly check how `handle_mounts` interacts with this; I suspect it could be relevant to the persistence or management states. I think it is important to figure out when these flags are modified, as that's often when a dentry goes into the persistent or discardable state.
|
| 11/2 |
2026/05/16 04:34 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/namei.c IncludeLines:true Name:handle_mounts]
Results: map[SourceCode:1723: static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
1724: struct path *path)
1725: {
1726: bool jumped;
1727: int ret;
1728:
1729: path->mnt = nd->path.mnt;
1730: path->dentry = dentry;
1731: if (nd->flags & LOOKUP_RCU) {
1732: unsigned int seq = nd->next_seq;
1733: if (likely(!d_managed(dentry)))
1734: return 0;
1735: if (likely(__follow_mount_rcu(nd, path)))
1736: return 0;
1737: // *path and nd->next_seq might've been clobbered
1738: path->mnt = nd->path.mnt;
1739: path->dentry = dentry;
1740: nd->next_seq = seq;
1741: if (unlikely(!try_to_unlazy_next(nd, dentry)))
1742: return -ECHILD;
1743: }
1744: ret = traverse_mounts(path, &jumped, &nd->total_link_count, nd->flags);
1745: if (jumped)
1746: nd->state |= ND_JUMPED;
1747: if (unlikely(ret)) {
1748: dput(path->dentry);
1749: if (path->mnt != nd->path.mnt)
1750: mntput(path->mnt);
1751: }
1752: return ret;
1753: }
SourceFile:fs/namei.c]
|
| 12/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 7679
output: 24
thoughts: 171
Thoughts: **Analyzing a Potential Data Race in the Dentry Management Code**
Okay, let's break this down. I'm looking at the `d_managed(dentry)` function – and it's reading the `dentry->d_flags` field without any locking mechanism in place. Interesting. Now, over in `d_make_discardable`, we're definitely modifying `dentry->d_flags`, but we *are* holding a `spin_lock` on `dentry->d_lock` there. The concern is that `d_managed` is being called within an RCU lookup context, specifically `LOOKUP_RCU`. And, as everyone knows, the whole point of RCU is to *avoid* holding those `d_lock` locks during lookup. So, the read of `dentry->d_flags` in `d_managed` is essentially running concurrently with a write to the same field in `d_make_discardable`. It's a classic data race scenario.
The crucial question is, is this data race truly a problem? Let's analyze. `d_make_discardable` is clearing the `DCACHE_PERSISTENT` flag. That's a good starting point. Now, `DCACHE_MANAGED_DENTRY` is a bit field; We need to figure out what bits are being set and cleared here to understand the implications of the potential race. My gut feeling is that it's probably benign since `dentry` structures are almost always read more often than written to, and the bits may only be set once. But let's dig into that bitmask definition.
|
| 13/2 |
2026/05/16 04:34 |
tool |
grepper |
0m
Args: map[Expression:#define DCACHE_MANAGED_DENTRY]
Results: map[Output:include/linux/dcache.h=192=enum dentry_flags {
--
include/linux/dcache.h-241-
include/linux/dcache.h:242:#define DCACHE_MANAGED_DENTRY \
include/linux/dcache.h-243- (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
]
|
| 14/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 8336
output: 20
thoughts: 34
Thoughts: Okay, here's my interpretation of those thoughts, presented as a personal thought process, as requested:
**Navigating the Dentry Landscape**
Hmm, interesting. I'm noting that the `DCACHE_MANAGED_DENTRY` flag, which is relevant in this context, *doesn't* automatically imply the `DCACHE_PERSISTENT` flag. That's a key distinction I need to keep in mind. The relationship between these two, or lack thereof, is something I should understand well. I need to be absolutely clear on what implications it has. I should refresh my memory on the specifics of how `DCACHE_PERSISTENT` behaves and what it truly signifies in our implementation. It's time to dig into the definition of `DCACHE_PERSISTENT` and its associated behaviors; I need a firm grasp on the underlying mechanisms to make sure I understand the interaction.
|
| 15/2 |
2026/05/16 04:34 |
tool |
grepper |
0m
Args: map[Expression:DCACHE_PERSISTENT]
Results: map[Output:Documentation/filesystems/porting.rst=1326=end_creating() and the parent will be unlocked precisely when necessary.
--
Documentation/filesystems/porting.rst-1331-
Documentation/filesystems/porting.rst:1332:kill_litter_super() is gone; convert to DCACHE_PERSISTENT use (as all
Documentation/filesystems/porting.rst-1333-in-tree filesystems have done).
--
fs/dcache.c=980=void d_make_discardable(struct dentry *dentry)
--
fs/dcache.c-982- spin_lock(&dentry->d_lock);
fs/dcache.c:983: WARN_ON(!(dentry->d_flags & DCACHE_PERSISTENT));
fs/dcache.c:984: dentry->d_flags &= ~DCACHE_PERSISTENT;
fs/dcache.c-985- dentry->d_lockref.count--;
--
fs/dcache.c=1596=static enum d_walk_ret select_collect_umount(void *_data, struct dentry *dentry)
fs/dcache.c-1597-{
fs/dcache.c:1598: if (dentry->d_flags & DCACHE_PERSISTENT) {
fs/dcache.c:1599: dentry->d_flags &= ~DCACHE_PERSISTENT;
fs/dcache.c-1600- dentry->d_lockref.count--;
--
fs/dcache.c=2863=struct dentry *d_make_persistent(struct dentry *dentry, struct inode *inode)
--
fs/dcache.c-2870- __d_instantiate(dentry, inode);
fs/dcache.c:2871: dentry->d_flags |= DCACHE_PERSISTENT;
fs/dcache.c-2872- dget_dlock(dentry);
--
include/linux/dcache.h=192=enum dentry_flags {
--
include/linux/dcache.h-238- DCACHE_NORCU = BIT(26), /* No RCU delay for freeing */
include/linux/dcache.h:239: DCACHE_PERSISTENT = BIT(27)
include/linux/dcache.h-240-};
]
|
| 16/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 9193
output: 20
thoughts: 65
Thoughts: **Analyzing DCACHE Flags**
Okay, let's break down these `DCACHE` definitions. First, I see that `DCACHE_PERSISTENT` is defined as `BIT(27)`. Simple enough, that's just a specific bit position we're using to represent persistence in the dentry cache. Now, the more interesting one: `DCACHE_MANAGED_DENTRY` is a combination. It's built up from `DCACHE_MOUNTED`, `DCACHE_NEED_AUTOMOUNT`, and `DCACHE_MANAGE_TRANSIT`. I'll need to remember this composite definition. I'll need to consider how these individual flags contribute to the overall behavior of a "managed" dentry. What implications does this combination have for the dentry's lifecycle, mount points, and how transitions between states are managed? I need to understand this to understand the impact in relation to my expert knowledge.
|
| 17/2 |
2026/05/16 04:34 |
tool |
grepper |
0m
Args: map[Expression:DCACHE_MOUNTED]
Results: map[Output:Documentation/filesystems/path-lookup.rst=558=filesystem, which will then give it a special pass through
--
Documentation/filesystems/path-lookup.rst-560-
Documentation/filesystems/path-lookup.rst:561:``DCACHE_MOUNTED``
Documentation/filesystems/path-lookup.rst-562-~~~~~~~~~~~~~~~~~~
--
fs/dcache.c=1517=int d_set_mounted(struct dentry *dentry)
--
fs/dcache.c-1534- if (!d_mountpoint(dentry)) {
fs/dcache.c:1535: dentry->d_flags |= DCACHE_MOUNTED;
fs/dcache.c-1536- ret = 0;
--
fs/namei.c=1569=static int __traverse_mounts(struct path *path, unsigned flags, bool *jumped,
--
fs/namei.c-1589-
fs/namei.c:1590: if (flags & DCACHE_MOUNTED) { // something's mounted on it..
fs/namei.c-1591- struct vfsmount *mounted = lookup_mnt(path);
--
fs/namei.c=1682=static bool __follow_mount_rcu(struct nameidata *nd, struct path *path)
--
fs/namei.c-1701-
fs/namei.c:1702: if (flags & DCACHE_MOUNTED) {
fs/namei.c-1703- struct mount *mounted = __lookup_mnt(path->mnt, dentry);
--
fs/namespace.c=922=static void maybe_free_mountpoint(struct mountpoint *mp, struct list_head *list)
--
fs/namespace.c-926- spin_lock(&dentry->d_lock);
fs/namespace.c:927: dentry->d_flags &= ~DCACHE_MOUNTED;
fs/namespace.c-928- spin_unlock(&dentry->d_lock);
--
include/linux/dcache.h=192=enum dentry_flags {
--
include/linux/dcache.h-221- DCACHE_DENTRY_KILLED = BIT(14),
include/linux/dcache.h:222: DCACHE_MOUNTED = BIT(15), /* is a mountpoint */
include/linux/dcache.h-223- DCACHE_NEED_AUTOMOUNT = BIT(16), /* handle automount on this dir */
--
include/linux/dcache.h-242-#define DCACHE_MANAGED_DENTRY \
include/linux/dcache.h:243: (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
include/linux/dcache.h-244-
--
include/linux/dcache.h=419=static inline bool d_mountpoint(const struct dentry *dentry)
include/linux/dcache.h-420-{
include/linux/dcache.h:421: return dentry->d_flags & DCACHE_MOUNTED;
include/linux/dcache.h-422-}
]
|
| 18/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 10310
output: 22
thoughts: 1007
Thoughts: **Benign Data Race in the Dentry Flag Management**
Okay, so I'm looking at this KCSAN report, and it seems like we have a potential data race involving `dentry->d_flags`. My initial thought is that `d_managed` is reading `dentry->d_flags` to check for flags like `DCACHE_MOUNTED`, and `d_make_discardable` is clearing `DCACHE_PERSISTENT`. Since these are bitfields within a single `unsigned int`, clearing a bit means a read-modify-write operation. The race comes in if `d_managed` reads this flag concurrently while the write is happening.
The thing is, `DCACHE_PERSISTENT` is irrelevant to what `d_managed` checks, so whether it reads the old or the new value of the bit, it doesn't matter. Now, I do remember from C, data races are undefined behavior in C! But in the kernel, a simple integer read/write generally translates into a single load/store, right? But wait, the bitwise operation `&= ~DCACHE_PERSISTENT;` is a read-modify-write, so could it tear? No, not on a 32-bit integer.
I'm starting to think this could be a compiler optimization issue. However, the read in `d_managed` is a straightforward `return dentry->d_flags & DCACHE_MANAGED_DENTRY;`. This smells like a classic, benign data race, you know, the ones we see all over the VFS. The reader doesn't care about the modified bit, and the writer is protected by a lock (`d_lock`), and so there are no concurrent writers without a lock. Okay, so `d_flags` is modified under `d_lock`! That protects concurrent writers. The reader `d_managed` doesn't hold `d_lock` though, so it can race with the writers.
This feels like the RCU path walk pattern. The solution is either using `READ_ONCE` and `WRITE_ONCE` or simply ignoring it. Given this is a KCSAN report, it's just a data race detection, and it's not exploitable. Is this a denial of service? Nah. Can a regular user trigger this? Yes, `unlink` and `readlink` can.
Now, I'm trying to figure out if it could be *harmful* in some unexpected way. If a torn read occurs, could it read garbage? But on x86, 32-bit aligned reads and writes are atomic! The write is a single instruction, even if not locked. The read is also a single instruction, so this can't result in a corrupted value. Since `DCACHE_PERSISTENT` is not part of `DCACHE_MANAGED_DENTRY`, the result is the same whether it reads the old or new value. Completely benign.
Let me double-check. The bug report shows a value changing from `0x08300080` to `0x00004080`. Let's see... that looks like `BIT(27)`, `BIT(21)`, `BIT(20)`, and `BIT(7)` changing to `BIT(14)` and `BIT(7)`. `BIT(27)` is `DCACHE_PERSISTENT`. `BIT(21)` is `DCACHE_LRU_LIST`. `BIT(20)` is `DCACHE_SHRINK_LIST`. `BIT(14)` is `DCACHE_DENTRY_KILLED`. `BIT(7)` is likely `DCACHE_OP_REVALIDATE`. So, yeah, this confirms it, the race is between clearing `DCACHE_PERSISTENT` and some concurrent read. It’s still benign.
|
| 19/2 |
2026/05/16 04:34 |
tool |
grepper |
0m
Args: map[Expression:DCACHE_OP_REVALIDATE]
Results: map[Output:Documentation/filesystems/path-lookup.rst=139=awkward races. The VFS can detect these filesystems by the
Documentation/filesystems/path-lookup.rst:140:``DCACHE_OP_REVALIDATE`` flag being set in the dentry.
Documentation/filesystems/path-lookup.rst-141-
--
fs/dcache.c=1956=EXPORT_SYMBOL(d_alloc_name);
--
fs/dcache.c-1958-#define DCACHE_OP_FLAGS \
fs/dcache.c:1959: (DCACHE_OP_HASH | DCACHE_OP_COMPARE | DCACHE_OP_REVALIDATE | \
fs/dcache.c-1960- DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_DELETE | DCACHE_OP_PRUNE | \
--
fs/dcache.c=1963=static unsigned int d_op_flags(const struct dentry_operations *op)
--
fs/dcache.c-1971- if (op->d_revalidate)
fs/dcache.c:1972: flags |= DCACHE_OP_REVALIDATE;
fs/dcache.c-1973- if (op->d_weak_revalidate)
--
fs/ecryptfs/dentry.c=33=static int ecryptfs_d_revalidate(struct inode *dir, const struct qstr *name,
--
fs/ecryptfs/dentry.c-41-
fs/ecryptfs/dentry.c:42: if (lower_dentry->d_flags & DCACHE_OP_REVALIDATE) {
fs/ecryptfs/dentry.c-43- struct inode *lower_dir = ecryptfs_inode_to_lower(dir);
--
fs/namei.c=1026=static inline int d_revalidate(struct inode *dir, const struct qstr *name,
--
fs/namei.c-1028-{
fs/namei.c:1029: if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE))
fs/namei.c-1030- return dentry->d_op->d_revalidate(dir, name, dentry, flags);
--
fs/overlayfs/super.c=83=static int ovl_revalidate_real(struct dentry *d, unsigned int flags, bool weak)
--
fs/overlayfs/super.c-92- ret = d->d_op->d_weak_revalidate(d, flags);
fs/overlayfs/super.c:93: } else if (d->d_flags & DCACHE_OP_REVALIDATE) {
fs/overlayfs/super.c-94- struct dentry *parent;
--
fs/overlayfs/util.c=156=void ovl_free_entry(struct ovl_entry *oe)
--
fs/overlayfs/util.c-161-
fs/overlayfs/util.c:162:#define OVL_D_REVALIDATE (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)
fs/overlayfs/util.c-163-
--
include/linux/dcache.h=192=enum dentry_flags {
--
include/linux/dcache.h-194- DCACHE_OP_COMPARE = BIT(1),
include/linux/dcache.h:195: DCACHE_OP_REVALIDATE = BIT(2),
include/linux/dcache.h-196- DCACHE_OP_DELETE = BIT(3),
--
include/linux/fscrypt.h=268=static inline void fscrypt_handle_d_move(struct dentry *dentry)
--
include/linux/fscrypt.h-281- if (dentry->d_op->d_revalidate == fscrypt_d_revalidate)
include/linux/fscrypt.h:282: dentry->d_flags &= ~DCACHE_OP_REVALIDATE;
include/linux/fscrypt.h-283- }
--
include/linux/fscrypt.h=315=static inline void fscrypt_prepare_dentry(struct dentry *dentry,
--
include/linux/fscrypt.h-320- * to ->d_flags. We shouldn't be peeking on d_flags for
include/linux/fscrypt.h:321: * DCACHE_OP_REVALIDATE unlocked, but in the unlikely case
include/linux/fscrypt.h-322- * there is a race, the worst it can happen is that we fail to
include/linux/fscrypt.h:323: * unset DCACHE_OP_REVALIDATE and pay the cost of an extra
include/linux/fscrypt.h-324- * d_revalidate.
--
include/linux/fscrypt.h-329- spin_unlock(&dentry->d_lock);
include/linux/fscrypt.h:330: } else if (dentry->d_flags & DCACHE_OP_REVALIDATE &&
include/linux/fscrypt.h-331- dentry->d_op->d_revalidate == fscrypt_d_revalidate) {
--
include/linux/fscrypt.h-338- spin_lock(&dentry->d_lock);
include/linux/fscrypt.h:339: dentry->d_flags &= ~DCACHE_OP_REVALIDATE;
include/linux/fscrypt.h-340- spin_unlock(&dentry->d_lock);
]
|
| 20/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 13611
output: 18
thoughts: 59
Thoughts: **Debugging a Cache Operation**
Okay, hold on a second. I thought `BIT(7)` was assigned to `DCACHE_OP_REVALIDATE`, but something feels off. No, that can't be right; `BIT(2)` *should* be the revalidate operation. This discrepancy is throwing a wrench in my mental model of the dcache operations. I need to make absolutely sure. Let me quickly double-check the authoritative source. I'll open up `include/linux/dcache.h` right now to verify what `BIT(7)` actually represents, just to make certain I'm not missing something subtle. I need the definitive answer before I move forward.
|
| 21/2 |
2026/05/16 04:34 |
tool |
grepper |
0m
Args:
Results: map[Output:
Full output is too long, showing 500 out of 28781 lines.
Use more precise expression if possible.
[Documentation/ABI/testing/sysfs-devices-platform-ACPI-TAD=6=Description:
--
Documentation/ABI/testing/sysfs-devices-platform-ACPI-TAD-17- BIT(6): The AC timer wakes up from S5 if set
Documentation/ABI/testing/sysfs-devices-platform-ACPI-TAD:18: BIT(7): The DC timer wakes up from S4 if set
Documentation/ABI/testing/sysfs-devices-platform-ACPI-TAD-19- BIT(8): The DC timer wakes up from S5 if set
--
Documentation/ABI/testing/sysfs-driver-zynqmp-fpga=5=Description: (RO) Read fpga status.
--
Documentation/ABI/testing/sysfs-driver-zynqmp-fpga-32-
Documentation/ABI/testing/sysfs-driver-zynqmp-fpga:33: BIT(7) 0: GHIGH_B_STATUS asserted
Documentation/ABI/testing/sysfs-driver-zynqmp-fpga-34- 1: GHIGH_B_STATUS deasserted
--
Documentation/hwmon/pmbus-core.rst=301=currently provides a flags field with four bits used::
--
Documentation/hwmon/pmbus-core.rst-316-
Documentation/hwmon/pmbus-core.rst:317: #define PMBUS_VOUT_PROTECTED BIT(7)
Documentation/hwmon/pmbus-core.rst-318-
--
arch/alpha/include/asm/bitops.h=289=static inline bool xor_unlock_is_negative_byte(unsigned long mask,
--
arch/alpha/include/asm/bitops.h-305-
arch/alpha/include/asm/bitops.h:306: return (old & BIT(7)) != 0;
arch/alpha/include/asm/bitops.h-307-}
--
arch/arm/boot/dts/ti/omap/omap3-beagle-xm.dts=325=&twl_gpio {
--
arch/arm/boot/dts/ti/omap/omap3-beagle-xm.dts-330- * pulldowns:
arch/arm/boot/dts/ti/omap/omap3-beagle-xm.dts:331: * BIT(2), BIT(6), BIT(7), BIT(8), BIT(13)
arch/arm/boot/dts/ti/omap/omap3-beagle-xm.dts-332- * BIT(15), BIT(16), BIT(17)
--
arch/arm/boot/dts/ti/omap/omap3-beagle.dts=307=&twl_gpio {
--
arch/arm/boot/dts/ti/omap/omap3-beagle.dts-312- * pulldowns:
arch/arm/boot/dts/ti/omap/omap3-beagle.dts:313: * BIT(2), BIT(6), BIT(7), BIT(8), BIT(13)
arch/arm/boot/dts/ti/omap/omap3-beagle.dts-314- * BIT(15), BIT(16), BIT(17)
--
arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi=179=&twl_gpio {
--
arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi-182- * pulldowns:
arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi:183: * BIT(1), BIT(2), BIT(6), BIT(7), BIT(8), BIT(13)
arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi-184- * BIT(15), BIT(16), BIT(17)
--
arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi=681=&twl_gpio {
--
arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi-685- * pulldowns:
arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi:686: * BIT(0), BIT(1), BIT(6), BIT(7), BIT(8), BIT(13)
arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi-687- * BIT(15), BIT(16), BIT(17)
arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi-688- */
arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi:689: ti,pulldowns = <(BIT(0) | BIT(1) | BIT(6) | BIT(7) | BIT(8) |
arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi-690- BIT(13) | BIT(15) | BIT(16) | BIT(17))>;
--
arch/arm/boot/dts/ti/omap/omap3-tao3530.dtsi=241=&twl_gpio {
--
arch/arm/boot/dts/ti/omap/omap3-tao3530.dtsi-246- * pulldowns:
arch/arm/boot/dts/ti/omap/omap3-tao3530.dtsi:247: * BIT(2), BIT(6), BIT(7), BIT(8), BIT(13)
arch/arm/boot/dts/ti/omap/omap3-tao3530.dtsi-248- * BIT(15), BIT(16), BIT(17)
--
arch/arm/mach-bcm/platsmp-brcmstb.c=25=enum {
--
arch/arm/mach-bcm/platsmp-brcmstb.c-30- ZONE_MAN_ISO_CNTL_MASK = BIT(6),
arch/arm/mach-bcm/platsmp-brcmstb.c:31: ZONE_MANUAL_CONTROL_MASK = BIT(7),
arch/arm/mach-bcm/platsmp-brcmstb.c-32- ZONE_PWR_DN_REQ_MASK = BIT(9),
--
arch/arm/mach-footbridge/ebsa285.c-24-#define XBUS_RED_L BIT(2)
arch/arm/mach-footbridge/ebsa285.c:25:#define XBUS_TOGGLE BIT(7)
arch/arm/mach-footbridge/ebsa285.c-26-
--
arch/arm/mach-lpc32xx/lpc32xx.h-208-#define LPC32XX_CLKPWR_GPIOSRC_P1IO0_BIT _BIT(8)
arch/arm/mach-lpc32xx/lpc32xx.h:209:#define LPC32XX_CLKPWR_GPIOSRC_P0IO7_BIT _BIT(7)
arch/arm/mach-lpc32xx/lpc32xx.h-210-#define LPC32XX_CLKPWR_GPIOSRC_P0IO6_BIT _BIT(6)
--
arch/arm/mach-lpc32xx/lpc32xx.h-238-#define LPC32XX_CLKPWR_INTSRC_KEY_BIT _BIT(16)
arch/arm/mach-lpc32xx/lpc32xx.h:239:#define LPC32XX_CLKPWR_INTSRC_MAC_BIT _BIT(7)
arch/arm/mach-lpc32xx/lpc32xx.h-240-#define LPC32XX_CLKPWR_INTSRC_P0P1_BIT _BIT(6)
--
arch/arm/mach-lpc32xx/lpc32xx.h-271-#define LPC32XX_CLKPWR_EXTSRC_SPI1_DATIN_BIT _BIT(8)
arch/arm/mach-lpc32xx/lpc32xx.h:272:#define LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT _BIT(7)
arch/arm/mach-lpc32xx/lpc32xx.h-273-#define LPC32XX_CLKPWR_EXTSRC_SPI2_DATIN_BIT _BIT(6)
--
arch/arm/mach-lpc32xx/lpc32xx.h-292-#define LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH _BIT(8)
arch/arm/mach-lpc32xx/lpc32xx.h:293:#define LPC32XX_CLKPWR_AUTO_SDRAM_SELF_RFSH _BIT(7)
arch/arm/mach-lpc32xx/lpc32xx.h-294-#define LPC32XX_CLKPWR_HIGHCORE_STATE_BIT _BIT(5)
--
arch/arm/mach-lpc32xx/lpc32xx.h-400-#define LPC32XX_CLKPWR_SDRCLK_DO_CAL _BIT(8)
arch/arm/mach-lpc32xx/lpc32xx.h:401:#define LPC32XX_CLKPWR_SDRCLK_CAL_ON_RTC _BIT(7)
arch/arm/mach-lpc32xx/lpc32xx.h-402-#define LPC32XX_CLKPWR_SDRCLK_DQS_DLY(n) (((n) & 0x1F) << 2)
--
arch/arm/mach-lpc32xx/lpc32xx.h-432-#define LPC32XX_CLKPWR_MSCARD_MSDIO23_DIS _BIT(8)
arch/arm/mach-lpc32xx/lpc32xx.h:433:#define LPC32XX_CLKPWR_MSCARD_MSDIO1_DIS _BIT(7)
arch/arm/mach-lpc32xx/lpc32xx.h-434-#define LPC32XX_CLKPWR_MSCARD_MSDIO0_DIS _BIT(6)
--
arch/arm/mach-omap2/clockdomain.h-50-#define CLKDM_MISSING_IDLE_REPORTING (1 << 6)
arch/arm/mach-omap2/clockdomain.h:51:#define CLKDM_STANDBY_FORCE_WAKEUP BIT(7)
arch/arm/mach-omap2/clockdomain.h-52-
--
arch/arm/mach-omap2/control.h-382-#define AM35XX_VPFE_CCDC_VD1_INT_CLR BIT(6)
arch/arm/mach-omap2/control.h:383:#define AM35XX_VPFE_CCDC_VD2_INT_CLR BIT(7)
arch/arm/mach-omap2/control.h-384-
--
arch/arm/mach-omap2/soc.h=423=extern u32 omap_features;
--
arch/arm/mach-omap2/soc.h-431-#define OMAP3_HAS_IO_WAKEUP BIT(6)
arch/arm/mach-omap2/soc.h:432:#define OMAP3_HAS_SDRC BIT(7)
arch/arm/mach-omap2/soc.h-433-#define OMAP3_HAS_IO_CHAIN_CTRL BIT(8)
--
arch/arm/mach-qcom/platsmp.c-27-#define PLL_CLAMP BIT(8)
arch/arm/mach-qcom/platsmp.c:28:#define CORE_PWRD_UP BIT(7)
arch/arm/mach-qcom/platsmp.c-29-#define COREPOR_RST BIT(5)
--
arch/arm64/include/asm/cpufeature.h=109=extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
--
arch/arm64/include/asm/cpufeature.h-284- */
arch/arm64/include/asm/cpufeature.h:285:#define ARM64_CPUCAP_MATCH_ALL_EARLY_CPUS ((u16)BIT(7))
arch/arm64/include/asm/cpufeature.h-286-
--
arch/arm64/include/asm/kvm_host.h=860=struct kvm_vcpu_arch {
--
arch/arm64/include/asm/kvm_host.h-1111-/* KVM is currently emulating a nested ERET */
arch/arm64/include/asm/kvm_host.h:1112:#define IN_NESTED_ERET __vcpu_single_flag(sflags, BIT(7))
arch/arm64/include/asm/kvm_host.h-1113-/* SError pending for nested guest */
--
arch/arm64/include/asm/kvm_pgtable.h=51=typedef u64 kvm_pte_t;
--
arch/arm64/include/asm/kvm_pgtable.h-80-#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R BIT(6)
arch/arm64/include/asm/kvm_pgtable.h:81:#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W BIT(7)
arch/arm64/include/asm/kvm_pgtable.h-82-#define KVM_PTE_LEAF_ATTR_LO_S2_SH GENMASK(9, 8)
--
arch/arm64/include/asm/sysreg.h-334-#define SYS_PAR_EL1_F1_IMPDEF GENMASK_ULL(63, 48)
arch/arm64/include/asm/sysreg.h:335:#define SYS_PAR_EL1_F1_RES0 (BIT(7) | BIT(10) | GENMASK_ULL(47, 16))
arch/arm64/include/asm/sysreg.h-336-#define SYS_PAR_EL1_RES1 BIT(11)
--
arch/arm64/kernel/pi/patch-scs.c=98=static int __always_inline skip_xleb128(const u8 **opcode, int size)
--
arch/arm64/kernel/pi/patch-scs.c-104- size--;
arch/arm64/kernel/pi/patch-scs.c:105: } while (c & BIT(7));
arch/arm64/kernel/pi/patch-scs.c-106-
--
arch/arm64/kernel/pi/patch-scs.c=149=static int scs_handle_fde_frame(const struct eh_frame *frame,
--
arch/arm64/kernel/pi/patch-scs.c-165- // assume single byte uleb128_t for augmentation data size
arch/arm64/kernel/pi/patch-scs.c:166: if (*opcode & BIT(7))
arch/arm64/kernel/pi/patch-scs.c-167- return EDYNSCS_INVALID_FDE_AUGM_DATA_SIZE;
--
arch/arm64/kernel/pi/patch-scs.c=236=int scs_patch(const u8 eh_frame[], int size, bool skip_dry_run)
--
arch/arm64/kernel/pi/patch-scs.c-267- */
arch/arm64/kernel/pi/patch-scs.c:268: if ((frame->code_alignment_factor & BIT(7)) ||
arch/arm64/kernel/pi/patch-scs.c:269: (frame->data_alignment_factor & BIT(7)) ||
arch/arm64/kernel/pi/patch-scs.c-270- frame->return_address_register != 30 ||
--
arch/arm64/kvm/config.c=17=struct reg_bits_to_feat_map {
--
arch/arm64/kvm/config.c-29-#define RES1_WHEN_E2H0 BIT(6) /* RES1 when E2H=0 and not supported */
arch/arm64/kvm/config.c:30:#define RES1_WHEN_E2H1 BIT(7) /* RES1 when E2H=1 and not supported */
arch/arm64/kvm/config.c-31-
--
arch/arm64/lib/insn.c=24=static int __kprobes aarch64_get_imm_shift_mask(enum aarch64_insn_imm_type type,
--
arch/arm64/lib/insn.c-55- case AARCH64_INSN_IMM_7:
arch/arm64/lib/insn.c:56: mask = BIT(7) - 1;
arch/arm64/lib/insn.c-57- shift = 15;
--
arch/loongarch/include/asm/loongarch.h-83-#define CPUCFG2_LSX BIT(6)
arch/loongarch/include/asm/loongarch.h:84:#define CPUCFG2_LASX BIT(7)
arch/loongarch/include/asm/loongarch.h-85-#define CPUCFG2_COMPLEX BIT(8)
--
arch/loongarch/include/asm/loongarch.h-111-#define CPUCFG3_ITLBT BIT(6)
arch/loongarch/include/asm/loongarch.h:112:#define CPUCFG3_ICACHET BIT(7)
arch/loongarch/include/asm/loongarch.h-113-#define CPUCFG3_SPW_LVL GENMASK(10, 8)
--
arch/loongarch/include/asm/loongarch.h-148-#define CPUCFG16_L2_IUINCL BIT(6)
arch/loongarch/include/asm/loongarch.h:149:#define CPUCFG16_L2_DPRE BIT(7)
arch/loongarch/include/asm/loongarch.h-150-#define CPUCFG16_L2_DPRIV BIT(8)
--
arch/m68k/mac/misc.c=125=static void via_rtc_send(__u8 data)
--
arch/m68k/mac/misc.c-145-
arch/m68k/mac/misc.c:146:#define RTC_FLG_READ BIT(7)
arch/m68k/mac/misc.c:147:#define RTC_FLG_WRITE_PROTECT BIT(7)
arch/m68k/mac/misc.c-148-#define RTC_CMD_READ(r) (RTC_FLG_READ | (r << 2))
--
arch/mips/include/asm/bitops.h=283=static inline bool xor_unlock_is_negative_byte(unsigned long mask,
--
arch/mips/include/asm/bitops.h-296- "ir"(mask));
arch/mips/include/asm/bitops.h:297: res = (orig & BIT(7)) != 0;
arch/mips/include/asm/bitops.h-298- }
--
arch/mips/include/asm/ip32/crime.h=20=struct sgi_crime {
--
arch/mips/include/asm/ip32/crime.h-56-#define MACE_AUDIO_INT BIT(6)
arch/mips/include/asm/ip32/crime.h:57:#define MACE_PCI_BRIDGE_INT BIT(7)
arch/mips/include/asm/ip32/crime.h-58-#define MACEPCI_SCSI0_INT BIT(8)
--
arch/mips/include/asm/ip32/mace.h=181=struct mace_isactrl {
--
arch/mips/include/asm/ip32/mace.h-202-#define MACEISA_AUDIO3_DMAT_INT BIT(6)
arch/mips/include/asm/ip32/mace.h:203:#define MACEISA_AUDIO3_MERR_INT BIT(7)
arch/mips/include/asm/ip32/mace.h-204-#define MACEISA_RTC_INT BIT(8)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-479-#define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_1 BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:480:#define QCA956X_PLL_SWITCH_CLOCK_SPARE_UART1_CLK_SEL BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-481-#define QCA956X_PLL_SWITCH_CLOCK_SPARE_USB_REFCLK_FREQ_SEL_SHIFT 8
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-558-#define MISC_INT_TIMER2 BIT(8)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:559:#define MISC_INT_DMA BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-560-#define MISC_INT_OHCI BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-592-#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:593:#define AR724X_RESET_PCIE_PHY BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-594-#define AR724X_RESET_PCIE BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-636-#define AR934X_RESET_ETH_SWITCH BIT(8)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:637:#define AR934X_RESET_PCIE_PHY BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-638-#define AR934X_RESET_PCIE BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-660-#define QCA953X_RESET_ETH_SWITCH BIT(8)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:661:#define QCA953X_RESET_PCIE_PHY BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-662-#define QCA953X_RESET_PCIE BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-690-#define QCA955X_RESET_SGMII BIT(8)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:691:#define QCA955X_RESET_PCIE_PHY BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-692-#define QCA955X_RESET_PCIE BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-730-#define AR934X_BOOTSTRAP_SW_OPTION1 BIT(16)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:731:#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-732-#define AR934X_BOOTSTRAP_PCIE_RC BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-756-#define AR934X_PCIE_WMAC_INT_PCIE_RC1 BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:757:#define AR934X_PCIE_WMAC_INT_PCIE_RC2 BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-758-#define AR934X_PCIE_WMAC_INT_PCIE_RC3 BIT(8)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-774-#define QCA953X_PCIE_WMAC_INT_PCIE_RC1 BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:775:#define QCA953X_PCIE_WMAC_INT_PCIE_RC2 BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-776-#define QCA953X_PCIE_WMAC_INT_PCIE_RC3 BIT(8)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-792-#define QCA955X_EXT_INT_PCIE_RC1_INT1 BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:793:#define QCA955X_EXT_INT_PCIE_RC1_INT2 BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-794-#define QCA955X_EXT_INT_PCIE_RC1_INT3 BIT(8)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-823-#define QCA956X_EXT_INT_PCIE_RC1_INT1 BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:824:#define QCA956X_EXT_INT_PCIE_RC1_INT2 BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-825-#define QCA956X_EXT_INT_PCIE_RC1_INT3 BIT(8)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1042-#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1043:#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1044-#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1073-#define AR933X_GPIO_FUNC_SPI_CS_EN1 BIT(13)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1074:#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1075-#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1084-#define AR934X_GPIO_FUNC_CLK_OBS6_EN BIT(8)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1085:#define AR934X_GPIO_FUNC_CLK_OBS5_EN BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1086-#define AR934X_GPIO_FUNC_CLK_OBS4_EN BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1104-#define QCA955X_GPIO_FUNC_CLK_OBS6_EN BIT(8)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1105:#define QCA955X_GPIO_FUNC_CLK_OBS5_EN BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1106-#define QCA955X_GPIO_FUNC_CLK_OBS4_EN BIT(6)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1199-#define AR933X_ETH_CFG_MII_GE0_ERR_EN BIT(5)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1200:#define AR933X_ETH_CFG_SW_PHY_SWAP BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1201-#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1217-#define AR934X_ETH_CFG_SW_ONLY_MODE BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1218:#define AR934X_ETH_CFG_SW_PHY_SWAP BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1219-#define AR934X_ETH_CFG_SW_APB_ACCESS BIT(9)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1236-#define QCA953X_ETH_CFG_SW_ONLY_MODE BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1237:#define QCA953X_ETH_CFG_SW_PHY_SWAP BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1238-#define QCA953X_ETH_CFG_SW_APB_ACCESS BIT(9)
--
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1283-#define QCA956X_ETH_CFG_GE0_SGMII BIT(6)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h:1284:#define QCA956X_ETH_CFG_SW_ONLY_MODE BIT(7)
arch/mips/include/asm/mach-ath79/ar71xx_regs.h-1285-#define QCA956X_ETH_CFG_SW_PHY_SWAP BIT(8)
--
arch/mips/include/asm/mach-ath79/ar933x_uart.h-36-#define AR933X_UART_CS_DMA_EN BIT(6)
arch/mips/include/asm/mach-ath79/ar933x_uart.h:37:#define AR933X_UART_CS_TX_READY_ORIDE BIT(7)
arch/mips/include/asm/mach-ath79/ar933x_uart.h-38-#define AR933X_UART_CS_RX_READY_ORIDE BIT(8)
--
arch/mips/include/asm/mach-ath79/ar933x_uart.h-58-#define AR933X_UART_INT_RX_BREAK_ON BIT(6)
arch/mips/include/asm/mach-ath79/ar933x_uart.h:59:#define AR933X_UART_INT_RX_BREAK_OFF BIT(7)
arch/mips/include/asm/mach-ath79/ar933x_uart.h-60-#define AR933X_UART_INT_RX_FULL BIT(8)
--
arch/mips/include/asm/mach-loongson64/loongson_regs.h=19=static inline u32 read_cpucfg(u32 reg)
--
arch/mips/include/asm/mach-loongson64/loongson_regs.h-46-#define LOONGSON_CFG1_MSA2 BIT(6)
arch/mips/include/asm/mach-loongson64/loongson_regs.h:47:#define LOONGSON_CFG1_CGP BIT(7)
arch/mips/include/asm/mach-loongson64/loongson_regs.h-48-#define LOONGSON_CFG1_WRP BIT(8)
--
arch/mips/include/asm/mach-loongson64/loongson_regs.h-81-#define LOONGSON_CFG2_LBT3 BIT(6)
arch/mips/include/asm/mach-loongson64/loongson_regs.h:82:#define LOONGSON_CFG2_LBTMMU BIT(7)
arch/mips/include/asm/mach-loongson64/loongson_regs.h-83-#define LOONGSON_CFG2_LPMP BIT(8)
--
arch/mips/include/asm/mach-ralink/rt3883.h-96-#define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8)
arch/mips/include/asm/mach-ralink/rt3883.h:97:#define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7)
arch/mips/include/asm/mach-ralink/rt3883.h-98-#define RT3883_SYSCFG1_PCI_66M_MODE BIT(6)
--
arch/mips/include/asm/mach-ralink/rt3883.h-186-#define RT3883_INTC_INT_PIO BIT(6)
arch/mips/include/asm/mach-ralink/rt3883.h:187:#define RT3883_INTC_INT_DMA BIT(7)
arch/mips/include/asm/mach-ralink/rt3883.h-188-#define RT3883_INTC_INT_NAND BIT(8)
--
arch/mips/include/asm/sgi/heart.h=79=struct ip30_heart_regs { /* 0x0ff00000 */
--
arch/mips/include/asm/sgi/heart.h-195-#define HM_SYSSTATE_ERE BIT(8)
arch/mips/include/asm/sgi/heart.h:196:#define HM_SYSCMD_ERE BIT(7)
arch/mips/include/asm/sgi/heart.h-197-#define HM_NCOR_SYS_ERE BIT(6)
--
arch/mips/lantiq/xway/gptu.c-43-#define CON_CNT BIT(2)
arch/mips/lantiq/xway/gptu.c:44:#define CON_EDGE_ANY (BIT(7) | BIT(6))
arch/mips/lantiq/xway/gptu.c-45-#define CON_SYNC BIT(8)
--
arch/mips/lantiq/xway/sysctrl.c=76=static u32 pmu_clk_cr_b[] = {
--
arch/mips/lantiq/xway/sysctrl.c-91-#define PMU_USB0 BIT(6)
arch/mips/lantiq/xway/sysctrl.c:92:#define PMU_ASC0 BIT(7)
arch/mips/lantiq/xway/sysctrl.c:93:#define PMU_EPHY BIT(7) /* ase */
arch/mips/lantiq/xway/sysctrl.c:94:#define PMU_USIF BIT(7) /* from vr9 until grx390 */
arch/mips/lantiq/xway/sysctrl.c-95-#define PMU_SPI BIT(8)
--
arch/mips/lib/bitops.c=150=bool __mips_xor_is_negative_byte(unsigned long mask,
--
arch/mips/lib/bitops.c-160-
arch/mips/lib/bitops.c:161: return (data & BIT(7)) != 0;
arch/mips/lib/bitops.c-162-}
--
arch/mips/mti-malta/malta-setup.c-30-#define ROCIT_CONFIG_GEN0 0x1f403000
arch/mips/mti-malta/malta-setup.c:31:#define ROCIT_CONFIG_GEN0_PCI_IOCU BIT(7)
arch/mips/mti-malta/malta-setup.c-32-
--
arch/mips/ralink/timer.c-27-
arch/mips/ralink/timer.c:28:#define TMR0CTL_ENABLE BIT(7)
arch/mips/ralink/timer.c-29-#define TMR0CTL_MODE_PERIODIC BIT(4)
--
arch/powerpc/platforms/512x/clock-commonclk.c=1014=static void __init mpc5121_clk_provide_backwards_compat(void)
--
arch/powerpc/platforms/512x/clock-commonclk.c-1023- DID_REG_VIU = BIT(6),
arch/powerpc/platforms/512x/clock-commonclk.c:1024: DID_REG_FEC = BIT(7),
arch/powerpc/platforms/512x/clock-commonclk.c-1025- DID_REG_USB = BIT(8),
--
arch/powerpc/platforms/powernv/vas.h-205-#define VAS_WINCTL_RX_WORD_MODE PPC_BIT(6)
arch/powerpc/platforms/powernv/vas.h:206:#define VAS_WINCTL_RSVD_TXBUF PPC_BIT(7)
arch/powerpc/platforms/powernv/vas.h-207-#define VAS_WINCTL_THRESH_CTL PPC_BITMASK(8, 9)
--
arch/riscv/include/asm/bitops.h=337=static __always_inline bool arch_xor_unlock_is_negative_byte(unsigned long mask,
--
arch/riscv/include/asm/bitops.h-345- : "memory");
arch/riscv/include/asm/bitops.h:346: return (res & BIT(7)) != 0;
arch/riscv/include/asm/bitops.h-347-}
--
arch/riscv/include/asm/sbi.h=241=enum sbi_pmu_ctr_type {
--
arch/riscv/include/asm/sbi.h-270-#define SBI_PMU_CFG_FLAG_SET_SINH BIT(6)
arch/riscv/include/asm/sbi.h:271:#define SBI_PMU_CFG_FLAG_SET_MINH BIT(7)
arch/riscv/include/asm/sbi.h-272-
--
arch/sh/drivers/pci/pci-sh4.h-47- #define SH4_PCIINTM_MDEIM BIT(8) /* Master function disable error */
arch/sh/drivers/pci/pci-sh4.h:48: #define SH4_PCIINTM_APEDIM BIT(7) /* Address parity error detection */
arch/sh/drivers/pci/pci-sh4.h-49- #define SH4_PCIINTM_SDIM BIT(6) /* SERR detection */
--
arch/sh/include/mach-sdk7786/mach/fpga.h-78-#define PWRCR_PDWNACK BIT(5) /* Power down acknowledge */
arch/sh/include/mach-sdk7786/mach/fpga.h:79:#define PWRCR_PDWNREQ BIT(7) /* Power down request */
arch/sh/include/mach-sdk7786/mach/fpga.h-80-#define PWRCR_INT2 BIT(11) /* INT2 connection to power manager */
--
arch/sparc/include/asm/hypervisor.h=994=unsigned long sun4v_ccb_submit(unsigned long ccb_buf,
--
arch/sparc/include/asm/hypervisor.h-1008-#define HV_CCB_ARG0_PRIVILEGED BIT(6)
arch/sparc/include/asm/hypervisor.h:1009:#define HV_CCB_ALL_OR_NOTHING BIT(7)
arch/sparc/include/asm/hypervisor.h-1010-#define HV_CCB_QUEUE_INFO BIT(8)
--
arch/x86/coco/sev/vc-shared.c=168=static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
--
arch/x86/coco/sev/vc-shared.c-203-#define IOIO_ADDR_32 BIT(8)
arch/x86/coco/sev/vc-shared.c:204:#define IOIO_ADDR_16 BIT(7)
arch/x86/coco/sev/vc-shared.c-205-
--
arch/x86/coco/tdx/tdx.c=577=static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
--
arch/x86/coco/tdx/tdx.c-669- extend_size = insn.opnd_bytes;
arch/x86/coco/tdx/tdx.c:670: if (size == 1 && val & BIT(7))
arch/x86/coco/tdx/tdx.c-671- extend_val = 0xFF;
--
arch/x86/events/intel/pt.c=52=static struct pt_cap_desc {
--
arch/x86/events/intel/pt.c-64- PT_CAP(power_event_trace, 0, CPUID_EBX, BIT(5)),
arch/x86/events/intel/pt.c:65: PT_CAP(event_trace, 0, CPUID_EBX, BIT(7)),
arch/x86/events/intel/pt.c-66- PT_CAP(tnt_disable, 0, CPUID_EBX, BIT(8)),
--
arch/x86/include/asm/msr-index.h-89-#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
arch/x86/include/asm/msr-index.h:90:#define PRED_CMD_SBPB BIT(7) /* Selective Branch Prediction Barrier */
arch/x86/include/asm/msr-index.h-91-
--
arch/x86/include/asm/msr-index.h-148- */
arch/x86/include/asm/msr-index.h:149:#define ARCH_CAP_TSX_CTRL_MSR BIT(7) /* MSR for TSX control is available. */
arch/x86/include/asm/msr-index.h-150-#define ARCH_CAP_TAA_NO BIT(8) /*
--
arch/x86/include/asm/msr-index.h-366-#define RTIT_CTL_FABRIC_EN BIT(6)
arch/x86/include/asm/msr-index.h:367:#define RTIT_CTL_CR3EN BIT(7)
arch/x86/include/asm/msr-index.h-368-#define RTIT_CTL_TOPA BIT(8)
--
arch/x86/include/asm/sgx.h=128=enum sgx_attribute {
--
arch/x86/include/asm/sgx.h-135- /* BIT(6) is for CET */
arch/x86/include/asm/sgx.h:136: SGX_ATTR_KSS = BIT(7),
arch/x86/include/asm/sgx.h-137- /* BIT(8) is reserved */
--
arch/x86/include/asm/shared/tdx.h-91-#define TDX_RSI BIT(6)
arch/x86/include/asm/shared/tdx.h:92:#define TDX_RDI BIT(7)
arch/x86/include/asm/shared/tdx.h-93-#define TDX_R8 BIT(8)
--
arch/x86/include/asm/vmx.h=595=enum vm_entry_failure_code {
--
arch/x86/include/asm/vmx.h-614- EPT_VIOLATION_PROT_EXEC)
arch/x86/include/asm/vmx.h:615:#define EPT_VIOLATION_GVA_IS_VALID BIT(7)
arch/x86/include/asm/vmx.h-616-#define EPT_VIOLATION_GVA_TRANSLATED BIT(8)
--
arch/x86/kernel/cpu/common.c=1135=static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
--
arch/x86/kernel/cpu/common.c-1165-#define NO_SWAPGS BIT(6)
arch/x86/kernel/cpu/common.c:1166:#define NO_ITLB_MULTIHIT BIT(7)
arch/x86/kernel/cpu/common.c-1167-#define NO_SPECTRE_V2 BIT(8)
--
arch/x86/kernel/cpu/common.c=1184=static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
--
arch/x86/kernel/cpu/common.c-1276-/* CPU is affected by Register File Data Sampling */
arch/x86/kernel/cpu/common.c:1277:#define RFDS BIT(7)
arch/x86/kernel/cpu/common.c-1278-/* CPU is affected by Indirect Target Selection */
--
arch/x86/kernel/cpu/mce/core.c=533=bool mce_is_memory_error(struct mce *m)
--
arch/x86/kernel/cpu/mce/core.c-554- */
arch/x86/kernel/cpu/mce/core.c:555: return (m->status & 0xef80) == BIT(7) ||
arch/x86/kernel/cpu/mce/core.c-556- (m->status & 0xef00) == BIT(8) ||
--
arch/x86/platform/ts5500/ts5500.c-36-#define TS5500_RS485_RTS BIT(6) /* RTS for RS-485 */
arch/x86/platform/ts5500/ts5500.c:37:#define TS5500_RS485_AUTO BIT(7) /* Automatic RS-485 */
arch/x86/platform/ts5500/ts5500.c-38-
--
arch/x86/platform/ts5500/ts5500.c-52-#define TS5500_JP6 BIT(6) /* Console on COM1 (req. JP2) */
arch/x86/platform/ts5500/ts5500.c:53:#define TS5500_JP7 BIT(7) /* Undocumented (Unused) */
arch/x86/platform/ts5500/ts5500.c-54-
--
drivers/accel/habanalabs/gaudi/gaudiP.h-165-#define HW_CAP_MSI BIT(6)
drivers/accel/habanalabs/gaudi/gaudiP.h:166:#define HW_CAP_CPU_Q BIT(7)
drivers/accel/habanalabs/gaudi/gaudiP.h-167-#define HW_CAP_HBM_DMA BIT(8)
--
drivers/accel/ivpu/ivpu_drv.h-73-#define IVPU_DBG_PM BIT(6)
drivers/accel/ivpu/ivpu_drv.h:74:#define IVPU_DBG_IPC BIT(7)
drivers/accel/ivpu/ivpu_drv.h-75-#define IVPU_DBG_BO BIT(8)
--
drivers/accel/ivpu/ivpu_mmu_context.c-26-#define IVPU_MMU_ENTRY_FLAG_AF BIT(10)
drivers/accel/ivpu/ivpu_mmu_context.c:27:#define IVPU_MMU_ENTRY_FLAG_RO BIT(7)
drivers/accel/ivpu/ivpu_mmu_context.c-28-#define IVPU_MMU_ENTRY_FLAG_USER BIT(6)
--
drivers/accel/qaic/qaic_data.c=256=static int encode_reqs(struct qaic_device *qdev, struct bo_slice *slice,
--
drivers/accel/qaic/qaic_data.c-282- case 32:
drivers/accel/qaic/qaic_data.c:283: db_len = BIT(7);
drivers/accel/qaic/qaic_data.c-284- break;
drivers/accel/qaic/qaic_data.c-285- case 16:
drivers/accel/qaic/qaic_data.c:286: db_len = BIT(7) | 1;
drivers/accel/qaic/qaic_data.c-287- break;
drivers/accel/qaic/qaic_data.c-288- case 8:
drivers/accel/qaic/qaic_data.c:289: db_len = BIT(7) | 2;
drivers/accel/qaic/qaic_data.c-290- break;
--
drivers/accel/qaic/qaic_ras.c=161=struct pcie_syndrome {
--
drivers/accel/qaic/qaic_ras.c-181- * BIT(0): Power break (low power)
drivers/accel/qaic/qaic_ras.c:182: * BIT(1) to BIT(7): Reserved
drivers/accel/qaic/qaic_ras.c-183- */
--
drivers/acpi/acpi_tad.c=37=MODULE_AUTHOR("Rafael J. Wysocki");
--
drivers/acpi/acpi_tad.c-46-#define ACPI_TAD_AC_S5_WAKE BIT(6)
drivers/acpi/acpi_tad.c:47:#define ACPI_TAD_DC_S4_WAKE BIT(7)
drivers/acpi/acpi_tad.c-48-#define ACPI_TAD_DC_S5_WAKE BIT(8)
--
drivers/acpi/apei/einj-core.c=806=static struct { u32 mask; const char *str; } const einj_error_type_string[] = {
--
drivers/acpi/apei/einj-core.c-813- { BIT(6), "PCI Express Correctable" },
drivers/acpi/apei/einj-core.c:814: { BIT(7), "PCI Express Uncorrectable non-fatal" },
drivers/acpi/apei/einj-core.c-815- { BIT(8), "PCI Express Uncorrectable fatal" },
--
drivers/amba/tegra-ahb.c-33-#define ENB_FAST_REARBITRATE BIT(2)
drivers/amba/tegra-ahb.c:34:#define DONT_SPLIT_AHB_WR BIT(7)
drivers/amba/tegra-ahb.c-35-
--
drivers/ata/ahci.h=40=enum {
--
drivers/ata/ahci.h-59- AHCI_CMD_WRITE = BIT(6),
drivers/ata/ahci.h:60: AHCI_CMD_PREFETCH = BIT(7),
drivers/ata/ahci.h-61- AHCI_CMD_RESET = BIT(8),
--
drivers/ata/ahci.h-87- HOST_CAP_EMS = BIT(6), /* Enclosure Management support */
drivers/ata/ahci.h:88: HOST_CAP_CCC = BIT(7), /* Command Completion Coalescing */
drivers/ata/ahci.h-89- HOST_CAP_PART = BIT(13), /* Partial state capable */
--
drivers/ata/ahci.h-141- PORT_IRQ_PHYRDY = BIT(22), /* PhyRdy changed */
drivers/ata/ahci.h:142: PORT_IRQ_DMPS = BIT(7), /* mechanical presence status */
drivers/ata/ahci.h-143- PORT_IRQ_CONNECT = BIT(6), /* port connect change status */
]
]
|
| 22/2 |
2026/05/16 04:34 |
llm |
expert |
0m
Model:
Tokens:
input: 28064
output: 22
thoughts: 61
Thoughts: Okay, here's my interpretation of that thought process, assuming I'm deep in the weeds of kernel debugging:
**Decoding That Bitmask**
Right, `0x08300080`. That's not just a random number; it immediately screams "bitfield!" in my head. I'm seeing `BIT(27)`, `BIT(21)`, `BIT(20)`, and `BIT(7)` all set. I need to understand what these bits represent in this context. My intuition is telling me this relates to dcache, but I should double-check. I'm going straight to `include/linux/dcache.h` to confirm my suspicion about `BIT(7)`. I want to know what functionality or setting is triggered when that bit is active. I bet it's something fundamental, given its prominent position in this bitmask.
|
| 23/2 |
2026/05/16 04:35 |
tool |
grepper |
0m
Args: map[Expression:DCACHE_.*BIT\(7\)]
Results: map[Output:include/linux/dcache.h=192=enum dentry_flags {
--
include/linux/dcache.h-210- DCACHE_REFERENCED = BIT(6), /* Recently used, don't discard. */
include/linux/dcache.h:211: DCACHE_DONTCACHE = BIT(7), /* Purge from memory on final dput() */
include/linux/dcache.h-212- DCACHE_CANT_MOUNT = BIT(8),
]
|
| 24/2 |
2026/05/16 04:35 |
llm |
expert |
0m
Model:
Tokens:
input: 28473
output: 39
thoughts: 1045
Thoughts: **Analyzing a KCSAN Report on Dentry Flags**
Okay, let's break this down. KCSAN reported a change in a dentry's `d_flags` from `0x08300080` to `0x00004080`. First, I decoded those values. `0x08300080` translates to `DCACHE_PERSISTENT | DCACHE_LRU_LIST | DCACHE_SHRINK_LIST | DCACHE_DONTCACHE`. `0x00004080` means `DCACHE_DENTRY_KILLED | DCACHE_DONTCACHE`. So, we're seeing bits being cleared and set: `PERSISTENT`, `LRU_LIST`, `SHRINK_LIST` are cleared, and `DENTRY_KILLED` is set, while `DONTCACHE` persists.
The puzzle is how this could happen, because `d_make_discardable` is only supposed to clear `DCACHE_PERSISTENT`. I know `d_make_discardable` is part of `simple_unlink` -> `shmem_unlink` -> `vfs_unlink`, and immediately calls `finish_dput(dentry)`. `finish_dput` can *definitely* kill the dentry, which means setting `DCACHE_DENTRY_KILLED` and clearing the LRU and SHRINK lists.
The KCSAN report pinpoints the write: it's from `d_make_discardable+0x4f/0xa0 fs/dcache.c:984`, which is `dentry->d_flags &= ~DCACHE_PERSISTENT;`. But that alone would only change the value to `0x00300080`, not `0x00004080`. Ah, that's it! KCSAN's watchpoint takes a moment to trigger and then read the value *after* the write. By the time KCSAN read the value, `finish_dput` had already run and modified the `d_flags` further! So, the `d_make_discardable` write *plus* the subsequent actions in `finish_dput` explain the final value.
So, is this a *problem*? The code that triggers this KCSAN report uses `d_managed(dentry)`, which checks if a dentry is *managed*. This involves checking `DCACHE_MANAGED_DENTRY`, which is composed of `DCACHE_MOUNTED`, `DCACHE_NEED_AUTOMOUNT`, and `DCACHE_MANAGE_TRANSIT`. Crucially, *none* of these bits are modified by `d_make_discardable` or, apparently, `finish_dput` in this code path. I still need to double check `finish_dput`, just in case. However, based on this, it seems the write race *isn't* a problem with respect to `d_managed(dentry)`. I need to ensure that the bits in question are not accessed elsewhere.
|
| 25/2 |
2026/05/16 04:35 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/dcache.c IncludeLines:true Name:finish_dput]
Results: map[SourceCode: 921: static void finish_dput(struct dentry *dentry)
922: __releases(dentry->d_lock)
923: __releases(RCU)
924: {
925: while (lock_for_kill(dentry)) {
926: rcu_read_unlock();
927: dentry = __dentry_kill(dentry);
928: if (!dentry)
929: return;
930: if (retain_dentry(dentry, true)) {
931: spin_unlock(&dentry->d_lock);
932: return;
933: }
934: rcu_read_lock();
935: }
936: rcu_read_unlock();
937: spin_unlock(&dentry->d_lock);
938: }
SourceFile:fs/dcache.c]
|
| 26/2 |
2026/05/16 04:35 |
llm |
expert |
0m
Model:
Tokens:
input: 30524
output: 40
thoughts: 11
Thoughts: Okay, here's my attempt at summarizing that thought process, tailored for an expert audience:
**Analyzing the `__dentry_kill` Function**
Alright, let's dive into this. The initial impulse here is to dissect the `__dentry_kill` function. I'm immediately thinking about its role in the dentry cache management, and specifically how it deals with the removal of dentries. This implies a need to understand the implications of calling this function. What kind of cleanup does it perform? Are there subtle locking implications I need to be aware of? Does it interact directly with the inode or VFS layers? What are the potential race conditions related to reference counts and concurrent access during dentry removal? This function is fundamental to the stability of the file system. It's time to dig in.
|
| 27/2 |
2026/05/16 04:35 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/dcache.c IncludeLines:true Name:__dentry_kill]
Results: map[SourceCode: 694: static struct dentry *__dentry_kill(struct dentry *dentry)
695: {
696: struct dentry *parent = NULL;
697: bool can_free = true;
698:
699: /*
700: * The dentry is now unrecoverably dead to the world.
701: */
702: lockref_mark_dead(&dentry->d_lockref);
703:
704: /*
705: * inform the fs via d_prune that this dentry is about to be
706: * unhashed and destroyed.
707: */
708: if (dentry->d_flags & DCACHE_OP_PRUNE)
709: dentry->d_op->d_prune(dentry);
710:
711: if (dentry->d_flags & DCACHE_LRU_LIST) {
712: if (!(dentry->d_flags & DCACHE_SHRINK_LIST))
713: d_lru_del(dentry);
714: }
715: /* if it was on the hash then remove it */
716: __d_drop(dentry);
717: if (dentry->d_inode)
718: dentry_unlink_inode(dentry);
719: else
720: spin_unlock(&dentry->d_lock);
721: this_cpu_dec(nr_dentry);
722: if (dentry->d_op && dentry->d_op->d_release)
723: dentry->d_op->d_release(dentry);
724:
725: cond_resched();
726: /* now that it's negative, ->d_parent is stable */
727: if (!IS_ROOT(dentry)) {
728: parent = dentry->d_parent;
729: spin_lock(&parent->d_lock);
730: }
731: spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
732: dentry_unlist(dentry);
733: if (dentry->d_flags & DCACHE_SHRINK_LIST)
734: can_free = false;
735: spin_unlock(&dentry->d_lock);
736: if (likely(can_free))
737: dentry_free(dentry);
738: if (parent && --parent->d_lockref.count) {
739: spin_unlock(&parent->d_lock);
740: return NULL;
741: }
742: return parent;
743: }
SourceFile:fs/dcache.c]
|
| 28/2 |
2026/05/16 04:35 |
llm |
expert |
0m
Model:
Tokens:
input: 31553
output: 41
thoughts: 44
Thoughts: **Tracing the `DCACHE_DENTRY_KILLED` Flag**
Okay, hold on a second. I need to understand where this `DCACHE_DENTRY_KILLED` flag is actually being set. It's crucial for the integrity of the dentry cache, so I need to know the exact path of its setting. Let me think... wait, is it `lockref_mark_dead`? That's a likely candidate, given the context. Yes, that seems right. Alright, let's just confirm that. I'll need to double check the implementation of `lockref_mark_dead` to be absolutely certain, just to confirm my initial hypothesis. Let's dig into that function.
|
| 29/2 |
2026/05/16 04:35 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:lib/lockref.c IncludeLines:true Name:lockref_mark_dead]
Results: map[SourceCode: 127: /**
128: * lockref_mark_dead - mark lockref dead
129: * @lockref: pointer to lockref structure
130: */
131: void lockref_mark_dead(struct lockref *lockref)
132: {
133: assert_spin_locked(&lockref->lock);
134: lockref->count = -128;
135: }
SourceFile:lib/lockref.c]
|
| 30/2 |
2026/05/16 04:35 |
llm |
expert |
0m
Model:
Tokens:
input: 31946
output: 23
thoughts: 52
Thoughts: **Investigating the Dentry Death Count**
Okay, hold on a second. I'm seeing `lockref_mark_dead` set the `count` to -128. That's... unusual. Where does that constant `-128` actually come into play? It looks like we're signaling a killed dentry here, but I need to understand how this is used and why this specific value.
My first thought is, where is `DCACHE_DENTRY_KILLED` defined and, more importantly, *used*? I need to find all instances of that macro. Let's start with a thorough search for `DCACHE_DENTRY_KILLED`. That's going to be key to understanding the lifecycle, isn't it? Gotta track down where and how the death flag is being manipulated.
|
| 31/2 |
2026/05/16 04:35 |
tool |
grepper |
0m
Args: map[Expression:DCACHE_DENTRY_KILLED]
Results: map[Output:fs/dcache.c=655=static inline void dentry_unlist(struct dentry *dentry)
--
fs/dcache.c-661- */
fs/dcache.c:662: dentry->d_flags |= DCACHE_DENTRY_KILLED;
fs/dcache.c-663- d_complete_waiters(dentry);
--
fs/dcache.c=1203=void shrink_dentry_list(struct list_head *list)
--
fs/dcache.c-1214- d_shrink_del(dentry);
fs/dcache.c:1215: can_free = dentry->d_flags & DCACHE_DENTRY_KILLED;
fs/dcache.c-1216- spin_unlock(&dentry->d_lock);
--
fs/dcache.c=1370=static void d_walk(struct dentry *parent, void *data,
--
fs/dcache.c-1443- hlist_for_each_entry_continue(dentry, d_sib) {
fs/dcache.c:1444: if (likely(!(dentry->d_flags & DCACHE_DENTRY_KILLED))) {
fs/dcache.c-1445- rcu_read_unlock();
--
fs/dcache.c=1643=static void shrink_dcache_tree(struct dentry *parent, bool for_umount)
--
fs/dcache.c-1666- if (v->d_lockref.count < 0 &&
fs/dcache.c:1667: !(v->d_flags & DCACHE_DENTRY_KILLED)) {
fs/dcache.c-1668- struct completion_list wait;
--
include/linux/dcache.h=192=enum dentry_flags {
--
include/linux/dcache.h-220- DCACHE_FSNOTIFY_PARENT_WATCHED = BIT(13), /* Parent inode is watched by some fsnotify listener */
include/linux/dcache.h:221: DCACHE_DENTRY_KILLED = BIT(14),
include/linux/dcache.h-222- DCACHE_MOUNTED = BIT(15), /* is a mountpoint */
]
|
| 32/2 |
2026/05/16 04:35 |
llm |
expert |
0m
Model:
Tokens:
input: 32799
output: 39
thoughts: 418
Thoughts: **My Analysis of a Potential Data Race**
Okay, so `dentry_unlist` is setting `DCACHE_DENTRY_KILLED`, and that's called by `__dentry_kill`, which in turn is called by `finish_dput`. Thus, `finish_dput` is the culprit here, setting the `DCACHE_DENTRY_KILLED` flag. Also `d_lru_del` is clearing `DCACHE_LRU_LIST`. The observed change in `d_flags` from `0x08300080` to `0x00004080` is completely accounted for by the combination of `d_make_discardable` and `finish_dput` running.
Now, that `d_managed` reader is only looking at `DCACHE_MOUNTED | DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT` bits. None of those are modified in this sequence. This seems like a perfectly safe read on the `d_flags` variable, which confirms my initial intuition that this is a benign data race.
But, I'm a bit paranoid, so let's double-check. Could there be any other way this could be exploitable or, worst case, result in a denial of service? What if the compiler does something *really* weird to optimize `d_managed`?
```c
static inline bool d_managed(const struct dentry *dentry)
{
return dentry->d_flags & DCACHE_MANAGED_DENTRY;
}
```
Looking at the code, it's just a simple load and a bitwise AND. Barring some truly bizarre compiler bug, it can't crash unless `dentry` has been freed. The important part here is the dentry is protected by RCU, especially in `LOOKUP_RCU` mode. This is good because `d_make_discardable` is called on a dentry that's *being* unlinked. This means the dentry isn't immediately freed. Instead, it gets freed later, via RCU, because `dentry_free` uses `call_rcu` or something similar. I should probably double check the `dentry_free` implementation, just in case, but I'm pretty confident in my assessment.
|
| 33/2 |
2026/05/16 04:35 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:fs/dcache.c IncludeLines:true Name:dentry_free]
Results: map[SourceCode: 429: static void dentry_free(struct dentry *dentry)
430: {
431: WARN_ON(d_really_is_positive(dentry));
432: if (unlikely(dname_external(dentry))) {
433: struct external_name *p = external_name(dentry);
434: if (likely(atomic_dec_and_test(&p->count))) {
435: call_rcu(&dentry->d_rcu, __d_free_external);
436: return;
437: }
438: }
439: /* if dentry was never visible to RCU, immediate free is OK */
440: if (dentry->d_flags & DCACHE_NORCU)
441: __d_free(&dentry->d_rcu);
442: else
443: call_rcu(&dentry->d_rcu, __d_free);
444: }
SourceFile:fs/dcache.c]
|
| 34/2 |
2026/05/16 04:35 |
llm |
expert |
0m
Model:
Tokens:
input: 34073
output: 66
thoughts: 1199
Thoughts: **Benign Data Race Analysis**
Okay, so we're looking at a KCSAN report related to `d_flags` and `d_managed` during RCU walks. First, I confirmed that `call_rcu` is definitely in play, meaning the dentry memory is safe to access during the RCU walk. The core of the issue is a read of `d_flags` while it's being modified, a classic data race.
The good news is, the bits being modified are entirely disjoint from the bits being read. Furthermore, the modification involves a read-modify-write operation, so we are *reasonably* safe.
My initial concern was a compiler doing something funky and reordering or tearing reads. The kernel accesses `d_flags` concurrently in a bunch of places, and we usually see `READ_ONCE` used if there's a known race. But, `d_managed` simply uses a bitwise AND with `dentry->d_flags`.
Let's dive deeper and see if the compiler could mess with that. The bits of `DCACHE_MANAGED_DENTRY` are in the 2nd and 3rd byte. Bits being modified and read, are `BIT(15) | BIT(16) | BIT(17)`. These all fall within the second and third bytes, with `DCACHE_PERSISTENT` in the 4th byte. This means even a torn read, if the compiler was *that* aggressive, wouldn't mix the relevant bits. Also, modern compilers don't typically tear 32-bit aligned reads anyway.
So, this is a completely benign data race. It's not exploitable for anything malicious. It won't cause a denial of service; KCSAN reports, while important, don't halt the kernel in production. The race can be triggered by any unprivileged user, by unlinking a file while another process is doing a path lookup. It is accessible from user namespaces and is also reproducible within a VM guest. It isn't a network trigger, peripheral trigger, etc.
Now, let's go back through all the questions:
* Exploitable: No.
* Denial Of Service: No.
* Accessible From Unprivileged Processes: Yes.
* Accessible From User Namespaces: Yes.
* VM Guest Trigger: Yes.
* VM Host Trigger: No.
* Network Trigger: No.
* Remote Trigger: No.
* Peripheral Trigger: No.
* Malicious Filesystem Trigger: No.
I need to confirm if `d_make_discardable` is ever called on a dentry that *isn't* protected by RCU. I checked. The function is called from `simple_unlink` and `shmem_unlink`. Those are for ramfs/tmpfs/shmem unlinks, and the dentry *is* part of the dcache, therefore it *is* protected by RCU.
Next, I'll see if `d_flags` is ever concurrently modified by multiple *writers*.
`d_make_discardable` is protected by `spin_lock(&dentry->d_lock)`. `finish_dput` *also* holds or takes the lock. So, the writers are serialized. The problem boils down to that lockless reader in `d_managed`. Classic VFS lockless path walk data race. The VFS depends on these, and KCSAN frequently flags them. Many of these are slowly being annotated with `data_race()` or `READ_ONCE()`, but there are still tons left.
So, here's my final breakdown:
Exploitable: False
DenialOfService: False
Unprivileged: True
UserNamespace: True
VMGuestTrigger: True
VMHostTrigger: False
NetworkTrigger: False
RemoteTrigger: False
PeripheralTrigger: False
FilesystemTrigger: False
Let's double-check the `d_managed` call within `step_into_slowpath`. I examined `handle_mounts` because this calls `d_managed`. If `nd->flags & LOOKUP_RCU`, the code then reads `unsigned int seq = nd->next_seq;`. Then, the code checks `if (likely(!d_managed(dentry)))`. If `d_managed` returns true, then `__follow_mount_rcu` will be called. If a race caused `d_managed` to return the wrong value, since `DCACHE_MOUNTED | DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT` doesn't overlap with the bits being modified, the bitwise AND will yield the correct result. `d_managed` won't return a
|
| 35/2 |
2026/05/16 04:35 |
tool |
set-results |
0m
Args: map[DenialOfService:false Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:true VMGuestTrigger:true VMHostTrigger:false]
Results: map[DenialOfService:false Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:true UserNamespace:true VMGuestTrigger:true VMHostTrigger:false]
|
| 36/2 |
2026/05/16 04:35 |
llm |
expert |
0m
Model:
Tokens:
input: 36427
output: 724
thoughts: 246
Thoughts: **Analyzing the Benign Data Race in the VFS Subsystem**
Okay, the results are in, and it's time to craft the final explanation. My focus needs to be on framing this as a benign data race within the VFS subsystem. Specifically, it centers around how `d_make_discardable` and `d_managed` interact with the `dentry->d_flags` field.
The key lies in the fact that `d_make_discardable` is modifying `dentry->d_flags` to clear the `DCACHE_PERSISTENT` flag, and then `finish_dput` modifies other bits such as `DCACHE_DENTRY_KILLED`. Simultaneously, `d_managed` is reading `dentry->d_flags`, checking for the presence of `DCACHE_MANAGED_DENTRY`, which is composed of `DCACHE_MOUNTED`, `DCACHE_NEED_AUTOMOUNT`, and `DCACHE_MANAGE_TRANSIT`.
The important takeaway is that the bits `d_make_discardable` and `finish_dput` are writing, and the bits `d_managed` is reading, are entirely distinct. Further, since we're dealing with a 32-bit integer read/write, and this is atomic on all architectures we support, the reader will *always* see a consistent, correct state for the managed bits.
Therefore, despite the concurrent access, this particular data race poses no threat. There's no possibility of memory corruption, control flow hijacking, or even a denial-of-service condition arising from this interaction.
It's also worth noting that this race is accessible to unprivileged users. It can be triggered by concurrent operations like path lookups and file unlinking, especially in filesystems like tmpfs or shmem, making it relevant from a security perspective.
|
| 37/1 |
2026/05/16 04:36 |
action |
format-explanation |
0m
Results: map[Explanation:Based on the analysis of the provided KCSAN (Kernel Concurrency Sanitizer) bug
report and the kernel source code, here is the assessment of the bug:
### Bug Mechanism
The report highlights a data race on `dentry->d_flags` between a writer in
`d_make_discardable()` and a lockless reader in `d_managed()` (called during RCU
path walk via `step_into_slowpath()`).
1. **The Writer:** `d_make_discardable()` is called during the unlinking of a
file (e.g., in `shmem_unlink`). It modifies `dentry->d_flags` by clearing the
`DCACHE_PERSISTENT` bit (`BIT(27)`). Shortly after, `finish_dput()` is called,
which further modifies `d_flags` by setting `DCACHE_DENTRY_KILLED` (`BIT(14)`)
and clearing LRU/shrink list bits. These modifications are done while holding
the `dentry->d_lock`.
2. **The Reader:** `d_managed()` is called during a lockless RCU path walk. It
reads `dentry->d_flags` without holding the `d_lock` to check if any of the
`DCACHE_MANAGED_DENTRY` bits are set. `DCACHE_MANAGED_DENTRY` is defined as
`(DCACHE_MOUNTED | DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT)`, which
corresponds to `BIT(15)`, `BIT(16)`, and `BIT(17)`.
### Security Impact
**Not Exploitable & No Denial of Service:**
This is a classic, completely benign data race in the VFS subsystem.
- The bits being modified by the writer (`BIT(27)`, `BIT(14)`, etc.) are
strictly disjoint from the bits being checked by the reader (`BIT(15)`,
`BIT(16)`, `BIT(17)`).
- On all architectures supported by Linux, aligned 32-bit reads and writes are
atomic at the hardware level. The reader will never see a "torn" or corrupted
value that mixes up the bits.
- Regardless of whether `d_managed()` reads the `d_flags` just before or just
after the writer modifies the unrelated bits, the result of the bitwise AND
operation (`dentry->d_flags & DCACHE_MANAGED_DENTRY`) will remain perfectly
accurate.
- The VFS heavily relies on such lockless checks for performance during RCU path
walks. While it is technically undefined behavior in standard C (hence the KCSAN
report), it is practically safe and does not lead to memory corruption, crashes,
or incorrect control flow. Production kernels do not enable KCSAN, so this will
not even trigger a warning or panic in real-world environments.
### Reachability
- **Accessible From Unprivileged Processes / User Namespaces / VM Guests:** Yes.
Any unprivileged local user can easily trigger this race by having one thread
continuously unlink files (e.g., in a `tmpfs` or `shmem` mount) while another
thread concurrently performs path lookups (`readlink`, `open`, `stat`, etc.) on
the same paths.
- **Remote / Peripheral / Filesystem Trigger:** No. This is tied to local
syscall execution (`unlink` and `readlink`).]
|