Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null pointer dereference with mv #3

Open
hayley-leblanc opened this issue Jan 26, 2024 · 0 comments
Open

Null pointer dereference with mv #3

hayley-leblanc opened this issue Jan 26, 2024 · 0 comments
Labels
help wanted Extra attention is needed

Comments

@hayley-leblanc
Copy link
Collaborator

Just using rename seems to work fine, but the mv utility uses multiple calls to rename and renameat2 in a way that causes problems.

To reproduce:

$ sudo mkdir /mnt/pmem/A; sudo mkdir /mnt/pmem/B; sudo mkdir /mnt/pmem/C; sudo touch /mnt/pmem/A/foo; sudo touch /mnt/pmem/A/bar; sudo strace mv /mnt/pmem/A/foo /mnt/pmem/B/foo

dmesg output:

[   30.965473] BUG: kernel NULL pointer dereference, address: 0000000000000040
[   30.965477] #PF: supervisor read access in kernel mode
[   30.965479] #PF: error_code(0x0000) - not-present page
[   30.965480] PGD 0 P4D 0 
[   30.965482] Oops: 0000 [#1] PREEMPT SMP NOPTI
[   30.965484] CPU: 8 PID: 2026 Comm: mv Not tainted 6.3.0+ #170
[   30.965485] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[   30.965487] RIP: 0010:_RNvMs1_NtCslRB4dZEOnGX_5super4defsNtB5_6SbInfo31get_init_reg_inode_by_vfs_inode+0xa/0x190 [hayleyfs]
[   30.965494] Code: c7 43 04 ea ff ff ff b8 01 00 00 00 89 03 48 89 d8 48 83 c4 50 5b c3 66 0f 1f 84 00 00 00 00 00 41 56 53 48 83 ec 58 48 89 fb <48> 8b 42 40 48 89 44 24 18 48 85 c0 74 5a 48 3b 86 b8 00 00 00 73
[   30.965496] RSP: 0018:ffffc900010878d8 EFLAGS: 00010296
[   30.965497] RAX: 0000000000000000 RBX: ffffc90001087948 RCX: bdc8e033978c8000
[   30.965499] RDX: 0000000000000000 RSI: ffff888180ddb700 RDI: ffffc90001087948
[   30.965501] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffffff82684220
[   30.965504] R10: 0000000000000000 R11: 00000000ffffdfff R12: 0000000000000005
[   30.965505] R13: ffff8881816e7440 R14: ffff8881be6946f8 R15: 0000000000000004
[   30.965506] FS:  00007fc841829800(0000) GS:ffff888629c00000(0000) knlGS:0000000000000000
[   30.965507] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   30.965508] CR2: 0000000000000040 CR3: 00000001c7a06001 CR4: 0000000000770ee0
[   30.965511] PKRU: 55555554
[   30.965512] Call Trace:
[   30.965514]  <TASK>
[   30.965515]  ? _printk+0x58/0x80
[   30.965518]  _RNvXNtCslRB4dZEOnGX_5super5nameiNtB2_8InodeOpsNtNtCs8YfjL7j61RY_6kernel5inode10Operations6rename+0xb45/0x31e0 [hayleyfs]
[   30.965524]  _RNvMNtCs8YfjL7j61RY_6kernel5inodeINtB2_16OperationsVtableNtNtCslRB4dZEOnGX_5super5namei8InodeOpsE15rename_callbackBX_+0x6/0x20 [hayleyfs]
[   30.965528]  vfs_rename+0x432/0x590
[   30.965534]  ? d_lookup+0x29/0x40
[   30.965537]  do_renameat2+0x332/0x530
[   30.965538]  __x64_sys_rename+0x3f/0x50
[   30.965540]  do_syscall_64+0x45/0x90
[   30.965545]  ? exit_to_user_mode_prepare+0x2b/0x80
[   30.965547]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
[   30.965554] RIP: 0033:0x7fc841661eab
[   30.965555] Code: e8 6a 44 0b 00 f7 d8 19 c0 5d c3 0f 1f 40 00 b8 ff ff ff ff 5d c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa b8 52 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 05 c3 0f 1f 40 00 48 8b 15 51 6f 1b 00 f7 d8
[   30.965556] RSP: 002b:00007ffc2836d548 EFLAGS: 00000246 ORIG_RAX: 0000000000000052
[   30.965558] RAX: ffffffffffffffda RBX: 00007ffc2836dac0 RCX: 00007fc841661eab
[   30.965559] RDX: 0000000000000005 RSI: 00007ffc2836e8c9 RDI: 00007ffc2836e8b9
[   30.965560] RBP: 00007ffc2836d900 R08: 00007ffc2836d680 R09: 00007ffc2836dac0
[   30.965561] R10: 0000000000000100 R11: 0000000000000246 R12: 0000000000000011
[   30.965562] R13: 0000000000000000 R14: 00007ffc2836e8c9 R15: 0000000000000001
[   30.965563]  </TASK>
[   30.965564] Modules linked in: hayleyfs nd_pmem nd_btt
[   30.965568] CR2: 0000000000000040
[   30.965569] ---[ end trace 0000000000000000 ]---
[   30.965571] RIP: 0010:_RNvMs1_NtCslRB4dZEOnGX_5super4defsNtB5_6SbInfo31get_init_reg_inode_by_vfs_inode+0xa/0x190 [hayleyfs]
[   30.965576] Code: c7 43 04 ea ff ff ff b8 01 00 00 00 89 03 48 89 d8 48 83 c4 50 5b c3 66 0f 1f 84 00 00 00 00 00 41 56 53 48 83 ec 58 48 89 fb <48> 8b 42 40 48 89 44 24 18 48 85 c0 74 5a 48 3b 86 b8 00 00 00 73
[   30.965578] RSP: 0018:ffffc900010878d8 EFLAGS: 00010296
[   30.965580] RAX: 0000000000000000 RBX: ffffc90001087948 RCX: bdc8e033978c8000
[   30.965581] RDX: 0000000000000000 RSI: ffff888180ddb700 RDI: ffffc90001087948
[   30.965582] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffffff82684220
[   30.965583] R10: 0000000000000000 R11: 00000000ffffdfff R12: 0000000000000005
[   30.965584] R13: ffff8881816e7440 R14: ffff8881be6946f8 R15: 0000000000000004
[   30.965585] FS:  00007fc841829800(0000) GS:ffff888629c00000(0000) knlGS:0000000000000000
[   30.965586] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   30.965587] CR2: 0000000000000040 CR3: 00000001c7a06001 CR4: 0000000000770ee0
[   30.965589] PKRU: 55555554

