| From: Jeongjun Park <aha310510@gmail.com> |
| Subject: mm: shmem: fix data-race in shmem_getattr() |
| Date: Mon, 9 Sep 2024 21:35:58 +0900 |
| |
| I got the following KCSAN report during syzbot testing: |
| |
| ================================================================== |
| BUG: KCSAN: data-race in generic_fillattr / inode_set_ctime_current |
| |
| write to 0xffff888102eb3260 of 4 bytes by task 6565 on cpu 1: |
| inode_set_ctime_to_ts include/linux/fs.h:1638 [inline] |
| inode_set_ctime_current+0x169/0x1d0 fs/inode.c:2626 |
| shmem_mknod+0x117/0x180 mm/shmem.c:3443 |
| shmem_create+0x34/0x40 mm/shmem.c:3497 |
| lookup_open fs/namei.c:3578 [inline] |
| open_last_lookups fs/namei.c:3647 [inline] |
| path_openat+0xdbc/0x1f00 fs/namei.c:3883 |
| do_filp_open+0xf7/0x200 fs/namei.c:3913 |
| do_sys_openat2+0xab/0x120 fs/open.c:1416 |
| do_sys_open fs/open.c:1431 [inline] |
| __do_sys_openat fs/open.c:1447 [inline] |
| __se_sys_openat fs/open.c:1442 [inline] |
| __x64_sys_openat+0xf3/0x120 fs/open.c:1442 |
| x64_sys_call+0x1025/0x2d60 arch/x86/include/generated/asm/syscalls_64.h:258 |
| do_syscall_x64 arch/x86/entry/common.c:52 [inline] |
| do_syscall_64+0x54/0x120 arch/x86/entry/common.c:83 |
| entry_SYSCALL_64_after_hwframe+0x76/0x7e |
| |
| read to 0xffff888102eb3260 of 4 bytes by task 3498 on cpu 0: |
| inode_get_ctime_nsec include/linux/fs.h:1623 [inline] |
| inode_get_ctime include/linux/fs.h:1629 [inline] |
| generic_fillattr+0x1dd/0x2f0 fs/stat.c:62 |
| shmem_getattr+0x17b/0x200 mm/shmem.c:1157 |
| vfs_getattr_nosec fs/stat.c:166 [inline] |
| vfs_getattr+0x19b/0x1e0 fs/stat.c:207 |
| vfs_statx_path fs/stat.c:251 [inline] |
| vfs_statx+0x134/0x2f0 fs/stat.c:315 |
| vfs_fstatat+0xec/0x110 fs/stat.c:341 |
| __do_sys_newfstatat fs/stat.c:505 [inline] |
| __se_sys_newfstatat+0x58/0x260 fs/stat.c:499 |
| __x64_sys_newfstatat+0x55/0x70 fs/stat.c:499 |
| x64_sys_call+0x141f/0x2d60 arch/x86/include/generated/asm/syscalls_64.h:263 |
| do_syscall_x64 arch/x86/entry/common.c:52 [inline] |
| do_syscall_64+0x54/0x120 arch/x86/entry/common.c:83 |
| entry_SYSCALL_64_after_hwframe+0x76/0x7e |
| |
| value changed: 0x2755ae53 -> 0x27ee44d3 |
| |
| Reported by Kernel Concurrency Sanitizer on: |
| CPU: 0 UID: 0 PID: 3498 Comm: udevd Not tainted 6.11.0-rc6-syzkaller-00326-gd1f2d51b711a-dirty #0 |
| Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/06/2024 |
| ================================================================== |
| |
| When calling generic_fillattr(), if you don't hold read lock, data-race |
| will occur in inode member variables, which can cause unexpected |
| behavior. |
| |
| Since there is no special protection when shmem_getattr() calls |
| generic_fillattr(), data-race occurs by functions such as shmem_unlink() |
| or shmem_mknod(). This can cause unexpected results, so commenting it out |
| is not enough. |
| |
| Therefore, when calling generic_fillattr() from shmem_getattr(), it is |
| appropriate to protect the inode using inode_lock_shared() and |
| inode_unlock_shared() to prevent data-race. |
| |
| Link: https://lkml.kernel.org/r/20240909123558.70229-1-aha310510@gmail.com |
| Fixes: 44a30220bc0a ("shmem: recalculate file inode when fstat") |
| Signed-off-by: Jeongjun Park <aha310510@gmail.com> |
| Reported-by: syzbot <syzkaller@googlegroup.com> |
| Cc: Hugh Dickins <hughd@google.com> |
| Cc: Yu Zhao <yuzhao@google.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/shmem.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| --- a/mm/shmem.c~mm-shmem-fix-data-race-in-shmem_getattr |
| +++ a/mm/shmem.c |
| @@ -1166,7 +1166,9 @@ static int shmem_getattr(struct mnt_idma |
| stat->attributes_mask |= (STATX_ATTR_APPEND | |
| STATX_ATTR_IMMUTABLE | |
| STATX_ATTR_NODUMP); |
| + inode_lock_shared(inode); |
| generic_fillattr(idmap, request_mask, inode, stat); |
| + inode_unlock_shared(inode); |
| |
| if (shmem_huge_global_enabled(inode, 0, 0, false, NULL, 0)) |
| stat->blksize = HPAGE_PMD_SIZE; |
| _ |