diff --git a/src/lxc/attach.c b/src/lxc/attach.c index aedd403ad..4bfdf23cf 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -165,8 +165,7 @@ static inline bool sync_wait_fd(int fd, int *fd_recv) static bool attach_lsm(lxc_attach_options_t *options) { - return (options->namespaces & CLONE_NEWNS) && - (options->attach_flags & (LXC_ATTACH_LSM | LXC_ATTACH_LSM_LABEL)); + return (options->attach_flags & (LXC_ATTACH_LSM | LXC_ATTACH_LSM_LABEL)); } static struct attach_context *alloc_attach_context(void) diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h index 46d1ecd89..8187ecac0 100644 --- a/src/lxc/attach_options.h +++ b/src/lxc/attach_options.h @@ -65,7 +65,7 @@ enum { }; /*! All Linux Security Module flags */ -#define LXC_ATTACH_LSM (LXC_ATTACH_LSM_EXEC | LXC_ATTACH_LSM_NOW) +#define LXC_ATTACH_LSM (LXC_ATTACH_LSM_EXEC | LXC_ATTACH_LSM_NOW | LXC_ATTACH_LSM_LABEL) /*! LXC attach function type. * diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 45b950529..bf190e08b 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -3252,10 +3252,10 @@ int lxc_config_parse_arch(const char *arch, signed long *persona) return ret_errno(EINVAL); } -int lxc_fill_elevated_privileges(char *flaglist, int *flags) +int lxc_fill_elevated_privileges(char *flaglist, unsigned int *flags) { + unsigned int flags_tmp = 0; char *token; - int i, aflag; struct { const char *token; int flag; @@ -3267,28 +3267,33 @@ int lxc_fill_elevated_privileges(char *flaglist, int *flags) }; if (!flaglist) { - /* For the sake of backward compatibility, drop all privileges - * if none is specified. + /* + * For the sake of backward compatibility, keep all privileges + * if no specific privileges are specified. */ - for (i = 0; all_privs[i].token; i++) - *flags |= all_privs[i].flag; + for (unsigned int i = 0; all_privs[i].token; i++) + flags_tmp |= all_privs[i].flag; + *flags = flags_tmp; return 0; } lxc_iterate_parts(token, flaglist, "|") { - aflag = -1; + bool valid_token = false; - for (i = 0; all_privs[i].token; i++) - if (strequal(all_privs[i].token, token)) - aflag = all_privs[i].flag; + for (unsigned int i = 0; all_privs[i].token; i++) { + if (!strequal(all_privs[i].token, token)) + continue; - if (aflag < 0) - return ret_errno(EINVAL); + valid_token = true; + flags_tmp |= all_privs[i].flag; + } - *flags |= aflag; + if (!valid_token) + return syserror_set(-EINVAL, "Invalid elevated privilege \"%s\" requested", token); } + *flags = flags_tmp; return 0; } diff --git a/src/lxc/confile.h b/src/lxc/confile.h index 96c589189..999dc1648 100644 --- a/src/lxc/confile.h +++ b/src/lxc/confile.h @@ -89,7 +89,7 @@ __hidden extern void lxc_config_define_free(struct lxc_list *defines); */ __hidden extern int lxc_config_parse_arch(const char *arch, signed long *persona); -__hidden extern int lxc_fill_elevated_privileges(char *flaglist, int *flags); +__hidden extern int lxc_fill_elevated_privileges(char *flaglist, unsigned int *flags); __hidden extern int lxc_clear_config_item(struct lxc_conf *c, const char *key); diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c index bce2e1cae..0374d980b 100644 --- a/src/lxc/tools/lxc_attach.c +++ b/src/lxc/tools/lxc_attach.c @@ -52,7 +52,7 @@ static int add_to_simple_array(char ***array, ssize_t *capacity, char *value); static bool stdfd_is_pty(void); static int lxc_attach_create_log_file(const char *log_file); -static int elevated_privileges; +static unsigned int elevated_privileges; static signed long new_personality = -1; static int namespace_flags = -1; static int remount_sys_proc; @@ -277,10 +277,11 @@ int main(int argc, char *argv[]) { int ret = -1; int wexit = 0; - struct lxc_log log; - pid_t pid; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL}; + pid_t pid; + struct lxc_container *c; + struct lxc_log log; if (lxc_caps_init()) exit(EXIT_FAILURE); @@ -288,12 +289,12 @@ int main(int argc, char *argv[]) if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); - log.name = my_args.name; - log.file = my_args.log_file; - log.level = my_args.log_priority; - log.prefix = my_args.progname; - log.quiet = my_args.quiet; - log.lxcpath = my_args.lxcpath[0]; + log.name = my_args.name; + log.file = my_args.log_file; + log.level = my_args.log_priority; + log.prefix = my_args.progname; + log.quiet = my_args.quiet; + log.lxcpath = my_args.lxcpath[0]; if (lxc_log_init(&log)) exit(EXIT_FAILURE); @@ -304,7 +305,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - struct lxc_container *c = lxc_container_new(my_args.name, my_args.lxcpath[0]); + c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) exit(EXIT_FAILURE); @@ -333,21 +334,36 @@ int main(int argc, char *argv[]) if (remount_sys_proc) attach_options.attach_flags |= LXC_ATTACH_REMOUNT_PROC_SYS; - if (elevated_privileges) + if (elevated_privileges) { + if ((elevated_privileges & LXC_ATTACH_LSM_EXEC)) { + if (selinux_context) { + ERROR("Cannot combine elevated LSM privileges while requesting LSM profile"); + goto out; + } + + /* + * While most LSM flags are off by default let's still + * make sure they are stripped when elevated LSM + * privileges are requested. + */ + elevated_privileges |= LXC_ATTACH_LSM; + } + attach_options.attach_flags &= ~(elevated_privileges); + } if (stdfd_is_pty()) attach_options.attach_flags |= LXC_ATTACH_TERMINAL; - attach_options.namespaces = namespace_flags; - attach_options.personality = new_personality; - attach_options.env_policy = env_policy; - attach_options.extra_env_vars = extra_env; - attach_options.extra_keep_env = extra_keep; + attach_options.namespaces = namespace_flags; + attach_options.personality = new_personality; + attach_options.env_policy = env_policy; + attach_options.extra_env_vars = extra_env; + attach_options.extra_keep_env = extra_keep; if (my_args.argc > 0) { command.program = my_args.argv[0]; - command.argv = (char**)my_args.argv; + command.argv = (char**)my_args.argv; } if (my_args.console_log) {