diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 8a263f490..5a42cc29e 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -249,24 +249,89 @@ static void lxc_proc_put_context_info(struct lxc_proc_context_info *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/= 0) + close(ns_fd1); + if (ns_fd2 >= 0) + close(ns_fd2); + + return ret; +} + static int lxc_attach_to_ns(pid_t pid, int which) { 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?"); return -1; } for (i = 0; i < LXC_NS_MAX; i++) { + fd[i] = -EINVAL; + /* Ignore if we are not supposed to attach to that namespace. */ if (which != -1 && !(which & ns_info[i].clone_flag)) { - fd[i] = -1; - continue; + /* We likely inherited the namespace from someone. We + * 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) { saved_errno = errno; @@ -277,8 +342,8 @@ static int lxc_attach_to_ns(pid_t pid, int which) close(fd[j]); errno = saved_errno; - SYSERROR("Failed to open namespace: \"%s\".", - ns_info[i].proc_name); + SYSERROR("Failed to attach to %s namespace of %d", + ns_info[i].proc_name, pid); return -1; } } @@ -294,12 +359,12 @@ static int lxc_attach_to_ns(pid_t pid, int which) close(fd[j]); errno = saved_errno; - SYSERROR("Failed to attach to namespace \"%s\".", - ns_info[i].proc_name); + SYSERROR("Failed to attach to %s namespace of %d", + ns_info[i].proc_name, pid); 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]); }