Re: sanitizing kvmtool

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Oct 17, 2015 at 4:16 PM, Sasha Levin <sasha.levin@xxxxxxxxxx> wrote:
> On 10/15/2015 06:21 AM, Dmitry Vyukov wrote:
>> Hello,
>>
>> I've run a set of sanitizers on
>> git://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git commit
>> 3695adeb227813d96d9c41850703fb53a23845eb. I've just booted a VM and
>> shut it down.
>>
>> AddressSanitizer detected a heap-use-after-free:
>>
>> AddressSanitizer: heap-use-after-free on address 0x60400000df90 at pc
>> 0x0000004f46d0 bp 0x7ffc79def2d0 sp 0x7ffc79def2c8
>> READ of size 8 at 0x60400000df90 thread T0
>>     #0 0x4f46cf in kvm__pause kvm.c:436:7
>>     #1 0x4f0d5d in ioport__unregister ioport.c:129:2
>>     #2 0x4efb2f in serial8250__exit hw/serial.c:446:7
>>     #3 0x516204 in init_list__exit util/init.c:59:8
>>     #4 0x4ea956 in kvm_cmd_run_exit builtin-run.c:645:2
>>     #5 0x4ea956 in kvm_cmd_run builtin-run.c:661
>>     #6 0x51596f in handle_command kvm-cmd.c:84:8
>>     #7 0x7fa398101ec4 in __libc_start_main
>> /build/buildd/eglibc-2.19/csu/libc-start.c:287
>>     #8 0x41a505 in _start (lkvm+0x41a505)
>>
>> 0x60400000df90 is located 0 bytes inside of 40-byte region
>> [0x60400000df90,0x60400000dfb8)
>> freed by thread T0 here:
>>     #0 0x4b75a0 in free
>> /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/asan/asan_malloc_linux.cc:30
>>     #1 0x4f29e6 in kvm_cpu__exit kvm-cpu.c:263:2
>>     #2 0x5160c4 in init_list__exit util/init.c:59:8
>>
>> previously allocated by thread T0 here:
>>     #0 0x4b7a2c in calloc
>> /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/asan/asan_malloc_linux.cc:56
>>     #1 0x4f2491 in kvm_cpu__init kvm-cpu.c:221:14
>
> I'm sending a patch to fix this + another issue it uncovered. This was caused by
> the kvm cpu exit function to be marked as late call rather than core call, so it
> would free the vcpus before anything else had a chance to exit.
>
>>
>> ThreadSanitizer detected a whole bunch of data races, for example:
>>
>> WARNING: ThreadSanitizer: data race (pid=109228)
>>   Write of size 1 at 0x7d6c0001f384 by thread T55:
>>     #0 memcpy /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:608
>> (lkvm+0x00000044b28b)
>>     #1 virtio_pci__msix_mmio_callback virtio/pci.c:269:3 (lkvm+0x0000004b3ee0)
>>     #2 kvm__emulate_mmio mmio.c:131:3 (lkvm+0x0000004ac332)
>>     #3 kvm_cpu__emulate_mmio x86/include/kvm/kvm-cpu-arch.h:46:9
>> (lkvm+0x0000004aa8c6)
>>     #4 kvm_cpu__start kvm-cpu.c:147 (lkvm+0x0000004aa8c6)
>>     #5 kvm_cpu_thread builtin-run.c:174:6 (lkvm+0x0000004a6e3e)
>>
>>   Previous read of size 4 at 0x7d6c0001f384 by thread T58:
>>     #0 virtio_pci__signal_vq virtio/pci.c:290:29 (lkvm+0x0000004b36b6)
>>     #1 virtio_net_tx_thread virtio/net.c:210:4 (lkvm+0x0000004b1fb5)
>>
>>   Location is heap block of size 1648 at 0x7d6c0001f100 allocated by
>> main thread:
>>     #0 calloc /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:544
>> (lkvm+0x00000043e812)
>>     #1 virtio_init virtio/core.c:191:12 (lkvm+0x0000004afa48)
>>     #2 virtio_net__init_one virtio/net.c:846:2 (lkvm+0x0000004b095d)
>>     #3 virtio_net__init virtio/net.c:868:3 (lkvm+0x0000004b0296)
>>     #4 init_list__init util/init.c:40:8 (lkvm+0x0000004bc7ee)
>>     #5 kvm_cmd_run_init builtin-run.c:621:6 (lkvm+0x0000004a6799)
>>     #6 kvm_cmd_run builtin-run.c:656 (lkvm+0x0000004a6799)
>>     #7 handle_command kvm-cmd.c:84:8 (lkvm+0x0000004bc40c)
>>     #8 handle_kvm_command main.c:11:9 (lkvm+0x0000004ac0b4)
>>     #9 main main.c:18 (lkvm+0x0000004ac0b4)
>>
>>   Thread T55 'kvm-vcpu-2' (tid=109285, running) created by main thread at:
>>     #0 pthread_create
>> /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:848
>> (lkvm+0x0000004478a3)
>>     #1 kvm_cmd_run_work builtin-run.c:633:7 (lkvm+0x0000004a683f)
>>     #2 kvm_cmd_run builtin-run.c:660 (lkvm+0x0000004a683f)
>>     #3 handle_command kvm-cmd.c:84:8 (lkvm+0x0000004bc40c)
>>     #4 handle_kvm_command main.c:11:9 (lkvm+0x0000004ac0b4)
>>     #5 main main.c:18 (lkvm+0x0000004ac0b4)
>>
>>   Thread T58 'virtio-net-tx' (tid=109334, running) created by thread T53 at:
>>     #0 pthread_create
>> /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:848
>> (lkvm+0x0000004478a3)
>>     #1 init_vq virtio/net.c:526:4 (lkvm+0x0000004b1523)
>>     #2 virtio_pci__io_out virtio/pci.c:219:3 (lkvm+0x0000004b484c)
>>     #3 kvm__emulate_io ioport.c:196:11 (lkvm+0x0000004aa0f8)
>>     #4 virtio_pci__io_mmio_callback virtio/pci.c:340:2 (lkvm+0x0000004b3e55)
>>     #5 kvm__emulate_mmio mmio.c:131:3 (lkvm+0x0000004ac332)
>>     #6 kvm_cpu__emulate_mmio x86/include/kvm/kvm-cpu-arch.h:46:9
>> (lkvm+0x0000004aa8c6)
>>     #7 kvm_cpu__start kvm-cpu.c:147 (lkvm+0x0000004aa8c6)
>>     #8 kvm_cpu_thread builtin-run.c:174:6 (lkvm+0x0000004a6e3e)
>
> So in this case (and most of the other data race cases described in the full log) it
> seems like ThreadSanitizer is mixing with different accesses by the guest to one underlying
> block of memory on the host.
>
> Here, for example, T55 accesses the msix block of the virtio-net PCI device, and T58 is accessing
> the virtqueue exposed by that device. While they both get to the same block of memory inside

