Skip to content

Commit

Permalink
lxc-attach: elevate specific privileges
Browse files Browse the repository at this point in the history
There are scenarios in which we want to execute process with specific
privileges elevated.

An example for this might be executing a process inside the container
securely, with capabilities dropped, but not in container's cgroup so
that we can have per process restrictions inside single container.

Similar to namespaces, privileges to be elevated can be OR'd:

    lxc-attach --elevated-privileges='CAP|CGROUP' ...

Backward compatibility with previous versions is retained. In case no
privileges are specified behaviour is the same as before: all of them
are elevated.

Signed-off-by: Nikola Kotur <kotnick@gmail.com>
Acked-By: Christian Seiler <christian@iwakd.de>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information
kotnik authored and hallyn committed Nov 20, 2013
1 parent c7e426b commit 4d69b29
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 11 deletions.
13 changes: 12 additions & 1 deletion doc/lxc-attach.sgml.in
Expand Up @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

-->


<!DOCTYPE refentry PUBLIC @docdtd@ [

<!ENTITY commonoptions SYSTEM "@builddir@/common_options.sgml">
Expand Down Expand Up @@ -107,7 +108,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

<varlistentry>
<term>
<option>-e, --elevated-privileges</option>
<option>
-e, --elevated-privileges <replaceable>privileges</replaceable>
</option>
</term>
<listitem>
<para>
Expand All @@ -117,6 +120,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<emphasis>not</emphasis> be added to the container's cgroup(s)
and it will not drop its capabilities before executing.
</para>
<para>
You may specify privileges, in case you do not want to elevate all of
them, as a pipe-separated list, e.g.
<replaceable>CGROUP|LSM</replaceable>. Allowed values are
<replaceable>CGROUP</replaceable>, <replaceable>CAP</replaceable> and
<replaceable>LSM</replaceable> representing cgroup, capabilities and
restriction privileges respectively.
</para>
<para>
<emphasis>Warning:</emphasis> This may leak privileges into the
container if the command starts subprocesses that remain active
Expand Down
37 changes: 37 additions & 0 deletions src/lxc/confile.c
Expand Up @@ -1568,6 +1568,43 @@ signed long lxc_config_parse_arch(const char *arch)
return -1;
}

int lxc_fill_elevated_privileges(char *flaglist, int *flags)
{
char *token, *saveptr = NULL;
int i, aflag;
struct { const char *token; int flag; } all_privs[] = {
{ "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
{ "CAP", LXC_ATTACH_DROP_CAPABILITIES },
{ "LSM", LXC_ATTACH_LSM_EXEC },
{ NULL, 0 }
};

if (!flaglist) {
/* for the sake of backward compatibility, drop all privileges
if none is specified */
for (i = 0; all_privs[i].token; i++) {
*flags |= all_privs[i].flag;
}
return 0;
}

token = strtok_r(flaglist, "|", &saveptr);
while (token) {
aflag = -1;
for (i = 0; all_privs[i].token; i++) {
if (!strcmp(all_privs[i].token, token))
aflag = all_privs[i].flag;
}
if (aflag < 0)
return -1;

*flags |= aflag;

token = strtok_r(NULL, "|", &saveptr);
}
return 0;
}

static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v)
{
if (!retv)
Expand Down
2 changes: 2 additions & 0 deletions src/lxc/confile.h
Expand Up @@ -22,6 +22,7 @@
*/

#include <stdio.h>
#include "attach_options.h"

#ifndef _confile_h
#define _confile_h
Expand All @@ -47,6 +48,7 @@ extern int lxc_config_define_load(struct lxc_list *defines,

/* needed for lxc-attach */
extern signed long lxc_config_parse_arch(const char *arch);
extern int lxc_fill_elevated_privileges(char *flaglist, int *flags);

extern int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv, int inlen);
extern int lxc_clear_config_item(struct lxc_conf *c, const char *key);
Expand Down
28 changes: 18 additions & 10 deletions src/lxc/lxc_attach.c
Expand Up @@ -38,7 +38,7 @@
lxc_log_define(lxc_attach_ui, lxc);

static const struct option my_longopts[] = {
{"elevated-privileges", no_argument, 0, 'e'},
{"elevated-privileges", optional_argument, 0, 'e'},
{"arch", required_argument, 0, 'a'},
{"namespaces", required_argument, 0, 's'},
{"remount-sys-proc", no_argument, 0, 'R'},
Expand Down Expand Up @@ -87,7 +87,11 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
int ret;

switch (c) {
case 'e': elevated_privileges = 1; break;
case 'e':
ret = lxc_fill_elevated_privileges(arg, &elevated_privileges);
if (ret)
return -1;
break;
case 'R': remount_sys_proc = 1; break;
case 'a':
new_personality = lxc_config_parse_arch(arg);
Expand All @@ -102,7 +106,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
if (ret)
return -1;
/* -s implies -e */
elevated_privileges = 1;
lxc_fill_elevated_privileges(NULL, &elevated_privileges);
break;
case 500: /* clear-env */
env_policy = LXC_ATTACH_CLEAR_ENV;
Expand Down Expand Up @@ -138,19 +142,23 @@ Execute the specified COMMAND - enter the container NAME\n\
\n\
Options :\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\
-e, --elevated-privileges=PRIVILEGES\n\
Use elevated privileges instead of those of the\n\
container. If you don't specify privileges to be\n\
elevated as OR'd list: CAP, CGROUP and LSM (capabilities,\n\
cgroup and restrictions, respectively) then all of them\n\
will be elevated.\n\
WARNING: This may leak privileges into the container.\n\
Use with care.\n\
-a, --arch=ARCH Use ARCH for program instead of container's own\n\
architecture.\n\
-s, --namespaces=FLAGS\n\
Don't attach to all the namespaces of the container\n\
but just to the following OR'd list of flags:\n\
MOUNT, PID, UTSNAME, IPC, USER or NETWORK\n\
WARNING: Using -s implies -e, it may therefore\n\
leak privileges into the container. Use with care.\n\
MOUNT, PID, UTSNAME, IPC, USER or NETWORK.\n\
WARNING: Using -s implies -e with all privileges\n\
elevated, it may therefore leak privileges into the\n\
container. Use with care.\n\
-R, --remount-sys-proc\n\
Remount /sys and /proc if not attaching to the\n\
mount namespace when using -s in order to properly\n\
Expand Down Expand Up @@ -199,7 +207,7 @@ int main(int argc, char *argv[])
if (remount_sys_proc)
attach_options.attach_flags |= LXC_ATTACH_REMOUNT_PROC_SYS;
if (elevated_privileges)
attach_options.attach_flags &= ~(LXC_ATTACH_MOVE_TO_CGROUP | LXC_ATTACH_DROP_CAPABILITIES | LXC_ATTACH_LSM_EXEC);
attach_options.attach_flags &= ~(elevated_privileges);
attach_options.namespaces = namespace_flags;
attach_options.personality = new_personality;
attach_options.env_policy = env_policy;
Expand Down

0 comments on commit 4d69b29

Please sign in to comment.