From 7ea7ef99b8d3f9a7d83ea12a843d786b182f24e3 Mon Sep 17 00:00:00 2001 Message-Id: <7ea7ef99b8d3f9a7d83ea12a843d786b182f24e3@dist-git> From: Michal Privoznik Date: Mon, 11 May 2020 16:56:48 +0200 Subject: [PATCH] virDevMapperGetTargetsImpl: quit early if device is not a devmapper target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As suggested in the linked bug, libvirt should firstly check whether the major number of the device is device mapper major. Because if it isn't subsequent DM_DEVICE_DEPS task may not only fail, but also yield different results. In the bugzilla this is demonstrated by creating a devmapper target named 'loop0' and then creating loop target /dev/loop0. When the latter is then passed to a domain, our virDevMapperGetTargetsImpl() function blindly asks devmapper to provide target dependencies for /dev/loop0 and because of the way devmapper APIs work, it will 'sanitize' the input by using the last component only which is 'loop0' and thus return different results than expected. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1823976 Signed-off-by: Michal Privoznik Reviewed-by: Ján Tomko (cherry picked from commit 01626c668ecfbe465d18799ac4628e6127ea1d47) Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1834353 Signed-off-by: Michal Privoznik Message-Id: Reviewed-by: Jiri Denemark --- src/util/virdevmapper.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c index cc6a099faa..f000979ce0 100644 --- a/src/util/virdevmapper.c +++ b/src/util/virdevmapper.c @@ -66,6 +66,7 @@ virDevMapperGetTargetsImpl(const char *path, char ***devPaths_ret, unsigned int ttl) { + struct stat sb; struct dm_task *dmt = NULL; struct dm_deps *deps; struct dm_info info; @@ -84,6 +85,15 @@ virDevMapperGetTargetsImpl(const char *path, return ret; } + if (stat(path, &sb) < 0) { + if (errno == ENOENT) + return 0; + return -1; + } + + if (!dm_is_dm_major(major(sb.st_dev))) + return 0; + if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) { if (errno == ENOENT || errno == ENODEV) { /* It's okay. Kernel is probably built without -- 2.26.2