@@ -202,6 +202,10 @@ static int vhost_net_start_one(struct vhost_net *net,
struct vhost_vring_file file = { };
int r;
+ if (!net) {
+ return -1;
+ }
+
net->dev.nvqs = 2;
net->dev.vqs = net->vqs;
@@ -256,6 +260,10 @@ static void vhost_net_stop_one(struct vhost_net *net,
{
struct vhost_vring_file file = { .fd = -1 };
+ if (!net) {
+ return;
+ }
+
if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
const VhostOps *vhost_ops = net->dev.vhost_ops;
@@ -287,6 +295,9 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
struct vhost_net *net;
net = get_vhost_net(ncs[i].peer);
+ if (!net) {
+ return -1;
+ }
vhost_net_set_vq_index(net, i * 2);
/* Suppress the masking guest notifiers on vhost user
@@ -419,9 +430,14 @@ void put_vhost_net(NetClientState *nc)
int vhost_set_vring_enable(NetClientState *nc, int enable)
{
VHostNetState *net = get_vhost_net(nc);
- const VhostOps *vhost_ops = net->dev.vhost_ops;
+ const VhostOps *vhost_ops;
int res = 0;
+ if (!net) {
+ return 0;
+ }
+
+ vhost_ops = net->dev.vhost_ops;
if (vhost_ops->vhost_set_vring_enable) {
res = vhost_ops->vhost_set_vring_enable(&net->dev, enable);
}
After successfull destroying of vhost-user device (may be after virtio driver unbinding after disconnection of vhost-user socket) QEMU will fail to bind virtio driver again with segmentation fault: [-------------------------------- cut -----------------------------------] # After vhost-user socket diconnection. [guest]# ip link show eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc <...> link/ether 00:16:35:af:aa:4b brd ff:ff:ff:ff:ff:ff [guest]# echo -n '0000:00:01.0' > /sys/bus/pci/drivers/virtio-pci/unbind qemu: Failed to read msg header. Read 0 instead of 12. Original request 11. qemu: Failed to read msg header. Read 0 instead of 12. Original request 11. [guest]# echo -n '0000:00:01.0' > /sys/bus/pci/drivers/virtio-pci/bind Child terminated with signal = 0xb (SIGSEGV) GDBserver exiting [-------------------------------- cut -----------------------------------] [host]# gdb Program received signal SIGSEGV, Segmentation fault. vhost_set_vring_enable (<...>) at /hw/net/vhost_net.c:425 425 if (vhost_ops->vhost_set_vring_enable) { (gdb) bt #0 vhost_set_vring_enable (nc=0xfff8a0, enable=enable@entry=1) net = 0x0 # NULL pointer to vhost_net device ! vhost_ops = <(Cannot access memory at address 0x110)> res = 0 #1 peer_attach #2 virtio_net_set_queues #3 virtio_net_set_multiqueue #4 virtio_net_set_features #5 virtio_set_features_nocheck #6 memory_region_write_accessor #7 access_with_adjusted_size #8 memory_region_dispatch_write #9 address_space_write_continue #10 address_space_write <...> [-------------------------------- cut -----------------------------------] This happens because of invalid vhost_net device pointer. Fix that by checking this pointer in all functions before using. Result: [-------------------------------- cut -----------------------------------] [guest]# echo -n '0000:00:01.0' > /sys/bus/pci/drivers/virtio-pci/bind # Check link in guest. No crashes here, link in DOWN state. [guest]# ip link show eth0 7: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc <...> link/ether 00:16:35:af:aa:4b brd ff:ff:ff:ff:ff:ff [-------------------------------- cut -----------------------------------] Signed-off-by: Ilya Maximets <i.maximets@samsung.com> --- hw/net/vhost_net.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)