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