From time to time weird bugreports occur on the list, e.g [1].
Even though the kernel supports setns syscall, there's an older
glibc in the system that misses a wrapper over the syscall.
Hence, after the configure phase we think there's no setns
support in the system, which is obviously wrong. On the other
hand, we can't rely on linux distributions to provide newer glibc
soon. Therefore we need to introduce the wrapper on or own.
1:
https://www.redhat.com/archives/libvir-list/2014-September/msg00492.html
Signed-off-by: Stephan Sachse <ste.sachse(a)gmail.com>
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
The original patch was ACKed already, I've just rebased it to the
current master, and moved the wrapper declaration into
virprocess.c as we don't need to pollute the header file. I've
pushed this then.
src/util/virprocess.c | 57 ++++++++++++++++++++++-----------------------------
1 file changed, 24 insertions(+), 33 deletions(-)
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 97cce4f..b6fcbac 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -27,6 +27,8 @@
#include <errno.h>
#include <stdlib.h>
#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/syscall.h>
#if HAVE_SETRLIMIT
# include <sys/time.h>
# include <sys/resource.h>
@@ -60,6 +62,28 @@
VIR_LOG_INIT("util.process");
+/*
+ * Workaround older glibc. While kernel may support the setns
+ * syscall, the glibc wrapper might not exist. If that's the
+ * case, use our own.
+ */
+#ifndef __NR_setns
+# if defined(__x86_64__)
+# define __NR_setns 308
+# elif defined(__i386__)
+# define __NR_setns 346
+# else
+# error "__NR_setns is not defined"
+# endif
+#endif
+
+#ifndef HAVE_SETNS
+static inline int setns(int fd, int nstype)
+{
+ return syscall(__NR_setns, fd, nstype);
+}
+#endif /* HAVE_SETNS */
+
/**
* virProcessTranslateStatus:
* @status: child exit status to translate
@@ -559,7 +583,6 @@ int virProcessGetAffinity(pid_t pid ATTRIBUTE_UNUSED,
#endif /* HAVE_SCHED_GETAFFINITY */
-#if HAVE_SETNS
int virProcessGetNamespaces(pid_t pid,
size_t *nfdlist,
int **fdlist)
@@ -630,26 +653,6 @@ int virProcessSetNamespaces(size_t nfdlist,
}
return 0;
}
-#else /* ! HAVE_SETNS */
-int virProcessGetNamespaces(pid_t pid,
- size_t *nfdlist ATTRIBUTE_UNUSED,
- int **fdlist ATTRIBUTE_UNUSED)
-{
- virReportSystemError(ENOSYS,
- _("Cannot get namespaces for %llu"),
- (unsigned long long)pid);
- return -1;
-}
-
-
-int virProcessSetNamespaces(size_t nfdlist ATTRIBUTE_UNUSED,
- int *fdlist ATTRIBUTE_UNUSED)
-{
- virReportSystemError(ENOSYS, "%s",
- _("Cannot set namespaces"));
- return -1;
-}
-#endif /* ! HAVE_SETNS */
#if HAVE_PRLIMIT
static int
@@ -905,7 +908,6 @@ int virProcessGetStartTime(pid_t pid,
#endif
-#ifdef HAVE_SETNS
static int virProcessNamespaceHelper(int errfd,
pid_t pid,
virProcessNamespaceCallback cb,
@@ -992,17 +994,6 @@ virProcessRunInMountNamespace(pid_t pid,
VIR_FORCE_CLOSE(errfd[1]);
return ret;
}
-#else /* !HAVE_SETNS */
-int
-virProcessRunInMountNamespace(pid_t pid ATTRIBUTE_UNUSED,
- virProcessNamespaceCallback cb ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED)
-{
- virReportSystemError(ENOSYS, "%s",
- _("Mount namespaces are not available on this
platform"));
- return -1;
-}
-#endif
/**
--
1.8.5.5