Heap overflow due to inadequate length check in SMC91c111 device

Explanation of the bug: The len variable which is got from the guest, is not checked if it is very small. So if len is less than 5 the check if (len > MAX_PACKET_SIZE) (https://github.com/qemu/qemu/blob/ece408818d27f745ef1b05fb3cc99a1e7a5bf580/hw/net/smc91c111.c#L292) passes, and after the line len -= 6; (https://github.com/qemu/qemu/blob/ece408818d27f745ef1b05fb3cc99a1e7a5bf580/hw/net/smc91c111.c#L303) len becomes a very huge value. This leads to buffer overflow in qemu_net_queue_send function as packet = g_malloc(sizeof(NetPacket) + size);(https://github.com/qemu/qemu/blob/ece408818d27f745ef1b05fb3cc99a1e7a5bf580/net/queue.c#L105) wraps to a smaller number but memcpy(packet->data, buf, size); (https://github.com/qemu/qemu/blob/ece408818d27f745ef1b05fb3cc99a1e7a5bf580/net/queue.c#L110) is using the very huge value.

Steps to reproduce: Prepare the guest:

git clone https://git.buildroot.net/buildroot 
cd buildroot 
make qemu_arm_versatile_defconfig 
I enabled 9P_FS and VIRTIO to make it easy to push the driver to the guest. (refer the attached .config file )
make linux-rebuild all 

On the host, compiled qemu with Asan enabled. started qemu as:

~/dump/qemu/build/qemu-system-arm -M versatilepb -m 128M -nographic \
    -kernel zImage \
    -dtb versatile-pb.dtb \
    -drive file=rootfs.ext2,if=scsi,format=raw \
    -append "root=/dev/sda console=ttyAMA0,115200" \
    -fsdev local,path=$HOME/smc_driver_project,security_model=passthrough,id=host_share \
    -device virtio-9p-pci,fsdev=host_share,mount_tag=host_share \
    -netdev user,id=sshnet,hostfwd=tcp::2222-:22 \
    -device virtio-net-pci,netdev=sshnet \
    -netdev socket,id=targetnet,listen=:12345 \
    -net nic,model=smc91c111,netdev=targetnet \
    -object filter-dump,id=dump0,netdev=targetnet,file=repro_trace.pcap

This line was added like this so that the qemu_net_queue_append is taken. This is just a poc!

    -net nic,model=smc91c111,netdev=targetnet \
    -object filter-dump,id=dump0,netdev=targetnet,file=repro_trace.pcap 

Inside guest: Login as root:

mkdir -p /mnt/host
mount -t 9p -o trans=virtio,version=9p2000.L host_share /mnt/host
cd  /mnt/host
insmod qemu_smc_repro.ko
Welcome to Buildroot
buildroot login: root
# mkdir -p /mnt/host
# mount -t 9p -o trans=virtio,version=9p2000.L host_share /mnt/host
# cd /mnt/host
# insmod qemu_smc_repro.ko
qemu_smc_repro: loading out-of-tree module taints kernel.
=================================================================
==528315==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5290000316c0 at pc 0x7fed4a072957 bp 0x7fecb2bf8590 sp 0x7fecb2bf7d50
READ of size 65536 at 0x5290000316c0 thread T2
    #0 0x7fed4a072956 in read_iovec ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:963
    #1 0x7fed4a0c5307 in writev ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1157
    #2 0x55fd235c24d3 in dump_receive_iov ../net/dump.c:90
    #3 0x55fd235c2e00 in filter_dump_receive_iov ../net/dump.c:158
    #4 0x55fd235ca3a8 in qemu_netfilter_receive ../net/filter.c:41
    #5 0x55fd235d326b in filter_receive_iov ../net/net.c:668
    #6 0x55fd235d3464 in filter_receive ../net/net.c:692
    #7 0x55fd235d38a1 in qemu_send_packet_async_with_flags ../net/net.c:753
    #8 0x55fd235d3978 in qemu_send_packet_async ../net/net.c:768
    #9 0x55fd235d39b0 in qemu_send_packet ../net/net.c:774
    #10 0x55fd22fd120b in smc91c111_do_tx ../hw/net/smc91c111.c:332
    #11 0x55fd22fd13dc in smc91c111_queue_tx ../hw/net/smc91c111.c:355
    #12 0x55fd22fd255e in smc91c111_writeb ../hw/net/smc91c111.c:533
    #13 0x55fd22fd378a in smc91c111_writefn ../hw/net/smc91c111.c:784
    #14 0x55fd23472f7d in memory_region_write_accessor ../system/memory.c:491
    #15 0x55fd23473617 in access_with_adjusted_size ../system/memory.c:567
    #16 0x55fd2347baa2 in memory_region_dispatch_write ../system/memory.c:1547
    #17 0x55fd234a5b96 in flatview_write_continue_step ../system/physmem.c:3241
    #18 0x55fd234a5d8d in flatview_write_continue ../system/physmem.c:3271
    #19 0x55fd234a6093 in flatview_write ../system/physmem.c:3302
    #20 0x55fd234a4333 in subpage_write ../system/physmem.c:2909
    #21 0x55fd234731b1 in memory_region_write_with_attrs_accessor ../system/memory.c:512
    #22 0x55fd23473617 in access_with_adjusted_size ../system/memory.c:567
    #23 0x55fd2347bb89 in memory_region_dispatch_write ../system/memory.c:1554
    #24 0x55fd236f7999 in int_st_mmio_leN ../accel/tcg/cputlb.c:2465
    #25 0x55fd236f7c76 in do_st_mmio_leN ../accel/tcg/cputlb.c:2498
    #26 0x55fd236f8b60 in do_st_1 ../accel/tcg/cputlb.c:2626
    #27 0x55fd236f938f in do_st1_mmu ../accel/tcg/cputlb.c:2701
    #28 0x55fd236fafc6 in helper_stb_mmu ../accel/tcg/ldst_common.c.inc:86
    #29 0x7fecbd4c0229  (/memfd:tcg-jit (deleted)+0x24d5229)

0x5290000316c0 is located 0 bytes after 17600-byte region [0x52900002d200,0x5290000316c0)
allocated by thread T0 here:
    #0 0x7fed4a0f4c57 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x7fed48c19701 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x65701) (BuildId: 0238e5480cfba00d18623750cdd44b19a753f7ad)
    #2 0x55fd23cafb16 in object_new ../qom/object.c:789
    #3 0x55fd23ca2349 in qdev_new ../hw/core/qdev.c:149
    #4 0x55fd22fd431d in smc91c111_init ../hw/net/smc91c111.c:945
    #5 0x55fd239b72a6 in versatile_init ../hw/arm/versatilepb.c:269
    #6 0x55fd239b7de2 in vpb_init ../hw/arm/versatilepb.c:408
    #7 0x55fd22c91bb6 in machine_run_board_init ../hw/core/machine.c:1732
    #8 0x55fd234504e1 in qemu_init_board ../system/vl.c:2715
    #9 0x55fd23450cc9 in qmp_x_exit_preconfig ../system/vl.c:2809
    #10 0x55fd23455c40 in qemu_init ../system/vl.c:3849
    #11 0x55fd23fd6eb9 in main ../system/main.c:71
    #12 0x7fed45d95ca7  (/lib/x86_64-linux-gnu/libc.so.6+0x29ca7) (BuildId: fce446c9d4ad48e2b0c90cce1a11722897805281)

Thread T2 created by T0 here:
    #0 0x7fed4a0ecae1 in pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:245
    #1 0x55fd2417ea2b in qemu_thread_create ../util/qemu-thread-posix.c:433
    #2 0x55fd237144fe in mttcg_start_vcpu_thread ../accel/tcg/tcg-accel-ops-mttcg.c:135
    #3 0x55fd2345c1ae in qemu_init_vcpu ../system/cpus.c:726
    #4 0x55fd23872b5a in arm_cpu_realizefn ../target/arm/cpu.c:2210
    #5 0x55fd23ca3f00 in device_set_realized ../hw/core/qdev.c:523
    #6 0x55fd23cb7ca8 in property_set_bool ../qom/object.c:2376
    #7 0x55fd23cb2fd9 in object_property_set ../qom/object.c:1450
    #8 0x55fd23cbd2a2 in object_property_set_qobject ../qom/qom-qobject.c:28
    #9 0x55fd23cb355b in object_property_set_bool ../qom/object.c:1520
    #10 0x55fd23ca2d3d in qdev_realize ../hw/core/qdev.c:276
    #11 0x55fd239b6cc1 in versatile_init ../hw/arm/versatilepb.c:222
    #12 0x55fd239b7de2 in vpb_init ../hw/arm/versatilepb.c:408
    #13 0x55fd22c91bb6 in machine_run_board_init ../hw/core/machine.c:1732
    #14 0x55fd234504e1 in qemu_init_board ../system/vl.c:2715
    #15 0x55fd23450cc9 in qmp_x_exit_preconfig ../system/vl.c:2809
    #16 0x55fd23455c40 in qemu_init ../system/vl.c:3849
    #17 0x55fd23fd6eb9 in main ../system/main.c:71
    #18 0x7fed45d95ca7  (/lib/x86_64-linux-gnu/libc.so.6+0x29ca7) (BuildId: fce446c9d4ad48e2b0c90cce1a11722897805281)

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:963 in read_iovec
Shadow bytes around the buggy address:
  0x529000031400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000031480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000031500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000031580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000031600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x529000031680: 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa fa fa
  0x529000031700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000031780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000031800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000031880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000031900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6[exploit.zip](/uploads/3e7d4c46d522fd7ad94d7e775cdcd877/exploit.zip)

  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzon

-Vinod

Assignee Loading
Time tracking Loading