render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
c1c534
From 6c4c780eda082ef395b70af89b8b8942b9ad4a9d Mon Sep 17 00:00:00 2001
c1c534
Message-Id: <6c4c780eda082ef395b70af89b8b8942b9ad4a9d@dist-git>
c1c534
From: Michal Privoznik <mprivozn@redhat.com>
c1c534
Date: Mon, 8 Jan 2018 10:16:19 +0100
c1c534
Subject: [PATCH] qemuDomainAttachDeviceMknodHelper: Remove symlink before
c1c534
 creating it
c1c534
c1c534
https://bugzilla.redhat.com/show_bug.cgi?id=1528502
c1c534
c1c534
So imagine you have /dev/blah symlink which points to /dev/sda.
c1c534
You attach /dev/blah as disk to your domain. Libvirt correctly
c1c534
creates the /dev/blah -> /dev/sda symlink in the qemu namespace.
c1c534
However, then you detach the disk, change the symlink so that it
c1c534
points to /dev/sdb and tries to attach the disk again. This time,
c1c534
however, the attach fails (well, qemu attaches wrong disk)
c1c534
because the code assumes that symlinks don't change. Well they
c1c534
do.
c1c534
c1c534
This is inspired by test fix written by Eduardo Habkost.
c1c534
c1c534
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
c1c534
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
c1c534
(cherry picked from commit db98e7f67ea0d7699410f514f01947cef5128a6c)
c1c534
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
c1c534
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c1c534
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
c1c534
---
c1c534
 src/qemu/qemu_domain.c | 22 ++++++++++++++++------
c1c534
 1 file changed, 16 insertions(+), 6 deletions(-)
c1c534
c1c534
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
c1c534
index 8967f2774d..b0c78cc7c4 100644
c1c534
--- a/src/qemu/qemu_domain.c
c1c534
+++ b/src/qemu/qemu_domain.c
c1c534
@@ -9559,13 +9559,23 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
c1c534
 
c1c534
     if (isLink) {
c1c534
         VIR_DEBUG("Creating symlink %s -> %s", data->file, data->target);
c1c534
+
c1c534
+        /* First, unlink the symlink target. Symlinks change and
c1c534
+         * therefore we have no guarantees that pre-existing
c1c534
+         * symlink is still valid. */
c1c534
+        if (unlink(data->file) < 0 &&
c1c534
+            errno != ENOENT) {
c1c534
+            virReportSystemError(errno,
c1c534
+                                 _("Unable to remove symlink %s"),
c1c534
+                                 data->file);
c1c534
+            goto cleanup;
c1c534
+        }
c1c534
+
c1c534
         if (symlink(data->target, data->file) < 0) {
c1c534
-            if (errno != EEXIST) {
c1c534
-                virReportSystemError(errno,
c1c534
-                                     _("Unable to create symlink %s"),
c1c534
-                                     data->target);
c1c534
-                goto cleanup;
c1c534
-            }
c1c534
+            virReportSystemError(errno,
c1c534
+                                 _("Unable to create symlink %s (pointing to %s)"),
c1c534
+                                 data->file, data->target);
c1c534
+            goto cleanup;
c1c534
         } else {
c1c534
             delDevice = true;
c1c534
         }
c1c534
-- 
c1c534
2.15.1
c1c534