/* preserve_ns: open /proc/@pid/ns/@ns for each namespace specified * in clone_flags. * Return true on success, false on failure. */ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid) { int i, ret; for (i = 0; i < LXC_NS_MAX; i++) ns_fd[i] = -1; ret = lxc_preserve_ns(pid, ""); if (ret < 0) { SYSERROR("Kernel does not support attaching to namespaces."); return false; } else { close(ret); } for (i = 0; i < LXC_NS_MAX; i++) { if ((clone_flags & ns_info[i].clone_flag) == 0) continue; ns_fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name); if (ns_fd[i] < 0) goto error; } return true; error: if (errno == ENOENT) SYSERROR("Kernel does not support attaching to %s namespaces.", ns_info[i].proc_name); else SYSERROR("Failed to open file descriptor for %s namespace: %s.", ns_info[i].proc_name, strerror(errno)); close_ns(ns_fd); return false; }
static int lxc_attach_to_ns(pid_t pid, int which) { int fd[LXC_NS_MAX]; int i, j, saved_errno; if (access("/proc/self/ns", X_OK)) { ERROR("Does this kernel version support namespaces?"); return -1; } for (i = 0; i < LXC_NS_MAX; i++) { /* Ignore if we are not supposed to attach to that namespace. */ if (which != -1 && !(which & ns_info[i].clone_flag)) { fd[i] = -1; continue; } fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name); if (fd[i] < 0) { saved_errno = errno; /* Close all already opened file descriptors before we * return an error, so we don't leak them. */ for (j = 0; j < i; j++) close(fd[j]); errno = saved_errno; SYSERROR("Failed to open namespace: \"%s\".", ns_info[i].proc_name); return -1; } } for (i = 0; i < LXC_NS_MAX; i++) { if (fd[i] < 0) continue; if (setns(fd[i], 0) < 0) { saved_errno = errno; for (j = i; j < LXC_NS_MAX; j++) close(fd[j]); errno = saved_errno; SYSERROR("Failed to attach to namespace \"%s\".", ns_info[i].proc_name); return -1; } DEBUG("Attached to namespace \"%s\".", ns_info[i].proc_name); close(fd[i]); } return 0; }