syzbot |
sign-in | mailing list | source | docs |
| ID | Workflow | Result | Correct | Bug | Created | Started | Finished | Revision | Error |
|---|---|---|---|---|---|---|---|---|---|
| 7005ffbc-3cd2-4306-a9e6-4334035f959a | assessment-kcsan | Benign: ✅ | ❓ | KCSAN: data-race in pipe_release / pipe_wait_readable (10) | 2026/01/12 15:06 | 2026/01/12 15:06 | 2026/01/12 15:28 | dc57dbf3ee402bd8ad9c3037d56ee9d9940a9bc6 |
The KCSAN report indicates a data race on `pipe->files` between `pipe_release` (writer) and `pipe_wait_readable` -> `pipe_lock` (reader).
**Analysis:**
1. **Consistency:** The report is consistent. The stack traces point to `fs/pipe.c`.
* **Writer:** `pipe_release` calls `put_pipe_info`, which decrements `pipe->files` under `inode->i_lock` (Line 713/714 in `fs/pipe.c`).
* **Reader:** `pipe_wait_readable` calls `pipe_lock`. `pipe_lock` reads `pipe->files` to check if it is non-zero before locking `pipe->mutex` (Line 89 in `fs/pipe.c`).
* The accessed address matches `pipe->files` (offset within `struct pipe_inode_info`).
* The value change `2 -> 1` corresponds to closing one end of the pipe while another end is still open (or held).
2. **Benign vs. Harmful:**
* The variable `pipe->files` counts the number of open file objects referring to the pipe.
* The `pipe_lock` function checks `if (pipe->files)` before acquiring the mutex. This check appears to be an optimization or a sanity check.
* In the reported trace, `pipe_wait_readable` is called from `splice_from_pipe_next`. This path implies that the caller holds a reference to a `struct file` associated with the pipe (the input file for splice).
* Since the caller holds a file reference, `pipe->files` must be at least 1 (accounting for that file).
* The race occurs when another file referring to the same pipe is closed (decrementing `pipe->files` from 2 to 1).
* In this scenario, `pipe->files` remains non-zero. The reader (`pipe_lock`) will see either 2 or 1. In both cases, the condition `if (pipe->files)` evaluates to true, and the function proceeds to acquire the mutex.
* The `pipe` structure is freed only when `pipe->files` drops to 0. Since the reader holds a reference, `pipe->files` cannot drop to 0 during this access, ensuring the `pipe` structure remains valid and no use-after-free occurs.
* Therefore, the outcome of the function execution is identical regardless of the race ordering. The race does not lead to corruption, inconsistent state, or logical errors.
**Conclusion:**
The data race is **benign**. The read of `pipe->files` in `pipe_lock` is racy but safe because the existence of a reference held by the caller guarantees the value is non-zero, making the check always true and the subsequent locking action deterministic. The redundant check `if (pipe->files)` could be removed or annotated to silence the warning, but the race itself is not harmful.================================================================== BUG: KCSAN: data-race in pipe_release / pipe_wait_readable read-write to 0xffff88810d02796c of 4 bytes by task 5305 on cpu 0: put_pipe_info fs/pipe.c:714 [inline] pipe_release+0x16a/0x1d0 fs/pipe.c:744 __fput+0x29b/0x650 fs/file_table.c:468 ____fput+0x1c/0x30 fs/file_table.c:496 task_work_run+0x131/0x1a0 kernel/task_work.c:233 resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] __exit_to_user_mode_loop kernel/entry/common.c:44 [inline] exit_to_user_mode_loop+0x1fe/0x740 kernel/entry/common.c:75 __exit_to_user_mode_prepare include/linux/irq-entry-common.h:226 [inline] syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:256 [inline] syscall_exit_to_user_mode_work include/linux/entry-common.h:159 [inline] syscall_exit_to_user_mode include/linux/entry-common.h:194 [inline] do_syscall_64+0x1dd/0x2b0 arch/x86/entry/syscall_64.c:100 entry_SYSCALL_64_after_hwframe+0x77/0x7f read to 0xffff88810d02796c of 4 bytes by task 5306 on cpu 1: pipe_lock fs/pipe.c:90 [inline] pipe_wait_readable+0x1c2/0x210 fs/pipe.c:1077 splice_from_pipe_next+0x220/0x380 fs/splice.c:544 iter_file_splice_write+0x1b1/0xa20 fs/splice.c:693 do_splice_from fs/splice.c:938 [inline] do_splice+0x972/0x10b0 fs/splice.c:1351 __do_splice fs/splice.c:1433 [inline] __do_sys_splice fs/splice.c:1636 [inline] __se_sys_splice+0x26c/0x3a0 fs/splice.c:1618 __x64_sys_splice+0x78/0x90 fs/splice.c:1618 x64_sys_call+0x2e82/0x3000 arch/x86/include/generated/asm/syscalls_64.h:276 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xca/0x2b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f value changed: 0x00000002 -> 0x00000001 Reported by Kernel Concurrency Sanitizer on: CPU: 1 UID: 0 PID: 5306 Comm: syz.0.612 Not tainted syzkaller #0 PREEMPT(voluntary) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025 ==================================================================
| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/01/12 15:06 | flow | assessment-kcsan |
21mModel:unknown Results: map[Benign:true Explanation:The KCSAN report indicates a data race on `pipe->files` between `pipe_release` (writer) and `pipe_wait_readable` -> `pipe_lock` (reader).
**Analysis:**
1. **Consistency:** The report is consistent. The stack traces point to `fs/pipe.c`.
* **Writer:** `pipe_release` calls `put_pipe_info`, which decrements `pipe->files` under `inode->i_lock` (Line 713/714 in `fs/pipe.c`).
* **Reader:** `pipe_wait_readable` calls `pipe_lock`. `pipe_lock` reads `pipe->files` to check if it is non-zero before locking `pipe->mutex` (Line 89 in `fs/pipe.c`).
* The accessed address matches `pipe->files` (offset within `struct pipe_inode_info`).
* The value change `2 -> 1` corresponds to closing one end of the pipe while another end is still open (or held).
2. **Benign vs. Harmful:**
* The variable `pipe->files` counts the number of open file objects referring to the pipe.
* The `pipe_lock` function checks `if (pipe->files)` before acquiring the mutex. This check appears to be an optimization or a sanity check.
* In the reported trace, `pipe_wait_readable` is called from `splice_from_pipe_next`. This path implies that the caller holds a reference to a `struct file` associated with the pipe (the input file for splice).
* Since the caller holds a file reference, `pipe->files` must be at least 1 (accounting for that file).
* The race occurs when another file referring to the same pipe is closed (decrementing `pipe->files` from 2 to 1).
* In this scenario, `pipe->files` remains non-zero. The reader (`pipe_lock`) will see either 2 or 1. In both cases, the condition `if (pipe->files)` evaluates to true, and the function proceeds to acquire the mutex.
* The `pipe` structure is freed only when `pipe->files` drops to 0. Since the reader holds a reference, `pipe->files` cannot drop to 0 during this access, ensuring the `pipe` structure remains valid and no use-after-free occurs.
* Therefore, the outcome of the function execution is identical regardless of the race ordering. The race does not lead to corruption, inconsistent state, or logical errors.
**Conclusion:**
The data race is **benign**. The read of `pipe->files` in `pipe_lock` is racy but safe because the existence of a reference held by the caller guarantees the value is non-zero, making the check always true and the subsequent locking action deterministic. The redundant check `if (pipe->files)` could be removed or annotated to silence the warning, but the race itself is not harmful.] |
| 1/1 | 2026/01/12 15:06 | action | kernel-checkouter |
0mModel:unknown Results: map[KernelSrc:/usr/local/google/home/dvyukov/syzkaller/agent/workdir/cache/src/5d240f2140874f6657aee9957ead4428b65a3a7d] |
| 2/1 | 2026/01/12 15:07 | action | kernel-builder |
3mModel:unknown Results: map[KernelObj:/usr/local/google/home/dvyukov/syzkaller/agent/workdir/cache/build/7a2e2b5e87cdeb02007ac751242ddff9c6a45c7d] |
| 3/1 | 2026/01/12 15:11 | action | codesearch-prepare |
12mModel:unknown Results: map[Index:codesearch-index] |
| 4/1 | 2026/01/12 15:24 | agent | expert |
3mModel:unknown Results: map[Benign:true] Instruction: You are an experienced Linux kernel developer tasked with determining if the given kernel bug report is actionable or not. Actionable means that it contains enough info to root cause the underlying bug, and that the report is self-consistent and makes sense, rather than a one-off nonsensical crash induced by a previous memory corruption. Use the provided tools to confirm any assumptions, what variables/fields being accessed, etc. In particular, don't make assumptions about the kernel source code, use codesearch tools to read the actual source code. The bug report is a data race report from KCSAN tool. It contains 2 stack traces of the memory accesses that constitute a data race. The report would be inconsistent, if the stacks point to different subsystems, or if they access different fields. The report would be non-actionable, if the underlysing data race is "benign". That is, the race is on a simple int/bool or similar field, and the accesses are not supposed to be protected by any mutual exclusion primitives. Common examples of such "benign" data races are accesses to various flags fields, statistics counters, and similar. An actionable race is "harmful", that is can lead to corruption/crash even with a conservative compiler that compiles memory accesses to primitive types effectively as atomic. A common example of a "harmful" data races is race on a complex container (list/hashmap/etc), where accesses are supposed to be protected by a mutual exclusion primitive. In the final reply explain why you think the report is consistent and the data race is harmful. 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 bug report is: ================================================================== BUG: KCSAN: data-race in pipe_release / pipe_wait_readable read-write to 0xffff88810d02796c of 4 bytes by task 5305 on cpu 0: put_pipe_info fs/pipe.c:714 [inline] pipe_release+0x16a/0x1d0 fs/pipe.c:744 __fput+0x29b/0x650 fs/file_table.c:468 ____fput+0x1c/0x30 fs/file_table.c:496 task_work_run+0x131/0x1a0 kernel/task_work.c:233 resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] __exit_to_user_mode_loop kernel/entry/common.c:44 [inline] exit_to_user_mode_loop+0x1fe/0x740 kernel/entry/common.c:75 __exit_to_user_mode_prepare include/linux/irq-entry-common.h:226 [inline] syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:256 [inline] syscall_exit_to_user_mode_work include/linux/entry-common.h:159 [inline] syscall_exit_to_user_mode include/linux/entry-common.h:194 [inline] do_syscall_64+0x1dd/0x2b0 arch/x86/entry/syscall_64.c:100 entry_SYSCALL_64_after_hwframe+0x77/0x7f read to 0xffff88810d02796c of 4 bytes by task 5306 on cpu 1: pipe_lock fs/pipe.c:90 [inline] pipe_wait_readable+0x1c2/0x210 fs/pipe.c:1077 splice_from_pipe_next+0x220/0x380 fs/splice.c:544 iter_file_splice_write+0x1b1/0xa20 fs/splice.c:693 do_splice_from fs/splice.c:938 [inline] do_splice+0x972/0x10b0 fs/splice.c:1351 __do_splice fs/splice.c:1433 [inline] __do_sys_splice fs/splice.c:1636 [inline] __se_sys_splice+0x26c/0x3a0 fs/splice.c:1618 __x64_sys_splice+0x78/0x90 fs/splice.c:1618 x64_sys_call+0x2e82/0x3000 arch/x86/include/generated/asm/syscalls_64.h:276 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xca/0x2b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f value changed: 0x00000002 -> 0x00000001 Reported by Kernel Concurrency Sanitizer on: CPU: 1 UID: 0 PID: 5306 Comm: syz.0.612 Not tainted syzkaller #0 PREEMPT(voluntary) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025 ================================================================== Reply: The KCSAN report indicates a data race on `pipe->files` between `pipe_release` (writer) and `pipe_wait_readable` -> `pipe_lock` (reader).
**Analysis:**
1. **Consistency:** The report is consistent. The stack traces point to `fs/pipe.c`.
* **Writer:** `pipe_release` calls `put_pipe_info`, which decrements `pipe->files` under `inode->i_lock` (Line 713/714 in `fs/pipe.c`).
* **Reader:** `pipe_wait_readable` calls `pipe_lock`. `pipe_lock` reads `pipe->files` to check if it is non-zero before locking `pipe->mutex` (Line 89 in `fs/pipe.c`).
* The accessed address matches `pipe->files` (offset within `struct pipe_inode_info`).
* The value change `2 -> 1` corresponds to closing one end of the pipe while another end is still open (or held).
2. **Benign vs. Harmful:**
* The variable `pipe->files` counts the number of open file objects referring to the pipe.
* The `pipe_lock` function checks `if (pipe->files)` before acquiring the mutex. This check appears to be an optimization or a sanity check.
* In the reported trace, `pipe_wait_readable` is called from `splice_from_pipe_next`. This path implies that the caller holds a reference to a `struct file` associated with the pipe (the input file for splice).
* Since the caller holds a file reference, `pipe->files` must be at least 1 (accounting for that file).
* The race occurs when another file referring to the same pipe is closed (decrementing `pipe->files` from 2 to 1).
* In this scenario, `pipe->files` remains non-zero. The reader (`pipe_lock`) will see either 2 or 1. In both cases, the condition `if (pipe->files)` evaluates to true, and the function proceeds to acquire the mutex.
* The `pipe` structure is freed only when `pipe->files` drops to 0. Since the reader holds a reference, `pipe->files` cannot drop to 0 during this access, ensuring the `pipe` structure remains valid and no use-after-free occurs.
* Therefore, the outcome of the function execution is identical regardless of the race ordering. The race does not lead to corruption, inconsistent state, or logical errors.
**Conclusion:**
The data race is **benign**. The read of `pipe->files` in `pipe_lock` is racy but safe because the existence of a reference held by the caller guarantees the value is non-zero, making the check always true and the subsequent locking action deterministic. The redundant check `if (pipe->files)` could be removed or annotated to silence the warning, but the race itself is not harmful. |
| 5/2 | 2026/01/12 15:24 | llm | expert |
0mModel:unknown |
| 6/2 | 2026/01/12 15:24 | tool | codesearch-definition-source |
0mModel:unknown Args: map[IncludeLines:true Name:put_pipe_info SourceFile:fs/pipe.c] Results: map[Missing:false SourceCode: 708: static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
709: {
710: int kill = 0;
711:
712: spin_lock(&inode->i_lock);
713: if (!--pipe->files) {
714: inode->i_pipe = NULL;
715: kill = 1;
716: }
717: spin_unlock(&inode->i_lock);
718:
719: if (kill)
720: free_pipe_info(pipe);
721: }
SourceFile:fs/pipe.c] |
| 7/2 | 2026/01/12 15:24 | tool | codesearch-definition-source |
0mModel:unknown Args: map[IncludeLines:true Name:pipe_lock SourceFile:fs/pipe.c] Results: map[Missing:false SourceCode: 87: void pipe_lock(struct pipe_inode_info *pipe)
88: {
89: if (pipe->files)
90: mutex_lock(&pipe->mutex);
91: }
SourceFile:fs/pipe.c] |
| 8/2 | 2026/01/12 15:24 | llm | expert |
0mModel:unknown |
| 9/2 | 2026/01/12 15:24 | tool | codesearch-definition-source |
0mModel:unknown Args: map[IncludeLines:false Name:pipe_inode_info SourceFile:include/linux/pipe_fs_i.h] Results: map[Missing:true SourceCode: SourceFile:] |
| 10/2 | 2026/01/12 15:25 | llm | expert |
0mModel:unknown |
| 11/2 | 2026/01/12 15:25 | tool | codesearch-definition-source |
0mModel:unknown Args: map[IncludeLines:true Name:pipe_wait_readable SourceFile:fs/pipe.c] Results: map[Missing:false SourceCode:1063: /*
1064: * This is the stupid "wait for pipe to be readable or writable"
1065: * model.
1066: *
1067: * See pipe_read/write() for the proper kind of exclusive wait,
1068: * but that requires that we wake up any other readers/writers
1069: * if we then do not end up reading everything (ie the whole
1070: * "wake_next_reader/writer" logic in pipe_read/write()).
1071: */
1072: void pipe_wait_readable(struct pipe_inode_info *pipe)
1073: {
1074: pipe_unlock(pipe);
1075: wait_event_interruptible(pipe->rd_wait, pipe_readable(pipe));
1076: pipe_lock(pipe);
1077: }
SourceFile:fs/pipe.c] |
| 12/2 | 2026/01/12 15:25 | llm | expert |
0mModel:unknown |
| 13/2 | 2026/01/12 15:25 | tool | codesearch-file-index |
0mModel:unknown Args: map[SourceFile:include/linux/pipe_fs_i.h] Results: map[Entities:[map[Kind:function Name:account_pipe_buffers] map[Kind:function Name:alloc_pipe_info] map[Kind:function Name:create_pipe_files] map[Kind:function Name:free_pipe_info] map[Kind:function Name:generic_pipe_buf_get] map[Kind:function Name:generic_pipe_buf_release] map[Kind:function Name:generic_pipe_buf_try_steal] map[Kind:function Name:get_pipe_info] map[Kind:function Name:pipe_buf] map[Kind:function Name:pipe_buf_confirm] map[Kind:function Name:pipe_buf_get] map[Kind:function Name:pipe_buf_release] map[Kind:function Name:pipe_buf_try_steal] map[Kind:function Name:pipe_buf_usage] map[Kind:function Name:pipe_double_lock] map[Kind:function Name:pipe_empty] map[Kind:function Name:pipe_fcntl] map[Kind:function Name:pipe_full] map[Kind:function Name:pipe_has_watch_queue] map[Kind:function Name:pipe_head_buf] map[Kind:function Name:pipe_is_empty] map[Kind:function Name:pipe_is_full] map[Kind:function Name:pipe_is_unprivileged_user] map[Kind:function Name:pipe_lock] map[Kind:function Name:pipe_occupancy] map[Kind:function Name:pipe_resize_ring] map[Kind:function Name:pipe_unlock] map[Kind:function Name:pipe_wait_readable] map[Kind:function Name:pipe_wait_writable] map[Kind:function Name:round_pipe_size] map[Kind:function Name:too_many_pipe_buffers_hard] map[Kind:function Name:too_many_pipe_buffers_soft]] Missing:false] |
| 14/2 | 2026/01/12 15:25 | llm | expert |
0mModel:unknown |
| 15/2 | 2026/01/12 15:25 | tool | codesearch-definition-source |
0mModel:unknown Args: map[IncludeLines:true Name:alloc_pipe_info SourceFile:include/linux/pipe_fs_i.h] Results: map[Missing:false SourceCode: 314: struct pipe_inode_info *alloc_pipe_info(void); SourceFile:include/linux/pipe_fs_i.h] |
| 16/2 | 2026/01/12 15:25 | llm | expert |
0mModel:unknown |
| 17/2 | 2026/01/12 15:26 | tool | codesearch-definition-source |
0mModel:unknown Args: map[IncludeLines:true Name:pipe_lock SourceFile:include/linux/pipe_fs_i.h] Results: map[Missing:false SourceCode: 305: /* Pipe lock and unlock operations */ 306: void pipe_lock(struct pipe_inode_info *); SourceFile:include/linux/pipe_fs_i.h] |
| 18/2 | 2026/01/12 15:26 | llm | expert |
1mModel:unknown |
| 19/2 | 2026/01/12 15:27 | tool | set-results |
0mModel:unknown Args: map[Benign:true] Results: map[Benign:true] |
| 20/2 | 2026/01/12 15:27 | llm | expert |
0mModel:unknown |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|