render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
99cbc7
From 703d3a465850b768e627705a587cfd8095fe0be7 Mon Sep 17 00:00:00 2001
99cbc7
Message-Id: <703d3a465850b768e627705a587cfd8095fe0be7@dist-git>
99cbc7
From: Michal Privoznik <mprivozn@redhat.com>
99cbc7
Date: Tue, 23 Oct 2018 11:40:58 +0100
99cbc7
Subject: [PATCH] virfile: Take symlink into account in virFileIsSharedFixFUSE
99cbc7
99cbc7
RHEL-7.7: https://bugzilla.redhat.com/show_bug.cgi?id=1640465
99cbc7
RHEL-7.6.z: https://bugzilla.redhat.com/show_bug.cgi?id=1641798
99cbc7
99cbc7
Weirdly enough, there can be symlinks in the path we are trying
99cbc7
to fix. If it is the case our clever algorithm that finds matches
99cbc7
against mount table won't work. Canonicalize path at the
99cbc7
beginning then.
99cbc7
99cbc7
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
99cbc7
Reviewed-by: Erik Skultety <eskultet@redhat.com>
99cbc7
(cherry picked from commit c0790e3a09f57da0bd25c7eac4a35ed6e7e9e858)
99cbc7
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
99cbc7
Reviewed-by: Erik Skultety <eskultet@redhat.com>
99cbc7
---
99cbc7
 cfg.mk              |  2 +-
99cbc7
 src/util/virfile.c  | 15 +++++++++++++--
99cbc7
 tests/virfilemock.c | 33 ++++++++++++++++++++++++++++++++-
99cbc7
 tests/virfiletest.c |  1 +
99cbc7
 4 files changed, 47 insertions(+), 4 deletions(-)
99cbc7
99cbc7
diff --git a/cfg.mk b/cfg.mk
99cbc7
index 6bebd0ad9f..e3e94bf6f0 100644
99cbc7
--- a/cfg.mk
99cbc7
+++ b/cfg.mk
99cbc7
@@ -1216,7 +1216,7 @@ exclude_file_name_regexp--sc_prohibit_select = \
99cbc7
 	^cfg\.mk$$
99cbc7
 
99cbc7
 exclude_file_name_regexp--sc_prohibit_canonicalize_file_name = \
99cbc7
-  ^cfg\.mk$$
99cbc7
+  ^(cfg\.mk|tests/virfilemock\.c)$$
99cbc7
 
99cbc7
 exclude_file_name_regexp--sc_prohibit_raw_allocation = \
99cbc7
   ^(docs/hacking\.html\.in|src/util/viralloc\.[ch]|examples/.*|tests/(securityselinuxhelper|(vircgroup|nss)mock|commandhelper)\.c|tools/wireshark/src/packet-libvirt\.c)$$