I don't understand this.
Do you mean that this is a false positive? Or it is a real issue in lkvm?


>> and mutex unlock in a wrong thread (not supported by pthread):
>>
>> WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong
>> thread) (pid=109228)
>>     #0 pthread_mutex_unlock
>> /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:3303
>> (lkvm+0x00000042d183)
>>     #1 mutex_unlock include/kvm/mutex.h:35:6 (lkvm+0x0000004abfc8)
>>     #2 kvm__continue kvm.c:463 (lkvm+0x0000004abfc8)
>>     #3 kvm_cpu_signal_handler kvm-cpu.c:50:4 (lkvm+0x0000004aab59)
>>     #4 __tsan::CallUserSignalHandler(__tsan::ThreadState*, bool, bool,
>> bool, int, my_siginfo_t*, void*)
>> /usr/local/google/home/dvyukov/src/llvm/build/../projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1827
>> (lkvm+0x00000041f808)
>>     #5 kvm_cpu__reboot kvm-cpu.c:80:4 (lkvm+0x0000004aa449)
>>     #6 kbd_write_command hw/i8042.c:166:3 (lkvm+0x0000004cad7c)
>>     #7 kbd_out hw/i8042.c:327 (lkvm+0x0000004cad7c)
>>     #8 kvm__emulate_io ioport.c:196:11 (lkvm+0x0000004aa0f8)
>>     #9 kvm_cpu__emulate_io x86/include/kvm/kvm-cpu-arch.h:41:9
>> (lkvm+0x0000004aa718)
>>     #10 kvm_cpu__start kvm-cpu.c:126 (lkvm+0x0000004aa718)
>>     #11 kvm_cpu_thread builtin-run.c:174:6 (lkvm+0x0000004a6e3e)
>
> Still didn't look into this.
>
>> Full list is attached.
>>
>>
>> What do you think about incorporating the tools into Makefile and
>> running them continuously?
>> As far as I understand lkvm itself does not consume significant
>> portion of CPU time, so I would expect that it is possible to run the
>> tools always during development.
>>
>>
>> I've hacked Makefile as follows (makefile is not my favorite language):
>>
>>  $(PROGRAM)-static:  $(STATIC_OBJS) $(OTHEROBJS) $(GUEST_INIT)
>>         $(E) "  LINK    " $@
>> -       $(Q) $(CC) -static $(CFLAGS) $(STATIC_OBJS) $(OTHEROBJS)
>> $(GUEST_OBJS) $(LIBS) $(LIBS_STATOPT) -o $@
>> +       $(Q) clang -fsanitize=address -static $(CFLAGS) $(STATIC_OBJS)
>> $(OTHEROBJS) $(GUEST_OBJS) $(LIBS) $(LIBS_STATOPT) -o $@
>>
>>  $(PROGRAM): $(OBJS) $(OBJS_DYNOPT) $(OTHEROBJS) $(GUEST_INIT)
>>         $(E) "  LINK    " $@
>> -       $(Q) $(CC) $(CFLAGS) $(OBJS) $(OBJS_DYNOPT) $(OTHEROBJS)
>> $(GUEST_OBJS) $(LIBS) $(LIBS_DYNOPT) -o $@
>> +       $(Q) clang -fsanitize=address $(CFLAGS) $(OBJS) $(OBJS_DYNOPT)
>> $(OTHEROBJS) $(GUEST_OBJS) $(LIBS) $(LIBS_DYNOPT) -o $@
>>
>>  %.s: %.c
>>         $(Q) $(CC) -o $@ -S $(CFLAGS) -fverbose-asm $<
>> @@ -407,7 +409,7 @@ ifeq ($(C),1)
>>         $(Q) $(CHECK) -c $(CFLAGS) $(CFLAGS_DYNOPT) $< -o $@
>>  endif
>>         $(E) "  CC      " $@
>> -       $(Q) $(CC) -c $(c_flags) $(CFLAGS_DYNOPT) $< -o $@
>> +       $(Q) clang -fsanitize=address -c $(c_flags) $(CFLAGS_DYNOPT) $< -o $@
>>
>>
>>
>>
>> The set of flags you need is:
>> -fsanitize=address
>> -fsanitize=thread
>> -fsanitize=memory -fsanitize-memory-track-origins
>>
>> I've used tip clang, gcc also supports asan/tsan but not msan (and it
>> has somewhat outdated runtime).
>
> That'll be fine after we fix anything it finds right now :)
>
>
> Thanks,
> Sasha
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux