google / kmsan

KernelMemorySanitizer, a detector of uses of uninitialized memory in the Linux kernel
Other
406 stars 62 forks source link

BUG: KMSAN: uninit-value in kmsan_handle_dma #76

Closed SunHao-0 closed 4 years ago

SunHao-0 commented 4 years ago

While fuzzing latest KMSAN-build with HEALER(syscall fuzzer, not published yet), uninit-value is found in kmsan_handle_dma. It seems KMSAN found bugs in itself.

Caused by this call sequence syscalls.txt. With this crash msg.txt. THE latest KMSAN is used with this config config.txt.

ramosian-glider commented 4 years ago

This may be a valid bug in the kernel,a as kmsan_handle_dma() just checks the memory it received. In particular, this memory came from a kmalloc() call in elf_core_dump(). Not sure I'll be able to reproduce this bug using your syscall sequence, as it's neither C nor syzlang. What do I need to make it a valid C program?

In the meantime, you can add a memset after the kmalloc call in elf_core_dump() and overwrite the buffer with e.g. 0xAA. Then dump the memory in ata_qc_issue() and check if it's writing 0xAA's on disk. (Chances also are that I'm handling disk writes incorrectly, and these uninit writes aren't actually happening).

SunHao-0 commented 4 years ago

It happened five times during fuzzing in 24-h. The syscall sequence is a valid C program without header files, so just include related headers and wrap syscalls in the main function is enough. Pretty sure it's reproducible. Is it possible that this crash is caused by some other functions called by kmsan_handle_dma(), such as inline function? Thanks for replying.

ramosian-glider commented 4 years ago

Well, this is not a crash per se, it is a KMSAN report:

[ 1949.562864][ T3256] BUG: KMSAN: uninit-value in kmsan_handle_dma+0x9f/0xb0
...
[ 1949.568947][ T3256] kmsan_internal_check_memory+0x238/0x3d0
[ 1949.569644][ T3256] kmsan_handle_dma+0x9f/0xb0
[ 1949.570203][ T3256] kmsan_handle_dma_sg+0x35/0x50
[ 1949.570801][ T3256] ata_qc_issue+0xc71/0x1570
...
[ 1949.584854][ T3256] Uninit was stored to memory at:
[ 1949.585435][ T3256] kmsan_internal_chain_origin+0xad/0x130
[ 1949.586093][ T3256] kmsan_memcpy_memmove_metadata+0x262/0x2d0
[ 1949.586780][ T3256] kmsan_memcpy_metadata+0xb/0x10
[ 1949.587364][ T3256] __msan_memcpy+0x43/0x50
[ 1949.587876][ T3256] iov_iter_copy_from_user_atomic+0xb02/0x1510
[ 1949.588584][ T3256] generic_perform_write+0x499/0x9a0
[ 1949.589193][ T3256] ext4_buffered_write_iter+0x795/0xac0
[ 1949.589831][ T3256] ext4_file_write_iter+0x1330/0x2c60
[ 1949.590456][ T3256] __vfs_write+0xa5a/0xca0
[ 1949.590967][ T3256] __kernel_write+0x208/0x5f0
[ 1949.591507][ T3256] dump_emit+0x2ba/0x570
[ 1949.591998][ T3256] writenote+0x30c/0x4c0
[ 1949.592488][ T3256] elf_core_dump+0x6c49/0x8000
...
[ 1949.596382][ T3256] Uninit was created at:
[ 1949.596873][ T3256] kmsan_internal_poison_shadow+0x66/0xd0
[ 1949.597536][ T3256] kmsan_slab_alloc+0x8a/0xe0
[ 1949.598075][ T3256] __kmalloc+0x2c1/0x450
[ 1949.598566][ T3256] elf_core_dump+0x21dc/0x8000
[ 1949.599117][ T3256] do_coredump+0x3f74/0x56b0
[ 1949.599648][ T3256] get_signal+0xb36/0x32e0
[ 1949.600160][ T3256] do_signal+0x6f/0xe30
[ 1949.600646][ T3256] prepare_exit_to_usermode+0x2f0/0x520
[ 1949.601286][ T3256] swapgs_restore_regs_and_return_to_usermode+0x0/0x39
[ 1949.602069][ T3256] 
[ 1949.602341][ T3256] Bytes 2600-2647 of 4096 are uninitialized
[ 1949.603017][ T3256] Memory access of size 4096 starts at ffff999becb67000
[ 1949.603843][ T3256] =====================================================

So what presumably happens here is that elf_core_dump() allocates uninitialized memory, which is then written to the filesystem by __vfs_write(), and then asynchronously written to disk by ata_qc_issue().

If you add memset(0xAA) to the respective kmalloc call, you can even inspect the core dump file and search for 0xAA.

SunHao-0 commented 4 years ago

Thanks, got it. However, title of this kmsan report (_uninit-value in kmsan_handledma+0x9f/0xb0) is misleading.

ramosian-glider commented 4 years ago

Actually, the bug can be triggered by a trivial crashing program:

int main() {
  volatile char *c = 0;
  (void)*c;
  return 0;
}

I'm going to send an upstream patch.

ramosian-glider commented 4 years ago

Please let me know how the Reported-by: tag should look like, otherwise I'll send with:

Reported-by: sam <sunhaoyl@outlook.com>

SunHao-0 commented 4 years ago

Please let me know how the Reported-by: tag should look like, otherwise I'll send with:

Reported-by: sam <sunhaoyl@outlook.com>

Thanks! That would be very nice of you.

ramosian-glider commented 4 years ago

This can be closed now.