mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-09 07:22:15 +00:00
lxc-attach: Detect which namespaces to attach to dynamically
Use the command interface to contact lxc-start to receive the set of flags passed to clone() when starting the container. This allows lxc-attach to determine which namespaces were used for the container and select only those to attach to. Signed-off-by: Christian Seiler <christian@iwakd.de> Cc: Daniel Lezcano <daniel.lezcano@free.fr> Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
This commit is contained in:
parent
c8f7c5630e
commit
fc763ab77d
@ -121,13 +121,22 @@ out_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lxc_attach_to_ns(pid_t pid)
|
||||
int lxc_attach_to_ns(pid_t pid, int which)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *ns[] = { "pid", "mnt", "net", "ipc", "uts" };
|
||||
const int size = sizeof(ns) / sizeof(char *);
|
||||
/* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
|
||||
* the file for user namepsaces in /proc/$pid/ns will be called
|
||||
* 'user' once the kernel supports it
|
||||
*/
|
||||
static char *ns[] = { "mnt", "pid", "uts", "ipc", "user", "net" };
|
||||
static int flags[] = {
|
||||
CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
|
||||
CLONE_NEWUSER, CLONE_NEWNET
|
||||
};
|
||||
static const int size = sizeof(ns) / sizeof(char *);
|
||||
int fd[size];
|
||||
int i;
|
||||
int i, j, saved_errno;
|
||||
|
||||
|
||||
snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid);
|
||||
if (access(path, X_OK)) {
|
||||
@ -136,16 +145,39 @@ int lxc_attach_to_ns(pid_t pid)
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
/* ignore if we are not supposed to attach to that
|
||||
* namespace
|
||||
*/
|
||||
if (which != -1 && !(which & flags[i])) {
|
||||
fd[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]);
|
||||
fd[i] = open(path, O_RDONLY);
|
||||
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 '%s'", path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (setns(fd[i], 0)) {
|
||||
if (fd[i] >= 0 && setns(fd[i], 0) != 0) {
|
||||
saved_errno = errno;
|
||||
|
||||
for (j = i; j < size; j++)
|
||||
close(fd[j]);
|
||||
|
||||
errno = saved_errno;
|
||||
SYSERROR("failed to set namespace '%s'", ns[i]);
|
||||
return -1;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ struct lxc_proc_context_info {
|
||||
|
||||
extern struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid);
|
||||
|
||||
extern int lxc_attach_to_ns(pid_t other_pid);
|
||||
extern int lxc_attach_to_ns(pid_t other_pid, int which);
|
||||
extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx);
|
||||
|
||||
#endif
|
||||
|
@ -51,6 +51,7 @@ static const struct option my_longopts[] = {
|
||||
|
||||
static int elevated_privileges = 0;
|
||||
static signed long new_personality = -1;
|
||||
static int namespace_flags = -1;
|
||||
|
||||
static int my_parser(struct lxc_arguments* args, int c, char* arg)
|
||||
{
|
||||
@ -139,11 +140,24 @@ int main(int argc, char *argv[])
|
||||
|
||||
curdir = get_current_dir_name();
|
||||
|
||||
/* determine which namespaces the container was created with
|
||||
* by asking lxc-start
|
||||
*/
|
||||
if (namespace_flags == -1) {
|
||||
namespace_flags = lxc_get_clone_flags(my_args.name);
|
||||
/* call failed */
|
||||
if (namespace_flags == -1) {
|
||||
ERROR("failed to automatically determine the "
|
||||
"namespaces which the container unshared");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we need to attach before we fork since certain namespaces
|
||||
* (such as pid namespaces) only really affect children of the
|
||||
* current process and not the process itself
|
||||
*/
|
||||
ret = lxc_attach_to_ns(init_pid);
|
||||
ret = lxc_attach_to_ns(init_pid, namespace_flags);
|
||||
if (ret < 0) {
|
||||
ERROR("failed to enter the namespace");
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user