aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Seiler <christian@iwakd.de>2012-02-23 09:57:14 +0100
committerDaniel Lezcano <daniel.lezcano@free.fr>2012-02-23 09:57:14 +0100
commitcb014488ee24072579837439389552ce3d6cbb83 (patch)
tree37e4cd0cc7e4ecc6e061909e9dd8be67f7149a00
parentMove lxc_attach from namespace.c to attach.c and rename it to lxc_attach_to_ns (diff)
downloadlxc-cb014488ee24072579837439389552ce3d6cbb83.tar.gz
lxc-cb014488ee24072579837439389552ce3d6cbb83.tar.bz2
lxc-cb014488ee24072579837439389552ce3d6cbb83.zip
lxc-attach: Drop privileges when attaching to container unless requested otherwise
lxc-attach will now put the process that is attached to the container into the correct cgroups corresponding to the container, set the correct personality and drop the privileges. The information is extracted from entries in /proc of the init process of the container. Note that this relies on the (reasonable) assumption that the init process does not in fact drop additional capabilities from its bounding set. Additionally, 2 command line options are added to lxc-attach: One to prevent the capabilities from being dropped and the process from being put into the cgroup (-e, --elevated-privileges) and a second one to explicitly state the architecture which the process will see, (-a, --arch) which defaults to the container's current architecture. Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
-rw-r--r--src/lxc/lxc_attach.c115
1 files changed, 102 insertions, 13 deletions
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index c8643d1..3571b09 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -29,19 +29,45 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/personality.h>
#include "attach.h"
#include "commands.h"
#include "arguments.h"
#include "caps.h"
+#include "attach.h"
+#include "confile.h"
+#include "start.h"
+#include "sync.h"
#include "log.h"
lxc_log_define(lxc_attach_ui, lxc);
static const struct option my_longopts[] = {
+ {"elevated-privileges", no_argument, 0, 'e'},
+ {"arch", required_argument, 0, 'a'},
LXC_COMMON_OPTIONS
};
+static int elevated_privileges = 0;
+static signed long new_personality = -1;
+
+static int my_parser(struct lxc_arguments* args, int c, char* arg)
+{
+ switch (c) {
+ case 'e': elevated_privileges = 1; break;
+ case 'a':
+ new_personality = lxc_config_parse_arch(arg);
+ if (new_personality < 0) {
+ lxc_error(args, "invalid architecture specified: %s", arg);
+ return -1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
static struct lxc_arguments my_args = {
.progname = "lxc-attach",
.help = "\
@@ -50,17 +76,26 @@ static struct lxc_arguments my_args = {
Execute the specified command - enter the container NAME\n\
\n\
Options :\n\
- -n, --name=NAME NAME for name of the container\n",
+ -n, --name=NAME NAME for name of the container\n\
+ -e, --elevated-privileges\n\
+ Use elevated privileges (capabilities, cgroup\n\
+ restrictions) instead of those of the container.\n\
+ WARNING: This may leak privleges into the container.\n\
+ Use with care.\n\
+ -a, --arch=ARCH Use ARCH for program instead of container's own\n\
+ architecture.\n",
.options = my_longopts,
- .parser = NULL,
+ .parser = my_parser,
.checker = NULL,
};
int main(int argc, char *argv[], char *envp[])
{
int ret;
- pid_t pid;
+ pid_t pid, init_pid;
struct passwd *passwd;
+ struct lxc_proc_context_info *init_ctx;
+ struct lxc_handler *handler;
uid_t uid;
char *curdir;
@@ -77,24 +112,25 @@ int main(int argc, char *argv[], char *envp[])
if (ret)
return ret;
- pid = get_init_pid(my_args.name);
- if (pid < 0) {
+ init_pid = get_init_pid(my_args.name);
+ if (init_pid < 0) {
ERROR("failed to get the init pid");
return -1;
}
- curdir = get_current_dir_name();
-
- ret = lxc_attach_to_ns(pid);
- if (ret < 0) {
- ERROR("failed to enter the namespace");
+ init_ctx = lxc_proc_get_context_info(init_pid);
+ if (!init_ctx) {
+ ERROR("failed to get context of the init process, pid = %d", init_pid);
return -1;
}
- if (curdir && chdir(curdir))
- WARN("could not change directory to '%s'", curdir);
+ /* hack: we need sync.h infrastructure - and that needs a handler */
+ handler = calloc(1, sizeof(*handler));
- free(curdir);
+ if (lxc_sync_init(handler)) {
+ ERROR("failed to initialize synchronization socket");
+ return -1;
+ }
pid = fork();
@@ -106,6 +142,23 @@ int main(int argc, char *argv[], char *envp[])
if (pid) {
int status;
+ lxc_sync_fini_child(handler);
+
+ /* wait until the child has done configuring itself before
+ * we put it in a cgroup that potentially limits these
+ * possibilities */
+ if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
+ return -1;
+
+ if (!elevated_privileges && lxc_attach_proc_to_cgroups(pid, init_ctx))
+ return -1;
+
+ /* tell the child we are done initializing */
+ if (lxc_sync_wake_child(handler, LXC_SYNC_POST_CONFIGURE))
+ return -1;
+
+ lxc_sync_fini(handler);
+
again:
if (waitpid(pid, &status, 0) < 0) {
if (errno == EINTR)
@@ -121,6 +174,42 @@ int main(int argc, char *argv[], char *envp[])
}
if (!pid) {
+ lxc_sync_fini_parent(handler);
+
+ curdir = get_current_dir_name();
+
+ ret = lxc_attach_to_ns(init_pid);
+ if (ret < 0) {
+ ERROR("failed to enter the namespace");
+ return -1;
+ }
+
+ if (curdir && chdir(curdir))
+ WARN("could not change directory to '%s'", curdir);
+
+ free(curdir);
+
+ if (new_personality < 0)
+ new_personality = init_ctx->personality;
+
+ if (personality(new_personality) == -1) {
+ ERROR("could not ensure correct architecture: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (!elevated_privileges && lxc_attach_drop_privs(init_ctx)) {
+ ERROR("could not drop privileges");
+ return -1;
+ }
+
+ /* tell parent we are done setting up the container and wait
+ * until we have been put in the container's cgroup, if
+ * applicable */
+ if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
+ return -1;
+
+ lxc_sync_fini(handler);
if (my_args.argc) {
execve(my_args.argv[0], my_args.argv, envp);