99cbc7
diff --git a/src/util/virfile.c b/src/util/virfile.c
99cbc7
index e1dee7633a..716b55d770 100644
99cbc7
--- a/src/util/virfile.c
99cbc7
+++ b/src/util/virfile.c
99cbc7
@@ -3549,9 +3549,19 @@ virFileIsSharedFixFUSE(const char *path,
99cbc7
     char mntbuf[1024];
99cbc7
     char *mntDir = NULL;
99cbc7
     char *mntType = NULL;
99cbc7
+    char *canonPath = NULL;
99cbc7
     size_t maxMatching = 0;
99cbc7
     int ret = -1;
99cbc7
 
99cbc7
+    if (!(canonPath = virFileCanonicalizePath(path))) {
99cbc7
+        virReportSystemError(errno,
99cbc7
+                             _("unable to canonicalize %s"),
99cbc7
+                             path);
99cbc7
+        return -1;
99cbc7
+    }
99cbc7
+
99cbc7
+    VIR_DEBUG("Path canonicalization: %s->%s", path, canonPath);
99cbc7
+
99cbc7
     if (!(f = setmntent(PROC_MOUNTS, "r"))) {
99cbc7
         virReportSystemError(errno,
99cbc7
                              _("Unable to open %s"),
99cbc7
@@ -3563,7 +3573,7 @@ virFileIsSharedFixFUSE(const char *path,
99cbc7
         const char *p;
99cbc7
         size_t len = strlen(mb.mnt_dir);
99cbc7
 
99cbc7
-        if (!(p = STRSKIP(path, mb.mnt_dir)))
99cbc7
+        if (!(p = STRSKIP(canonPath, mb.mnt_dir)))
99cbc7
             continue;
99cbc7
 
99cbc7
         if (*(p - 1) != '/' && *p != '/' && *p != '\0')
99cbc7
@@ -3581,12 +3591,13 @@ virFileIsSharedFixFUSE(const char *path,
99cbc7
 
99cbc7
     if (STREQ_NULLABLE(mntType, "fuse.glusterfs")) {
99cbc7
         VIR_DEBUG("Found gluster FUSE mountpoint=%s for path=%s. "
99cbc7
-                  "Fixing shared FS type", mntDir, path);
99cbc7
+                  "Fixing shared FS type", mntDir, canonPath);
99cbc7
         *f_type = GFS2_MAGIC;
99cbc7
     }
99cbc7
 
99cbc7
     ret = 0;
99cbc7
  cleanup:
99cbc7
+    VIR_FREE(canonPath);
99cbc7
     VIR_FREE(mntType);
99cbc7
     VIR_FREE(mntDir);
99cbc7
     endmntent(f);
99cbc7
diff --git a/tests/virfilemock.c b/tests/virfilemock.c
99cbc7
index 822c757380..ae5c8d025a 100644
99cbc7
--- a/tests/virfilemock.c
99cbc7
+++ b/tests/virfilemock.c
99cbc7
@@ -28,11 +28,14 @@
99cbc7
 #endif
99cbc7
 
99cbc7
 #include "virmock.h"
99cbc7
+#include "virstring.h"
99cbc7
+#include "viralloc.h"
99cbc7
 
99cbc7
 #define VIR_FROM_THIS VIR_FROM_NONE
99cbc7
 
99cbc7
 static FILE *(*real_setmntent)(const char *filename, const char *type);
99cbc7
 static int (*real_statfs)(const char *path, struct statfs *buf);
99cbc7
+static char *(*real_canonicalize_file_name)(const char *path);
99cbc7
 
99cbc7
 
99cbc7
 static void
99cbc7
@@ -43,6 +46,7 @@ init_syms(void)
99cbc7
 
99cbc7
     VIR_MOCK_REAL_INIT(setmntent);
99cbc7
     VIR_MOCK_REAL_INIT(statfs);
99cbc7
+    VIR_MOCK_REAL_INIT(canonicalize_file_name);
99cbc7
 }
99cbc7
 
99cbc7
 
99cbc7
@@ -94,6 +98,7 @@ statfs_mock(const char *mtab,
99cbc7
     FILE *f;
99cbc7
     struct mntent mb;
99cbc7
     char mntbuf[1024];
99cbc7
+    char *canonPath = NULL;
99cbc7
     int ret = -1;
99cbc7
 
99cbc7
     if (!(f = real_setmntent(mtab, "r"))) {
99cbc7
@@ -101,10 +106,16 @@ statfs_mock(const char *mtab,
99cbc7
         return -1;
99cbc7
     }
99cbc7
 
99cbc7
+    /* We don't need to do this in callers because real statfs(2)
99cbc7
+     * does that for us. However, in mocked implementation we
99cbc7
+     * need to do this. */
99cbc7
+    if (!(canonPath = canonicalize_file_name(path)))
99cbc7
+        return -1;
99cbc7
+
99cbc7
     while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) {
99cbc7
         int ftype;
99cbc7
 
99cbc7
-        if (STRNEQ(mb.mnt_dir, path))
99cbc7
+        if (STRNEQ(mb.mnt_dir, canonPath))
99cbc7
             continue;
99cbc7
 
99cbc7
         if (STREQ(mb.mnt_type, "nfs") ||
99cbc7
@@ -136,6 +147,7 @@ statfs_mock(const char *mtab,
99cbc7
     }
99cbc7
 
99cbc7
     endmntent(f);
99cbc7
+    VIR_FREE(canonPath);
99cbc7
     return ret;
99cbc7
 }
99cbc7
 
99cbc7
@@ -152,3 +164,22 @@ statfs(const char *path, struct statfs *buf)
99cbc7
 
99cbc7
     return real_statfs(path, buf);
99cbc7
 }
99cbc7
+
99cbc7
+
99cbc7
+char *
99cbc7
+canonicalize_file_name(const char *path)
99cbc7
+{
99cbc7
+    if (getenv("LIBVIRT_MTAB")) {
99cbc7
+        const char *p;
99cbc7
+        char *ret;
99cbc7
+
99cbc7
+        if ((p = STRSKIP(path, "/some/symlink")))
99cbc7
+            ignore_value(virAsprintfQuiet(&ret, "/gluster%s", p));
99cbc7
+        else
99cbc7
+            ignore_value(VIR_STRDUP_QUIET(ret, path));
99cbc7
+
99cbc7
+        return ret;
99cbc7
+    }
99cbc7
+
99cbc7
+    return real_canonicalize_file_name(path);
99cbc7
+}
99cbc7
diff --git a/tests/virfiletest.c b/tests/virfiletest.c
99cbc7
index be4dbf8910..a246d601ba 100644
99cbc7
--- a/tests/virfiletest.c
99cbc7
+++ b/tests/virfiletest.c
99cbc7
@@ -457,6 +457,7 @@ mymain(void)
99cbc7
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/nfs/blah", false);
99cbc7
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/file", true);
99cbc7
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/sshfs/file", false);
99cbc7
+    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/some/symlink/file", true);
99cbc7
 
99cbc7
     return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
99cbc7
 }
99cbc7
-- 
99cbc7
2.21.0
99cbc7