提交 68eea850 编写于 作者: R Richard Weinberger 提交者: Daniel P. Berrange

Fix ordering of file open in virProcessGetNamespaces

virProcessGetNamespaces() opens files in /proc/XXX/ns/ which will
later be passed to setns(). We have to make sure that the file
descriptors in the array are in the correct order. In particular
the 'user' namespace must be first otherwise setns() may fail
for other namespaces.

The order has been taken from util-linux's sys-utils/nsenter.c

Also we must ignore EINVAL in setns() which occurs if the
namespace associated with the fd, matches the calling process'
current namespace.
Signed-off-by: NRichard Weinberger <richard@nod.at>
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
上级 e463f4de
......@@ -22,7 +22,6 @@
#include <config.h>
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
......@@ -513,66 +512,43 @@ int virProcessGetNamespaces(pid_t pid,
int **fdlist)
{
int ret = -1;
DIR *dh = NULL;
struct dirent *de;
char *nsdir = NULL;
char *nsfile = NULL;
size_t i;
size_t i = 0;
const char *ns[] = { "user", "ipc", "uts", "net", "pid", "mnt" };
*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))) {
for (i = 0; i < ARRAY_CARDINALITY(ns); i++) {
int fd;
if (de->d_name[0] == '.')
continue;
if (VIR_EXPAND_N(*fdlist, *nfdlist, 1) < 0) {
if (virAsprintf(&nsfile, "/proc/%llu/ns/%s",
(unsigned long long)pid,
ns[i]) < 0) {
virReportOOMError();
goto cleanup;
}
if (virAsprintf(&nsfile, "%s/%s", nsdir, de->d_name) < 0) {
virReportOOMError();
goto cleanup;
}
if ((fd = open(nsfile, O_RDWR)) >= 0) {
if (VIR_EXPAND_N(*fdlist, *nfdlist, 1) < 0) {
VIR_FORCE_CLOSE(fd);
virReportOOMError();
goto cleanup;
}
if ((fd = open(nsfile, O_RDWR)) < 0) {
virReportSystemError(errno,
_("Unable to open %s"),
nsfile);
goto cleanup;
(*fdlist)[(*nfdlist)-1] = fd;
}
(*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++) {
for (i = 0; i < *nfdlist; i++)
VIR_FORCE_CLOSE((*fdlist)[i]);
}
VIR_FREE(*fdlist);
}
return ret;
......@@ -590,7 +566,13 @@ int virProcessSetNamespaces(size_t nfdlist,
return -1;
}
for (i = 0; i < nfdlist; i++) {
if (setns(fdlist[i], 0) < 0) {
/* We get EINVAL if new NS is same as the current
* NS, or if the fd namespace doesn't match the
* type passed to setns()'s second param. Since we
* pass 0, we know the EINVAL is harmless
*/
if (setns(fdlist[i], 0) < 0 &&
errno != EINVAL) {
virReportSystemError(errno, "%s",
_("Unable to join domain namespace"));
return -1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册