KCSAN: data-race in do_sendfile / ksys_write (18)

Status: moderation: reported on 2026/11/15 22:16
Subsystems: fs
Labels: prio:low race:benign
[Documentation on labels]
Reported-by: syzbot+c90ce048115ac34e85f3@syzkaller.appspotmail.com
First crash: 1h17m, last: 1h17m
✨ AI-generated root cause summary:

A data race occurs on struct file::f_pos between ksys_write() and do_sendfile(). In ksys_write(), accesses to fd_file(f)->f_pos are serialized under file->f_pos_lock acquired via CLASS(fd_pos, f)(fd) (fdget_pos()). In do_sendfile(), however, input and output files are obtained using CLASS(fd, ...), which uses plain fdget() without acquiring f_pos_lock. When sendfile64() is invoked with a NULL offset pointer (ppos == NULL), do_sendfile() directly writes fd_file(in)->f_pos without holding file->f_pos_lock, racing against concurrent write() operations sharing the same open file description.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit fa2933aac170:

Root Cause Analysis

1. Racing Object and Field

The reported data race occurs on struct file::f_pos (loff_t, byte offset 0x68 / 104 bytes in include/linux/fs.h:1280) on an open file description (struct file) shared between multiple threads.

The two racing execution paths are:

  • Task 4597: Executing write(2) via ksys_write() (fs/read_write.c:721):
    if (ret >= 0 && ppos)
        fd_file(f)->f_pos = pos;
    
  • Task 4599: Executing sendfile(2) / sendfile64(2) via do_sendfile() (fs/read_write.c:1369):
    if (retval > 0) {
        ...
        fd_file(out)->f_pos = out_pos;
        if (ppos)
            *ppos = pos;
        else
            fd_file(in)->f_pos = pos;
    }
    

2. Mechanism & Invariant Violation

For regular files (FMODE_ATOMIC_POS), POSIX and Linux VFS semantics require serialized updates to file->f_pos when the struct file is shared across threads:

  1. ksys_write() uses CLASS(fd_pos, f)(fd) (fs/read_write.c:710), which invokes fdget_pos() (fs/file.c:1406). Since the file is shared (__file_ref_read_raw(&file->f_ref) != FILE_REF_ONEREF), file_needs_f_pos_lock(file) returns true, and mutex_lock(&file->f_pos_lock) is acquired for the duration of the write. At line 721, fd_file(f)->f_pos is written while holding f_pos_lock.
  2. do_sendfile() (fs/read_write.c:1283-1377) resolves its file descriptors using CLASS(fd, in)(in_fd) and CLASS(fd, out)(out_fd) (include/linux/file.h:84), which resolve to standard fdget() calls without acquiring file->f_pos_lock on either the input or output file.
  3. When sendfile64(out_fd, in_fd, offset, count) is called with offset == NULL (fs/read_write.c:1412), do_sendfile() is passed ppos = NULL. In this mode, do_sendfile() reads fd_file(in)->f_pos at line 1302 and writes the updated position back to fd_file(in)->f_pos at line 1369.

Because do_sendfile() does not acquire f_pos_lock (or use atomic accessors), its store to fd_file(in)->f_pos directly races with the store in ksys_write() whenever in_fd in sendfile64() refers to the same underlying struct file being concurrently written by ksys_write().

