diff --git a/configure.ac b/configure.ac index 20108c295e..1c601d277e 100644 --- a/configure.ac +++ b/configure.ac @@ -180,7 +180,7 @@ dnl Availability of various common functions (non-fatal if missing), dnl and various less common threadsafe functions AC_CHECK_FUNCS_ONCE([cfmakeraw geteuid getgid getgrnam_r getmntent_r \ getpwuid_r getuid initgroups kill mmap newlocale posix_fallocate \ - posix_memalign regexec sched_getaffinity]) + posix_memalign regexec sched_getaffinity setns]) dnl Availability of pthread functions (if missing, win32 threading is dnl assumed). Because of $LIB_PTHREAD, we cannot use AC_CHECK_FUNCS_ONCE. diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d9b7c1d865..d079cc9043 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1795,9 +1795,11 @@ virPidFileWritePath; # virprocess.h virProcessAbort; virProcessGetAffinity; +virProcessGetNamespaces; virProcessKill; virProcessKillPainfully; virProcessSetAffinity; +virProcessSetNamespaces; virProcessTranslateStatus; virProcessWait; diff --git a/src/util/virprocess.c b/src/util/virprocess.c index 0858553004..a492bd11f7 100644 --- a/src/util/virprocess.c +++ b/src/util/virprocess.c @@ -22,6 +22,8 @@ #include +#include +#include #include #include #include @@ -30,6 +32,7 @@ #include "virprocess.h" #include "virerror.h" #include "viralloc.h" +#include "virfile.h" #include "virlog.h" #include "virutil.h" @@ -489,3 +492,116 @@ int virProcessGetAffinity(pid_t pid ATTRIBUTE_UNUSED, return -1; } #endif /* HAVE_SCHED_GETAFFINITY */ + + +#if HAVE_SETNS +int virProcessGetNamespaces(pid_t pid, + size_t *nfdlist, + int **fdlist) +{ + int ret = -1; + DIR *dh = NULL; + struct dirent *de; + char *nsdir = NULL; + char *nsfile = NULL; + size_t i; + + *nfdlist = 0; + *fdlist = NULL; + + if (virAsprintf(&nsdir, "/proc/%llu/ns", + (unsigned long long)pid) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (!(dh = opendir(nsdir))) { + virReportSystemError(errno, + _("Cannot read directory %s"), + nsdir); + goto cleanup; + } + + while ((de = readdir(dh))) { + int fd; + if (de->d_name[0] == '.') + continue; + + if (VIR_EXPAND_N(*fdlist, *nfdlist, 1) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virAsprintf(&nsfile, "%s/%s", nsdir, de->d_name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((fd = open(nsfile, O_RDWR)) < 0) { + virReportSystemError(errno, + _("Unable to open %s"), + nsfile); + goto cleanup; + } + + (*fdlist)[(*nfdlist)-1] = fd; + + VIR_FREE(nsfile); + } + + ret = 0; + +cleanup: + if (dh) + closedir(dh); + VIR_FREE(nsdir); + VIR_FREE(nsfile); + if (ret < 0) { + for (i = 0 ; i < *nfdlist ; i++) { + VIR_FORCE_CLOSE((*fdlist)[i]); + } + VIR_FREE(*fdlist); + } + return ret; +} + + +int virProcessSetNamespaces(size_t nfdlist, + int *fdlist) +{ + size_t i; + + if (nfdlist == 0) { + virReportInvalidArg(nfdlist, "%s", + _("Expected at least one file descriptor")); + return -1; + } + for (i = 0 ; i < nfdlist ; i++) { + if (setns(fdlist[i], 0) < 0) { + virReportSystemError(errno, "%s", + _("Unable to join domain namespace")); + return -1; + } + } + 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 */ diff --git a/src/util/virprocess.h b/src/util/virprocess.h index 8724f649f2..53475d3cc3 100644 --- a/src/util/virprocess.h +++ b/src/util/virprocess.h @@ -47,4 +47,11 @@ int virProcessGetAffinity(pid_t pid, virBitmapPtr *map, int maxcpu); +int virProcessGetNamespaces(pid_t pid, + size_t *nfdlist, + int **fdlist); + +int virProcessSetNamespaces(size_t nfdlist, + int *fdlist); + #endif /* __VIR_PROCESS_H__ */