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 the abort() call. If the fd is found to be in a
bad state (e.g., EBADFD or ENODEV), the 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
tid = <optimized out>
ret = 0
pd = <optimized out>
old_mask = {__val = {10}}
ret = <optimized out>
ret = <optimized out>
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}
s = <optimized out>
i = 0
nc = 0x5589a730ab28
n = 0x5589a72cfa10
err = 0x0
i = 0
k = <optimized out>
bad = <optimized out>
vdev = 0x5589a72cfa10
k = 0x5589a5c162b0
i = 0
vdev = <optimized out>
proxy = 0x5589a72c7470
i = 0
bus = 0x5589a72cf990
tmp = <optimized out>
print_once_ = false
access_mask = 255
access_size = 1
i = 0
r = 0
reentrancy_guard_applied = <optimized out>
size = <optimized out>
val = 6
result = 0
release_lock = <optimized out>
result = 0
buf = 0x7f1711da6028 <error: Cannot access memory at address 0x7f1711da6028>
--Type <RET> for more, q to quit, c to continue without paging--
l = <optimized out>
mr_addr = 6
mr = 0x0
_rcu_read_auto = 0x1
result = 0
fv = 0x2956
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>
r = <optimized out>
cpu = <optimized out>
__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
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>
Signed-off-by: Houqi (Nick) Zuo <hzuo@redhat.com>
---
net/tap-linux.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/net/tap-linux.c b/net/tap-linux.c
index e832810665..37a53416e8 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -206,7 +206,6 @@ 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();
}
}
--
2.47.3
© 2016 - 2025 Red Hat, Inc.