diff options
author | Dan Walsh <dwalsh@redhat.com> | 2014-01-30 16:28:02 -0500 |
---|---|---|
committer | David Strauss <david@davidstrauss.net> | 2014-02-04 13:33:15 -0800 |
commit | a8828ed93878b4b4866d40ebfb660e54995ff72e (patch) | |
tree | 069b43684335a229432b2fa1f7666d8e62e3e715 | |
parent | 483798e0770c65968bbe2b668ece293b2419f2ec (diff) |
Add SELinux support to systemd-nspawn
This patch adds to new options:
-Z PROCESS_LABEL
This specifies the process label to run on processes run within the container.
-L FILE_LABEL
The file label to assign to memory file systems created within the container.
For example if you wanted to wrap an container with SELinux sandbox labels, you could execute a command line the following
chcon system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 -R /srv/container
systemd-nspawn -L system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 -Z system_u:system_r:svirt_lxc_net_t:s0:c0,c1 -D /srv/container /bin/sh
-rw-r--r-- | man/systemd-nspawn.xml | 29 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 82 |
2 files changed, 90 insertions, 21 deletions
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index bec233c1ca..08b0457d16 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -249,6 +249,27 @@ </varlistentry> <varlistentry> + <term><option>-L</option></term> + <term><option>--file-label=</option></term> + + <listitem><para>Sets the mandatory + access control (MAC) file label to be + used by tmpfs file systems in the + container.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-Z</option></term> + <term><option>--process-label=</option></term> + + <listitem><para>Sets the mandatory + access control (MAC) label to be used by + processes in the container.</para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>--uuid=</option></term> <listitem><para>Set the specified UUID @@ -456,6 +477,14 @@ btrfs snapshot.</para> </refsect1> + <refsect1> + <title>Example 6</title> + + <programlisting># chcon system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 -R /srv/container +# systemd-nspawn -L system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 -Z system_u:system_r:svirt_lxc_net_t:s0:c0,c1 -D /srv/container /bin/sh</programlisting> + + <para>This runs a container with SELinux sandbox labels.</para> + </refsect1> <refsect1> <title>Exit status</title> diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index f0e7b0619f..c91f6cce21 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -41,6 +41,9 @@ #include <sys/socket.h> #include <linux/netlink.h> #include <sys/eventfd.h> +#if HAVE_SELINUX +#include <selinux/selinux.h> +#endif #include "sd-daemon.h" #include "sd-bus.h" @@ -77,6 +80,8 @@ static char *arg_directory = NULL; static char *arg_user = NULL; static sd_id128_t arg_uuid = {}; static char *arg_machine = NULL; +static char *process_label = NULL; +static char *file_label = NULL; static const char *arg_slice = NULL; static bool arg_private_network = false; static bool arg_read_only = false; @@ -117,25 +122,27 @@ static int help(void) { printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" "Spawn a minimal namespace container for debugging, testing and building.\n\n" - " -h --help Show this help\n" - " --version Print version string\n" - " -D --directory=NAME Root directory for the container\n" - " -b --boot Boot up full system (i.e. invoke init)\n" - " -u --user=USER Run the command under specified user or uid\n" - " --uuid=UUID Set a specific machine UUID for the container\n" - " -M --machine=NAME Set the machine name for the container\n" - " -S --slice=SLICE Place the container in the specified slice\n" - " --private-network Disable network in container\n" - " --read-only Mount the root directory read-only\n" - " --capability=CAP In addition to the default, retain specified\n" - " capability\n" - " --drop-capability=CAP Drop the specified capability from the default set\n" - " --link-journal=MODE Link up guest journal, one of no, auto, guest, host\n" - " -j Equivalent to --link-journal=host\n" - " --bind=PATH[:PATH] Bind mount a file or directory from the host into\n" - " the container\n" - " --bind-ro=PATH[:PATH] Similar, but creates a read-only bind mount\n" - " --setenv=NAME=VALUE Pass an environment variable to PID 1\n", + " -h --help Show this help\n" + " --version Print version string\n" + " -D --directory=NAME Root directory for the container\n" + " -b --boot Boot up full system (i.e. invoke init)\n" + " -u --user=USER Run the command under specified user or uid\n" + " --uuid=UUID Set a specific machine UUID for the container\n" + " -M --machine=NAME Set the machine name for the container\n" + " -S --slice=SLICE Place the container in the specified slice\n" + " -L --file-label=LABEL Set the MAC file label to be used by tmpfs file systems in container\n" + " -Z --process-label=LABEL Set the MAC label to be used by processes in container\n" + " --private-network Disable network in container\n" + " --read-only Mount the root directory read-only\n" + " --capability=CAP In addition to the default, retain specified\n" + " capability\n" + " --drop-capability=CAP Drop the specified capability from the default set\n" + " --link-journal=MODE Link up guest journal, one of no, auto, guest, host\n" + " -j Equivalent to --link-journal=host\n" + " --bind=PATH[:PATH] Bind mount a file or directory from the host into\n" + " the container\n" + " --bind-ro=PATH[:PATH] Similar, but creates a read-only bind mount\n" + " --setenv=NAME=VALUE Pass an environment variable to PID 1\n", program_invocation_short_name); return 0; @@ -173,6 +180,8 @@ static int parse_argv(int argc, char *argv[]) { { "machine", required_argument, NULL, 'M' }, { "slice", required_argument, NULL, 'S' }, { "setenv", required_argument, NULL, ARG_SETENV }, + { "process-label", required_argument, NULL, 'Z' }, + { "file-label", required_argument, NULL, 'L' }, {} }; @@ -181,7 +190,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "+hD:u:bM:jS:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "+hD:u:bL:M:jS:Z:", options, NULL)) >= 0) { switch (c) { @@ -247,6 +256,20 @@ static int parse_argv(int argc, char *argv[]) { break; + case 'L': + file_label = strdup(optarg); + if (!file_label) + return log_oom(); + + break; + + case 'Z': + process_label = strdup(optarg); + if (!process_label) + return log_oom(); + + break; + case ARG_READ_ONLY: arg_read_only = true; break; @@ -396,6 +419,7 @@ static int mount_all(const char *dest) { for (k = 0; k < ELEMENTSOF(mount_table); k++) { _cleanup_free_ char *where = NULL; + _cleanup_free_ char *options = NULL; int t; where = strjoin(dest, "/", mount_table[k].where, NULL); @@ -418,11 +442,22 @@ static int mount_all(const char *dest) { mkdir_p(where, 0755); +#ifdef HAVE_SELINUX + if (file_label && (streq_ptr(mount_table[k].what, "tmpfs") || + streq_ptr(mount_table[k].what, "devpts"))) + options = strjoin(mount_table[k].options, ",context=\"", file_label, "\"", NULL); + else +#endif + options = strjoin(mount_table[k].options, NULL); + + if (!options) + return log_oom(); + if (mount(mount_table[k].what, where, mount_table[k].type, mount_table[k].flags, - mount_table[k].options) < 0 && + options) < 0 && mount_table[k].fatal) { log_error("mount(%s) failed: %m", where); @@ -1491,6 +1526,11 @@ int main(int argc, char *argv[]) { } else env_use = (char**) envp; +#if HAVE_SELINUX + if (process_label) + if (setexeccon(process_label) < 0) + log_error("setexeccon(\"%s\") failed: %m", process_label); +#endif if (arg_boot) { char **a; size_t l; |