On Wed, Sep 24, 2025 at 4:51 PM Houqi (Nick) Zuo <h...@redhat.com> wrote:
>
> When QEMU creates a tap device automatically and the tap device is
> manually removed from the host while the guest is running, the tap
> device file descriptor becomes invalid. Later, when the guest executes
> shutdown, the tap_fd_set_vnet_hdr_len() function may be called and
> abort QEMU with a core dump when attempting to use the invalid fd.
>
> This patch removes many abort() calls in this file. If the fd is found
> to be in a bad state (e.g., EBADFD or ENODEV), the related function
> will print an error message.
>
> The expected behavior for this negative test case is that QEMU should
> report an error but continue running rather than aborting.
>
> Testing:
> - Start QEMU with automatically created tap device
> - Manually remove the tap device on the host
> - Execute shutdown in the guest
> - Verify QEMU reports an error but does not abort
>
> (gdb) bt full
> #0  __pthread_kill_implementation (threadid=<optimized out>, 
> signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
>         tid = <optimized out>
>         ret = 0
>         pd = <optimized out>
>         old_mask = {__val = {10}}
>         ret = <optimized out>
> #1  0x00007f1710b6bff3 in __pthread_kill_internal (threadid=<optimized out>, 
> signo=6) at pthread_kill.c:78
> #2  0x00007f1710b15f56 in __GI_raise (sig=sig@entry=6) at 
> ../sysdeps/posix/raise.c:26
>         ret = <optimized out>
> #3  0x00007f1710afd8fa in __GI_abort () at abort.c:79
>         save_stage = 1
>         act = {__sigaction_handler = {sa_handler = 0x20, sa_sigaction = 
> 0x20}, sa_mask = {__val = {16929458408262392576, 18446744073709550848, 
> 139737042419943, 139737042419943, 0, 94049703655600, 139737042419943, 
> 139737042670528, 18446744073709550328, 77, 139705603579344, 
> 18446744073709551615, 139737041472378, 139705595179568, 16929458408262392576, 
> 94049679794864}}, sa_flags = 281695456, sa_restorer = 0xa}
> #4  0x000055899a71de58 in tap_fd_set_vnet_hdr_len (fd=<optimized out>, 
> len=10) at ../net/tap-linux.c:204
> #5  tap_set_vnet_hdr_len (nc=<optimized out>, len=10) at ../net/tap.c:269
>         s = <optimized out>
> #6  0x000055899a8be67f in qemu_set_vnet_hdr_len (nc=0x2956, len=10588) at 
> ../net/net.c:573
> #7  virtio_net_set_mrg_rx_bufs (n=0x5589a72cfa10, 
> mergeable_rx_bufs=<optimized out>, version_1=<error reading variable: 
> Incompatible types on DWARF stack>, hash_report=<optimized out>) at 
> ../hw/net/virtio-net.c:664
>         i = 0
>         nc = 0x5589a730ab28
> #8  virtio_net_set_features (vdev=0x5589a72cfa10, features=0) at 
> ../hw/net/virtio-net.c:897
>         n = 0x5589a72cfa10
>         err = 0x0
>         i = 0
> #9  0x000055899a8e4eaa in virtio_set_features_nocheck (vdev=0x5589a72cfa10, 
> val=0) at ../hw/virtio/virtio.c:3079
>         k = <optimized out>
>         bad = <optimized out>
> #10 virtio_reset (opaque=0x5589a72cfa10) at ../hw/virtio/virtio.c:3184
>         vdev = 0x5589a72cfa10
>         k = 0x5589a5c162b0
>         i = 0
> #11 0x000055899a630d2b in virtio_bus_reset (bus=0x5589a72cf990) at 
> ../hw/virtio/virtio-bus.c:109
>         vdev = <optimized out>
> #12 virtio_pci_reset (qdev=0x5589a72c7470) at ../hw/virtio/virtio-pci.c:2311
>         proxy = 0x5589a72c7470
>         i = 0
>         bus = 0x5589a72cf990
> #13 0x000055899a686ded in memory_region_write_accessor (mr=<optimized out>, 
> addr=<optimized out>, value=<optimized out>, size=<optimized out>, 
> shift=<optimized out>, mask=<optimized out>, attrs=...) at 
> ../system/memory.c:490
>         tmp = <optimized out>
> #14 0x000055899a686cbc in access_with_adjusted_size (addr=20, 
> value=0x7f0fbedfde00, size=1, access_size_min=<optimized out>, 
> access_size_max=<optimized out>, access_fn=0x55899a686d30 
> <memory_region_write_accessor>, mr=0x5589a72c8040, attrs=...) at 
> ../system/memory.c:566
>         print_once_ = false
>         access_mask = 255
>         access_size = 1
>         i = 0
>         r = 0
>         reentrancy_guard_applied = <optimized out>
> #15 0x000055899a686ac5 in memory_region_dispatch_write (mr=<optimized out>, 
> addr=20, data=<optimized out>, op=<optimized out>, attrs=...) at 
> ../system/memory.c:1545
>         size = <optimized out>
> #16 0x000055899a69f7da in flatview_write_continue_step (attrs=..., 
> buf=0x7f1711da6028 <error: Cannot access memory at address 0x7f1711da6028>, 
> len=<optimized out>, mr_addr=20, l=0x7f0fbedfde28, mr=0x5589a72c8040) at 
> ../system/physmem.c:2972
>         val = 6
>         result = 0
>         release_lock = <optimized out>
> #17 0x000055899a697c15 in flatview_write_continue (fv=0x7f0f6c124d90, 
> addr=61675730370580, attrs=..., ptr=0x7f1711da6028, len=1, mr_addr=6, l=1, 
> mr=0x0) at ../system/physmem.c:3002
>         result = 0
>         buf = 0x7f1711da6028 <error: Cannot access memory at address 
> 0x7f1711da6028>
> #18 flatview_write (fv=0x7f0f6c124d90, addr=61675730370580, attrs=..., 
> buf=0x7f1711da6028, len=1) at ../system/physmem.c:3033
> --Type <RET> for more, q to quit, c to continue without paging--
>         l = <optimized out>
>         mr_addr = 6
>         mr = 0x0
> #19 0x000055899a697a91 in address_space_write (as=0x55899bceeba0 
> <address_space_memory>, addr=61675730370580, attrs=..., buf=0x7f1711da6028, 
> len=1) at ../system/physmem.c:3153
>         _rcu_read_auto = 0x1
>         result = 0
>         fv = 0x2956
> #20 0x000055899a91159b in address_space_rw (addr=10588, attrs=..., 
> buf=0x7f1711da6028, len=0, as=<optimized out>, is_write=<optimized out>) at 
> ../system/physmem.c:3163
> #21 kvm_cpu_exec (cpu=0x5589a5d68b40) at ../accel/kvm/kvm-all.c:3255
>         attrs = {secure = 0, space = 0, user = 0, memory = 0, debug = 0, 
> requester_id = 0, pid = 0, address_type = 0, unspecified = false, _reserved1 
> = 0 '\000', _reserved2 = 0}
>         run = 0x7f1711da6000
>         ret = <optimized out>
>         run_ret = <optimized out>
> #22 0x000055899a9189ca in kvm_vcpu_thread_fn (arg=0x5589a5d68b40) at 
> ../accel/kvm/kvm-accel-ops.c:51
>         r = <optimized out>
>         cpu = <optimized out>
> #23 0x000055899aba817a in qemu_thread_start (args=0x5589a5d72580) at 
> ../util/qemu-thread-posix.c:393
>         __clframe = {__cancel_routine = <optimized out>, __cancel_arg = 0x0, 
> __do_it = 1, __cancel_type = <optimized out>}
>         qemu_thread_args = 0x5589a5d72580
>         start_routine = 0x55899a918850 <kvm_vcpu_thread_fn>
>         arg = 0x5589a5d68b40
>         r = 0x0
> #24 0x00007f1710b6a128 in start_thread (arg=<optimized out>) at 
> pthread_create.c:448
>         ret = <optimized out>
>         pd = <optimized out>
>         out = <optimized out>
>         unwind_buf = {cancel_jmp_buf = {{jmp_buf = {32, 8894544057743421332, 
> -1288, 0, 140726164742416, 140726164742679, -8831356496486092908, 
> -8844535456800460908}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 
> 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
>         not_first_call = <optimized out>
> #25 0x00007f1710bda924 in clone () at 
> ../sysdeps/unix/sysv/linux/x86_64/clone.S:100
>
> Fixes: 0caed25cd171c611781589b5402161d27d57229c virtio: Call set_features 
> during reset
>
i think the format of fix should be
 “Fixes: <at-least-12-digits-of-SHA-commit-id> (“Fixed commit subject”)”

> Signed-off-by: Houqi (Nick) Zuo <h...@redhat.com>
> ---
>  net/tap-linux.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/net/tap-linux.c b/net/tap-linux.c
> index e832810665..24e63a0b54 100644
> --- a/net/tap-linux.c
> +++ b/net/tap-linux.c
> @@ -206,15 +206,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
>      if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) {
>          fprintf(stderr, "TUNSETVNETHDRSZ ioctl() failed: %s. Exiting.\n",
>                  strerror(errno));
> -        abort();
>      }
>  }
>
>  int tap_fd_set_vnet_le(int fd, int is_le)
>  {
>      int arg = is_le ? 1 : 0;
> +    int ret;
>
> -    if (!ioctl(fd, TUNSETVNETLE, &arg)) {
> +    ret = ioctl(fd, TUNSETVNETLE, &arg);
> +    if (!ret) {
>          return 0;
>      }
>
> @@ -224,14 +225,16 @@ int tap_fd_set_vnet_le(int fd, int is_le)
>      }
>
>      error_report("TUNSETVNETLE ioctl() failed: %s.", strerror(errno));
> -    abort();
> +    return ret;
>  }
>
>  int tap_fd_set_vnet_be(int fd, int is_be)
>  {
>      int arg = is_be ? 1 : 0;
> +    int ret;
>
> -    if (!ioctl(fd, TUNSETVNETBE, &arg)) {
> +    ret = ioctl(fd, TUNSETVNETBE, &arg);
> +    if (!ret) {
>          return 0;
>      }
>
> @@ -241,7 +244,7 @@ int tap_fd_set_vnet_be(int fd, int is_be)
>      }
>
>      error_report("TUNSETVNETBE ioctl() failed: %s.", strerror(errno));
> -    abort();
> +    return ret;
>  }
>
>  void tap_fd_set_offload(int fd, int csum, int tso4,
> --
> 2.47.3
>


Reply via email to