mirror of
git://github.com/lxc/lxc
synced 2025-09-03 21:49:34 +00:00
Merge pull request #1883 from brauner/2017-10-29/fix_namespace_inheritance_on_attach
attach: correctly handle namespace inheritance
This commit is contained in:
@@ -249,24 +249,89 @@ static void lxc_proc_put_context_info(struct lxc_proc_context_info *ctx)
|
|||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in_same_namespace - Check whether two processes are in the same namespace.
|
||||||
|
* @pid1 - PID of the first process.
|
||||||
|
* @pid2 - PID of the second process.
|
||||||
|
* @ns - Name of the namespace to check. Must correspond to one of the names
|
||||||
|
* for the namespaces as shown in /proc/<pid/ns/
|
||||||
|
*
|
||||||
|
* If the two processes are not in the same namespace returns an fd to the
|
||||||
|
* namespace of the second process identified by @pid2. If the two processes are
|
||||||
|
* in the same namespace returns -EINVAL, -1 if an error occurred.
|
||||||
|
*/
|
||||||
|
static int in_same_namespace(pid_t pid1, pid_t pid2, const char *ns)
|
||||||
|
{
|
||||||
|
int ns_fd1 = -1, ns_fd2 = -1, ret = -1;
|
||||||
|
struct stat ns_st1, ns_st2;
|
||||||
|
|
||||||
|
ns_fd1 = lxc_preserve_ns(pid1, ns);
|
||||||
|
if (ns_fd1 < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ns_fd2 = lxc_preserve_ns(pid2, ns);
|
||||||
|
if (ns_fd2 < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = fstat(ns_fd1, &ns_st1);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = fstat(ns_fd2, &ns_st2);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* processes are in the same namespace */
|
||||||
|
ret = -EINVAL;
|
||||||
|
if ((ns_st1.st_dev == ns_st2.st_dev ) && (ns_st1.st_ino == ns_st2.st_ino))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* processes are in different namespaces */
|
||||||
|
ret = ns_fd2;
|
||||||
|
ns_fd2 = -1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
|
if (ns_fd1 >= 0)
|
||||||
|
close(ns_fd1);
|
||||||
|
if (ns_fd2 >= 0)
|
||||||
|
close(ns_fd2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int lxc_attach_to_ns(pid_t pid, int which)
|
static int lxc_attach_to_ns(pid_t pid, int which)
|
||||||
{
|
{
|
||||||
int fd[LXC_NS_MAX];
|
int fd[LXC_NS_MAX];
|
||||||
int i, j, saved_errno;
|
int i, j, ret, saved_errno;
|
||||||
|
|
||||||
if (access("/proc/self/ns", X_OK)) {
|
ret = access("/proc/self/ns", X_OK);
|
||||||
|
if (ret) {
|
||||||
ERROR("Does this kernel version support namespaces?");
|
ERROR("Does this kernel version support namespaces?");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < LXC_NS_MAX; i++) {
|
for (i = 0; i < LXC_NS_MAX; i++) {
|
||||||
|
fd[i] = -EINVAL;
|
||||||
|
|
||||||
/* Ignore if we are not supposed to attach to that namespace. */
|
/* Ignore if we are not supposed to attach to that namespace. */
|
||||||
if (which != -1 && !(which & ns_info[i].clone_flag)) {
|
if (which != -1 && !(which & ns_info[i].clone_flag)) {
|
||||||
fd[i] = -1;
|
/* We likely inherited the namespace from someone. We
|
||||||
continue;
|
* need to check whether we are already in the same
|
||||||
|
* namespace. If we are then there's nothing for us to
|
||||||
|
* do. If we are not then we need to attach to it.
|
||||||
|
*/
|
||||||
|
fd[i] = in_same_namespace(getpid(), pid, ns_info[i].proc_name);
|
||||||
|
/* we are in the same namespace */
|
||||||
|
if (fd[i] == -EINVAL) {
|
||||||
|
DEBUG("Inheriting %s namespace from %d",
|
||||||
|
ns_info[i].proc_name, pid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
|
if (fd[i] == -EINVAL)
|
||||||
|
fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
|
||||||
if (fd[i] < 0) {
|
if (fd[i] < 0) {
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
@@ -277,8 +342,8 @@ static int lxc_attach_to_ns(pid_t pid, int which)
|
|||||||
close(fd[j]);
|
close(fd[j]);
|
||||||
|
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
SYSERROR("Failed to open namespace: \"%s\".",
|
SYSERROR("Failed to attach to %s namespace of %d",
|
||||||
ns_info[i].proc_name);
|
ns_info[i].proc_name, pid);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,12 +359,12 @@ static int lxc_attach_to_ns(pid_t pid, int which)
|
|||||||
close(fd[j]);
|
close(fd[j]);
|
||||||
|
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
SYSERROR("Failed to attach to namespace \"%s\".",
|
SYSERROR("Failed to attach to %s namespace of %d",
|
||||||
ns_info[i].proc_name);
|
ns_info[i].proc_name, pid);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("Attached to namespace \"%s\".", ns_info[i].proc_name);
|
DEBUG("Attached to %s namespace of %d", ns_info[i].proc_name, pid);
|
||||||
|
|
||||||
close(fd[i]);
|
close(fd[i]);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user