From 7f90c668b14030c72e2ade8d4bf8895060e889ca Mon Sep 17 00:00:00 2001 From: David Marchand Date: Tue, 22 Oct 2024 17:51:18 +0200 Subject: [PATCH] vhost: vduse toctou Signed-off-by: David Marchand --- lib/vhost/vduse.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/lib/vhost/vduse.c b/lib/vhost/vduse.c index f9ac317438d..f29095b318a 100644 --- a/lib/vhost/vduse.c +++ b/lib/vhost/vduse.c @@ -485,7 +485,6 @@ vduse_device_create(const char *path, bool compliant_ol_flags) struct virtio_net_config vnet_config = {{ 0 }}; uint64_t ver = VHOST_VDUSE_API_VERSION; uint64_t features; - struct vduse_dev_config *dev_config = NULL; const char *name = path + strlen("/dev/vduse/"); char reconnect_file[PATH_MAX]; struct vhost_reconnect_data *reconnect_log = NULL; @@ -530,13 +529,13 @@ vduse_device_create(const char *path, bool compliant_ol_flags) ret = rte_vhost_driver_get_features(path, &features); if (ret < 0) { VHOST_CONFIG_LOG(name, ERR, "Failed to get backend features"); - goto out_free; + goto out_dev_close; } ret = rte_vhost_driver_get_queue_num(path, &max_queue_pairs); if (ret < 0) { VHOST_CONFIG_LOG(name, ERR, "Failed to get max queue pairs"); - goto out_free; + goto out_dev_close; } VHOST_CONFIG_LOG(path, INFO, "VDUSE max queue pairs: %u", max_queue_pairs); @@ -547,7 +546,8 @@ vduse_device_create(const char *path, bool compliant_ol_flags) else total_queues += 1; /* Includes ctrl queue */ - if (access(path, F_OK) == 0) { + dev_fd = open(path, O_RDWR); + if (dev_fd >= 0) { VHOST_CONFIG_LOG(name, INFO, "Device already exists, reconnecting..."); reconnect = true; @@ -594,7 +594,10 @@ vduse_device_create(const char *path, bool compliant_ol_flags) ret = -1; goto out_ctrl_close; } - } else { + } else if (errno == ENOENT) { + char buf[offsetof(struct vduse_dev_config, config) + sizeof(vnet_config)]; + struct vduse_dev_config *dev_config = (struct vduse_dev_config *)buf; + reco_fd = open(reconnect_file, O_CREAT | O_EXCL | O_RDWR, 0600); if (reco_fd < 0) { if (errno == EEXIST) { @@ -628,14 +631,6 @@ vduse_device_create(const char *path, bool compliant_ol_flags) reconnect_log->version = VHOST_RECONNECT_VERSION; - dev_config = malloc(offsetof(struct vduse_dev_config, config) + - sizeof(vnet_config)); - if (!dev_config) { - VHOST_CONFIG_LOG(name, ERR, "Failed to allocate VDUSE config"); - ret = -1; - goto out_ctrl_close; - } - vnet_config.max_virtqueue_pairs = max_queue_pairs; memset(dev_config, 0, sizeof(struct vduse_dev_config)); @@ -652,16 +647,15 @@ vduse_device_create(const char *path, bool compliant_ol_flags) if (ret < 0) { VHOST_CONFIG_LOG(name, ERR, "Failed to create VDUSE device: %s", strerror(errno)); - goto out_free; + goto out_dev_close; } memcpy(&reconnect_log->config, &vnet_config, sizeof(vnet_config)); reconnect_log->nr_vrings = total_queues; - free(dev_config); - dev_config = NULL; + + dev_fd = open(path, O_RDWR); } - dev_fd = open(path, O_RDWR); if (dev_fd < 0) { VHOST_CONFIG_LOG(name, ERR, "Failed to open device %s: %s", path, strerror(errno)); @@ -765,12 +759,10 @@ vduse_device_create(const char *path, bool compliant_ol_flags) out_dev_destroy: vhost_destroy_device(vid); out_dev_close: - if (dev_fd >= 0) - close(dev_fd); ioctl(control_fd, VDUSE_DESTROY_DEV, name); -out_free: - free(dev_config); out_ctrl_close: + if (dev_fd >= 0) + close(dev_fd); close(control_fd); return ret;