▶ ▼ ✨ AI Jobs (2)
ID Workflow Result Correct Bug Created Started Finished Revision
790db12b assessment-kcsan Benign: ✅ ❓ KCSAN: data-race in do_sendfile / ksys_write (18) 2026/11/15 21:44 2026/11/15 21:44 2026/11/15 22:30 819ebe34
952e9d7c assessment-security DenialOfService: ❌ Exploitable: ❌ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ❌ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ✅ UserNamespace: ✅ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ KCSAN: data-race in do_sendfile / ksys_write (18) 2026/11/15 21:44 2026/11/15 21:44 2026/11/15 22:12 819ebe34
▶ ▼ Similar bugs (17)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
upstream KCSAN: data-race in do_sendfile / ksys_write (17) fs 6 1 265d 265d 0/29 auto-obsoleted due to no activity on 2026/04/20 09:50
upstream KCSAN: data-race in do_sendfile / ksys_write (16) fs 6 1 936d 936d 0/29 auto-obsoleted due to no activity on 2024/05/28 12:59
upstream KCSAN: data-race in do_sendfile / ksys_write (5) fs 6 1 2126d 2126d 0/29 auto-closed as invalid on 2021/02/23 08:15
upstream KCSAN: data-race in do_sendfile / ksys_write (7) fs 6 3 1757d 1781d 0/29 auto-closed as invalid on 2022/02/27 04:59
upstream KCSAN: data-race in do_sendfile / ksys_write (8) fs 6 1 1717d 1717d 0/29 auto-closed as invalid on 2022/04/08 18:00
upstream KCSAN: data-race in do_sendfile / ksys_write (12) fs 6 2 1246d 1259d 0/29 auto-obsoleted due to no activity on 2023/07/23 08:25
upstream KCSAN: data-race in do_sendfile / ksys_write (15) fs 6 1 996d 996d 0/29 auto-obsoleted due to no activity on 2024/03/29 14:30
upstream KCSAN: data-race in do_sendfile / ksys_write fs 6 1 2569d 2569d 0/29 closed as invalid on 2019/11/19 13:24
upstream KCSAN: data-race in do_sendfile / ksys_write (14) fs 6 2 1071d 1070d 0/29 auto-obsoleted due to no activity on 2024/01/14 07:58
upstream KCSAN: data-race in do_sendfile / ksys_write (13) fs 6 5 1139d 1196d 0/29 auto-obsoleted due to no activity on 2023/11/07 08:57
upstream KCSAN: data-race in do_sendfile / ksys_write (2) fs 6 2 2452d 2515d 0/29 auto-closed as invalid on 2020/05/08 04:57
upstream KCSAN: data-race in do_sendfile / ksys_write (6) fs 6 1 2059d 2059d 0/29 auto-closed as invalid on 2021/05/17 10:56
upstream KCSAN: data-race in do_sendfile / ksys_write (4) fs 6 1 2162d 2162d 0/29 auto-closed as invalid on 2021/01/18 19:47
upstream KCSAN: data-race in do_sendfile / ksys_write (10) fs 6 1 1576d 1576d 0/29 auto-closed as invalid on 2022/08/27 13:39
upstream KCSAN: data-race in do_sendfile / ksys_write (3) fs 6 1 2235d 2235d 0/29 auto-closed as invalid on 2020/11/06 02:13
upstream KCSAN: data-race in do_sendfile / ksys_write (9) fs 6 2 1658d 1661d 0/29 auto-closed as invalid on 2022/06/06 18:20
upstream KCSAN: data-race in do_sendfile / ksys_write (11) fs 6 1 1509d 1509d 0/29 auto-obsoleted due to no activity on 2022/11/02 18:18

Sample crash report:
==================================================================
BUG: KCSAN: data-race in do_sendfile / ksys_write

write to 0xffff88810cdaa068 of 8 bytes by task 4597 on cpu 1:
 ksys_write+0x11c/0x1a0 fs/read_write.c:721
 __do_sys_write fs/read_write.c:730 [inline]
 __se_sys_write fs/read_write.c:727 [inline]
 __x64_sys_write+0x40/0x50 fs/read_write.c:727
 x64_sys_call+0x154e/0x2550 arch/x86/include/generated/asm/syscalls_64.h:2
 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
 do_syscall_64+0x121/0x390 arch/x86/entry/syscall_64.c:89
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

write to 0xffff88810cdaa068 of 8 bytes by task 4599 on cpu 0:
 do_sendfile+0x44c/0x640 fs/read_write.c:1369
 __do_sys_sendfile64 fs/read_write.c:1412 [inline]
 __se_sys_sendfile64 fs/read_write.c:1398 [inline]
 __x64_sys_sendfile64+0x105/0x150 fs/read_write.c:1398
 x64_sys_call+0x1015/0x2550 arch/x86/include/generated/asm/syscalls_64.h:41
 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
 do_syscall_64+0x121/0x390 arch/x86/entry/syscall_64.c:89
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

value changed: 0x0000000000000000 -> 0x0000000000e08e80

Reported by Kernel Concurrency Sanitizer on:
CPU: 0 UID: 0 PID: 4599 Comm: syz.3.333 Not tainted syzkaller #0 PREEMPT(lazy) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/06/2026
==================================================================

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/15 21:44 upstream fa2933aac170 819ebe34 .config console log report info [disk image] [vmlinux] [kernel image] ci2-upstream-kcsan-gce KCSAN: data-race in do_sendfile / ksys_write
* Struck through repros no longer work on HEAD.