[lxc-devel] [PATCH v3 3/6] lxc-attach: Detect which namespaces to attach to dynamically
Serge Hallyn
serge.hallyn at canonical.com
Thu May 24 14:17:44 UTC 2012
Quoting Christian Seiler (christian at iwakd.de):
> 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 at iwakd.de>
> Cc: Daniel Lezcano <daniel.lezcano at free.fr>
> Cc: Serge Hallyn <serge.hallyn at canonical.com>
Looks nice, thanks.
Acked-by: Serge Hallyn <serge.hallyn at canonical.com>
> ---
> src/lxc/attach.c | 42 +++++++++++++++++++++++++++++++++++++-----
> src/lxc/attach.h | 2 +-
> src/lxc/lxc_attach.c | 16 +++++++++++++++-
> 3 files changed, 53 insertions(+), 7 deletions(-)
>
> diff --git a/src/lxc/attach.c b/src/lxc/attach.c
> index a95b3d3..37e667f 100644
> --- a/src/lxc/attach.c
> +++ b/src/lxc/attach.c
> @@ -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;
> }
> diff --git a/src/lxc/attach.h b/src/lxc/attach.h
> index 2d46c83..d96fdae 100644
> --- a/src/lxc/attach.h
> +++ b/src/lxc/attach.h
> @@ -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
> diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
> index e4f604b..10d4a64 100644
> --- a/src/lxc/lxc_attach.c
> +++ b/src/lxc/lxc_attach.c
> @@ -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;
> --
> 1.7.2.5
>
More information about the lxc-devel
mailing list