Skip to content

SIGSEGV in memcpy in v9fs_co_readdir_many

Host environment

  • Operating system: ALT Linux
  • OS/kernel version: 5.16
  • Architecture: x86-64
  • QEMU flavor: qemu-system-x86_64
  • QEMU version: QEMU emulator version 6.2.0 (qemu-6.2.0-alt1)
  • QEMU command line:
    qemu-system-x86_64 -enable-kvm -m 40270M -smp cores=20 -nodefaults -nographic -no-reboot -fsdev local,id=root,path=/,security_model=none,multidevs=remap -device virtio-9p-pci,fsdev=root,mount_tag=/dev/root -device virtio-rng-pci -serial mon:stdio -kernel /boot/vmlinuz-5.16.2-un-def-alt1 -initrd /usr/src/tmp/initramfs-5.16.2-un-def-alt1.img -bios bios.bin -append console=ttyS0 mitigations=off nokaslr quiet panic=-1 SCRIPT=/usr/src/tmp/tmp.g5TpLWtJa1 UDEVD=y NOTTY no_timer_check

Emulated/Virtualized environment

  • Operating system: ALT Linux
  • OS/kernel version: 5.16.2
  • Architecture: x86-64

Description of problem

When running btrfs tests in vm (using virtme-like setup with 9pfs) occasionally qemu crashes with (coredumpctl info output):

...
Message: Process 1764494 (qemu-system-x86) of user 502 dumped core.
Stack trace of thread 1764817:
 #0  0x00005555559ebeed v9fs_co_readdir_many (/usr/bin/qemu-system-x86_64 + 0x497eed)
 #1  0x00005555559ec2e9 v9fs_readdir (/usr/bin/qemu-system-x86_64 + 0x4982e9)
 #2  0x0000555555eb7983 coroutine_trampoline (/usr/bin/qemu-system-x86_64 + 0x963983)
 #3  0x00007ffff73e0be0 n/a (n/a + 0x0)

Additional information

coredumpctl debug:

Failed to read a valid object file image from memory.
Core was generated by `qemu-system-x86_64 -enable-kvm -m 40270M -smp cores=20 -nodefaults -nographic -'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00005555559ebeed in memcpy (__len=<optimized out>, __src=<optimized out>, __dest=<optimized out>, __dest=<optimized out>, __src=<optimized out>,
    __len=<optimized out>) at /usr/include/bits/string_fortified.h:29
29        return __builtin___memcpy_chk (__dest, __src, __len,
[Current thread is 1 (LWP 1764817)]
(gdb) list ../hw/9pfs/codir.c:147
142                 *entries = e = g_malloc0(sizeof(V9fsDirEnt));
143             } else {
144                 e = e->next = g_malloc0(sizeof(V9fsDirEnt));
145             }
146             e->dent = g_malloc0(sizeof(struct dirent));
147             memcpy(e->dent, dent, sizeof(struct dirent));
148
149             /* perform a full stat() for directory entry if requested by caller */
150             if (dostat) {
151                 err = s->ops->name_to_path(
(gdb) bt
#0  0x00005555559ebeed in memcpy (__len=<optimized out>, __src=<optimized out>, __dest=<optimized out>, __dest=<optimized out>, __src=<optimized out>,
    __len=<optimized out>) at /usr/include/bits/string_fortified.h:29
#1  do_readdir_many (dostat=<optimized out>, maxsize=<optimized out>, offset=<optimized out>, entries=<optimized out>, fidp=<optimized out>,
    pdu=0x555557353500) at ../hw/9pfs/codir.c:147
#2  v9fs_co_readdir_many (pdu=pdu@entry=0x555557353500, fidp=fidp@entry=0x555556cdd280, entries=entries@entry=0x7ff5bf7f7f58, offset=<optimized out>,
    maxsize=<optimized out>, dostat=<optimized out>) at ../hw/9pfs/codir.c:226
#3  0x00005555559ec2e9 in v9fs_do_readdir (max_count=<optimized out>, offset=<optimized out>, fidp=0x555556cdd280, pdu=0x555557353500) at ../hw/9pfs/9p.c:2430
#4  v9fs_readdir (opaque=0x555557353500) at ../hw/9pfs/9p.c:2543
#5  0x0000555555eb7983 in coroutine_trampoline (i0=<optimized out>, i1=<optimized out>) at ../util/coroutine-ucontext.c:173
#6  0x00007ffff73e0be0 in ?? ()
#7  0x00007fffffffd480 in ?? ()
#8  0x0000000000000000 in ?? ()
(gdb) x/11i 0x00005555559ebeed - 27
   0x5555559ebed2 <v9fs_co_readdir_many+530>:   call   0x555555928480 <g_malloc0@plt>
   0x5555559ebed7 <v9fs_co_readdir_many+535>:   mov    %rbp,%rsi
   0x5555559ebeda <v9fs_co_readdir_many+538>:   mov    %rax,(%r12)
   0x5555559ebede <v9fs_co_readdir_many+542>:   mov    0x0(%rbp),%rdx
   0x5555559ebee2 <v9fs_co_readdir_many+546>:   lea    0x8(%rax),%rdi
   0x5555559ebee6 <v9fs_co_readdir_many+550>:   and    $0xfffffffffffffff8,%rdi
   0x5555559ebeea <v9fs_co_readdir_many+554>:   mov    %rdx,(%rax)
=> 0x5555559ebeed <v9fs_co_readdir_many+557>:   mov    0x110(%rbp),%rdx
   0x5555559ebef4 <v9fs_co_readdir_many+564>:   mov    %rdx,0x110(%rax)
   0x5555559ebefb <v9fs_co_readdir_many+571>:   sub    %rdi,%rax
   0x5555559ebefe <v9fs_co_readdir_many+574>:   sub    %rax,%rsi
(gdb) i r rdx rax rip
rdx            0x29287d            2697341
rax            0x7ff4bc12ccf0      140689104096496
rip            0x5555559ebeed      0x5555559ebeed <v9fs_co_readdir_many+557>
(gdb) x/11x 0x7ff4bc12ccf0
0x7ff4bc12ccf0: 0x0029287d      0x00000000      0x00000000      0x00000000
0x7ff4bc12cd00: 0x00000000      0x00000000      0x00000000      0x00000000
0x7ff4bc12cd10: 0x00000000      0x00000000      0x00000000
(gdb) frame 1
#1  do_readdir_many (dostat=<optimized out>, maxsize=<optimized out>, offset=<optimized out>, entries=<optimized out>, fidp=<optimized out>,
    pdu=0x555557353500) at ../hw/9pfs/codir.c:147
147             memcpy(e->dent, dent, sizeof(struct dirent));
(gdb) p e
$3 = (struct V9fsDirEnt *) 0x7ff4bc12caa0
(gdb) p e->dent
$4 = (struct dirent *) 0x7ff4bc12ccf0
(gdb) p dent
$5 = (struct dirent *) 0x7ff4ec04cef0
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information