chiark / gitweb /
nspawn: add --read-only switch
authorLennart Poettering <lennart@poettering.net>
Wed, 25 Apr 2012 13:11:20 +0000 (15:11 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 25 Apr 2012 13:11:20 +0000 (15:11 +0200)
man/systemd-nspawn.xml
src/nspawn/nspawn.c

index cf6756952466bc561f22ed692652ab5f82002c9d..a926a7e5d3d18545890f68856b524c846c7b2639 100644 (file)
                                 loopback device.</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><option>--read-only</option></term>
+
+                                <listitem><para>Mount the root file
+                                system read only for the
+                                container.</para></listitem>
+                        </varlistentry>
+
                 </variablelist>
 
         </refsect1>
index 83bec96cc5cee11c0e732121342c4ef9c8b4583c..2a1f37bffcd50dca1a40bc3763e4f0827dc230e7 100644 (file)
@@ -57,6 +57,7 @@ static char *arg_user = NULL;
 static char **arg_controllers = NULL;
 static char *arg_uuid = NULL;
 static bool arg_private_network = false;
+static bool arg_read_only = false;
 static bool arg_boot = false;
 
 static int help(void) {
@@ -69,7 +70,8 @@ static int help(void) {
                "  -u --user=USER        Run the command under specified user or uid\n"
                "  -C --controllers=LIST Put the container in specified comma-separated cgroup hierarchies\n"
                "     --uuid=UUID        Set a specific machine UUID for the container\n"
-               "     --private-network  Disable network in container\n",
+               "     --private-network  Disable network in container\n"
+               "     --read-only        Mount the root directory read-only\n",
                program_invocation_short_name);
 
         return 0;
@@ -79,7 +81,8 @@ static int parse_argv(int argc, char *argv[]) {
 
         enum {
                 ARG_PRIVATE_NETWORK = 0x100,
-                ARG_UUID
+                ARG_UUID,
+                ARG_READ_ONLY
         };
 
         static const struct option options[] = {
@@ -90,6 +93,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "private-network", no_argument,       NULL, ARG_PRIVATE_NETWORK },
                 { "boot",            no_argument,       NULL, 'b'                 },
                 { "uuid",            required_argument, NULL, ARG_UUID            },
+                { "read-only",       no_argument,       NULL, ARG_READ_ONLY       },
                 { NULL,              0,                 NULL, 0                   }
         };
 
@@ -148,6 +152,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_uuid = optarg;
                         break;
 
+                case ARG_READ_ONLY:
+                        arg_read_only = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -971,6 +979,18 @@ int main(int argc, char *argv[]) {
                 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
                         goto child_fail;
 
+                /* Turn directory into bind mount */
+                if (mount(arg_directory, arg_directory, "bind", MS_BIND, NULL) < 0) {
+                        log_error("Failed to make bind mount.");
+                        goto child_fail;
+                }
+
+                if (arg_read_only)
+                        if (mount(arg_directory, arg_directory, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
+                                log_error("Failed to make read-only.");
+                                goto child_fail;
+                        }
+
                 if (mount_all(arg_directory) < 0)
                         goto child_fail;
 
@@ -1001,8 +1021,8 @@ int main(int argc, char *argv[]) {
                     dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
                         goto child_fail;
 
-                if (mount(arg_directory, "/", "bind", MS_BIND, NULL) < 0) {
-                        log_error("mount(MS_MOVE) failed: %m");
+                if (mount(arg_directory, "/", "bind", MS_MOVE, NULL) < 0) {
+                        log_error("mount(MS_BIND) failed: %m");
                         goto child_fail;
                 }