mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
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: Richard Weinberger <richard@nod.at> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
e463f4de77
commit
68eea85021
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user