Output from strace:

execve("/usr/bin/mv", ["mv", "/mnt/pmem/A/foo", "/mnt/pmem/B/foo"], 0x7ffdd0d33710 /* 13 vars */) = 0
brk(NULL)                               = 0x5631519a0000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffc2836db30) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc841912000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=58827, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 58827, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc841903000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=166280, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 177672, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc8418d7000
mprotect(0x7fc8418dd000, 139264, PROT_NONE) = 0
mmap(0x7fc8418dd000, 106496, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7fc8418dd000
mmap(0x7fc8418f7000, 28672, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x20000) = 0x7fc8418f7000
mmap(0x7fc8418ff000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x27000) = 0x7fc8418ff000
mmap(0x7fc841901000, 5640, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc841901000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=34888, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 36896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc8418cd000
mprotect(0x7fc8418cf000, 24576, PROT_NONE) = 0
mmap(0x7fc8418cf000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7fc8418cf000
mmap(0x7fc8418d3000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7fc8418d3000
mmap(0x7fc8418d5000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7000) = 0x7fc8418d5000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=26696, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 28696, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc8418c5000
mmap(0x7fc8418c7000, 12288, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7fc8418c7000
mmap(0x7fc8418ca000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0x7fc8418ca000
mmap(0x7fc8418cb000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0x7fc8418cb000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\244;\374\204(\337f#\315I\214\234\f\256\271\32"..., 68, 896) = 68
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2216304, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2260560, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc841600000
mmap(0x7fc841628000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7fc841628000
mmap(0x7fc8417bd000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fc8417bd000
mmap(0x7fc841815000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7fc841815000
mmap(0x7fc84181b000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc84181b000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=613064, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 615184, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc84182e000
mmap(0x7fc841830000, 438272, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7fc841830000
mmap(0x7fc84189b000, 163840, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6d000) = 0x7fc84189b000
mmap(0x7fc8418c3000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x94000) = 0x7fc8418c3000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc84182c000
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc841829000
arch_prctl(ARCH_SET_FS, 0x7fc841829800) = 0
set_tid_address(0x7fc841829ad0)         = 2026
set_robust_list(0x7fc841829ae0, 24)     = 0
rseq(0x7fc84182a1a0, 0x20, 0, 0x53053053) = 0
mprotect(0x7fc841815000, 16384, PROT_READ) = 0
mprotect(0x7fc8418c3000, 4096, PROT_READ) = 0
mprotect(0x7fc8418cb000, 4096, PROT_READ) = 0
mprotect(0x7fc8418d5000, 4096, PROT_READ) = 0
mprotect(0x7fc8418ff000, 4096, PROT_READ) = 0
mprotect(0x563150c61000, 4096, PROT_READ) = 0
mprotect(0x7fc84194c000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7fc841903000, 58827)           = 0
statfs("/sys/fs/selinux", {f_type=SELINUX_MAGIC, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NOEXEC|ST_RELATIME}) = 0
statfs("/sys/fs/selinux", {f_type=SELINUX_MAGIC, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NOEXEC|ST_RELATIME}) = 0
getrandom("\xb8\xa3\x8e\x1e\xfc\x66\x5a\x32", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x5631519a0000
brk(0x5631519c1000)                     = 0x5631519c1000
access("/etc/selinux/config", F_OK)     = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=5712208, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 5712208, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc841000000
close(3)                                = 0
geteuid()                               = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
renameat2(AT_FDCWD, "/mnt/pmem/A/foo", AT_FDCWD, "/mnt/pmem/B/foo", RENAME_NOREPLACE) = -1 EEXIST (File exists)
newfstatat(AT_FDCWD, "/mnt/pmem/B/foo", 0x7ffc2836db10, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/mnt/pmem/A/foo", {st_mode=S_IFREG|0644, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "/mnt/pmem/B/foo", 0x7ffc2836d680, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
geteuid()                               = 0
rename("/mnt/pmem/A/foo", "/mnt/pmem/B/foo") = ?
+++ killed by SIGKILL +++

The null pointer appears to be the inode in the /mnt/pmem/B/foo (?) directory entry. Prior renameat2 calls shouldn't have deleted this inode since they return an error, but it may be happening anyway?

@vijay03 vijay03 added the help wanted Extra attention is needed label Jul 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants