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