chiark / gitweb /
everywhere: remove configurability of sysv runlevel to target mapping
[elogind.git] / src / nspawn / nspawn.c
index 226c4415bb63c694d9679fd1a0d4de46263fcfa3..232629d20ad80c9e4b95f894edf730bf5017ebff 100644 (file)
@@ -187,6 +187,7 @@ static unsigned long arg_personality = 0xffffffffLU;
 static char *arg_image = NULL;
 static Volatile arg_volatile = VOLATILE_NO;
 static ExposePort *arg_expose_ports = NULL;
+static char **arg_property = NULL;
 
 static void help(void) {
         printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
@@ -205,6 +206,7 @@ static void help(void) {
                "  -M --machine=NAME         Set the machine name for the container\n"
                "     --uuid=UUID            Set a specific machine UUID for the container\n"
                "  -S --slice=SLICE          Place the container in the specified slice\n"
+               "     --property=NAME=VALUE  Set scope unit property\n"
                "     --private-network      Disable network in container\n"
                "     --network-interface=INTERFACE\n"
                "                            Assign an existing network interface to the\n"
@@ -294,6 +296,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_PERSONALITY,
                 ARG_VOLATILE,
                 ARG_TEMPLATE,
+                ARG_PROPERTY,
         };
 
         static const struct option options[] = {
@@ -331,6 +334,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "image",                 required_argument, NULL, 'i'                   },
                 { "volatile",              optional_argument, NULL, ARG_VOLATILE          },
                 { "port",                  required_argument, NULL, 'p'                   },
+                { "property",              required_argument, NULL, ARG_PROPERTY          },
                 {}
         };
 
@@ -731,6 +735,12 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_PROPERTY:
+                        if (strv_extend(&arg_property, optarg) < 0)
+                                return log_oom();
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -962,7 +972,7 @@ static int mount_cgroup_hierarchy(const char *dest, const char *controller, cons
         char *to;
         int r;
 
-        to = strappenda(dest, "/sys/fs/cgroup/", hierarchy);
+        to = strjoina(dest, "/sys/fs/cgroup/", hierarchy);
 
         r = path_is_mount_point(to, false);
         if (r < 0)
@@ -1004,7 +1014,7 @@ static int mount_cgroup(const char *dest) {
         if (r < 0)
                 return log_error_errno(r, "Failed to determine our own cgroup path: %m");
 
-        cgroup_root = strappenda(dest, "/sys/fs/cgroup");
+        cgroup_root = strjoina(dest, "/sys/fs/cgroup");
         if (mount("tmpfs", cgroup_root, "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, "mode=755") < 0)
                 return log_error_errno(errno, "Failed to mount tmpfs to /sys/fs/cgroup: %m");
 
@@ -1057,12 +1067,12 @@ static int mount_cgroup(const char *dest) {
                 return r;
 
         /* Make our own cgroup a (writable) bind mount */
-        systemd_own = strappenda(dest, "/sys/fs/cgroup/systemd", own_cgroup_path);
+        systemd_own = strjoina(dest, "/sys/fs/cgroup/systemd", own_cgroup_path);
         if (mount(systemd_own, systemd_own,  NULL, MS_BIND, NULL) < 0)
                 return log_error_errno(errno, "Failed to turn %s into a bind mount: %m", own_cgroup_path);
 
         /* And then remount the systemd cgroup root read-only */
-        systemd_root = strappenda(dest, "/sys/fs/cgroup/systemd");
+        systemd_root = strjoina(dest, "/sys/fs/cgroup/systemd");
         if (mount(NULL, systemd_root, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL) < 0)
                 return log_error_errno(errno, "Failed to mount cgroup root read-only: %m");
 
@@ -1215,7 +1225,7 @@ static int setup_volatile_state(const char *directory) {
         if (r < 0)
                 return log_error_errno(r, "Failed to remount %s read-only: %m", directory);
 
-        p = strappenda(directory, "/var");
+        p = strjoina(directory, "/var");
         r = mkdir(p, 0755);
         if (r < 0 && errno != EEXIST)
                 return log_error_errno(errno, "Failed to create %s: %m", directory);
@@ -1251,8 +1261,8 @@ static int setup_volatile(const char *directory) {
 
         tmpfs_mounted = true;
 
-        f = strappenda(directory, "/usr");
-        t = strappenda(template, "/usr");
+        f = strjoina(directory, "/usr");
+        t = strjoina(template, "/usr");
 
         r = mkdir(t, 0755);
         if (r < 0 && errno != EEXIST) {
@@ -1434,7 +1444,7 @@ static int setup_dev_console(const char *dest, const char *console) {
          * /dev/console. (Note that the major minor doesn't actually
          * matter here, since we mount it over anyway). */
 
-        to = strappenda(dest, "/dev/console");
+        to = strjoina(dest, "/dev/console");
         if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0)
                 return log_error_errno(errno, "mknod() for /dev/console failed: %m");
 
@@ -1897,6 +1907,7 @@ static int register_machine(pid_t pid, int local_ifindex) {
                                 local_ifindex > 0 ? 1 : 0, local_ifindex);
         } else {
                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+                char **i;
 
                 r = sd_bus_message_new_method_call(
                                 bus,
@@ -1906,7 +1917,7 @@ static int register_machine(pid_t pid, int local_ifindex) {
                                 "org.freedesktop.machine1.Manager",
                                 "CreateMachineWithNetwork");
                 if (r < 0)
-                        return log_error_errno(r, "Failed to create message: %m");
+                        return bus_log_create_error(r);
 
                 r = sd_bus_message_append(
                                 m,
@@ -1919,21 +1930,21 @@ static int register_machine(pid_t pid, int local_ifindex) {
                                 strempty(arg_directory),
                                 local_ifindex > 0 ? 1 : 0, local_ifindex);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to append message arguments: %m");
+                        return bus_log_create_error(r);
 
                 r = sd_bus_message_open_container(m, 'a', "(sv)");
                 if (r < 0)
-                        return log_error_errno(r, "Failed to open container: %m");
+                        return bus_log_create_error(r);
 
                 if (!isempty(arg_slice)) {
                         r = sd_bus_message_append(m, "(sv)", "Slice", "s", arg_slice);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to append slice: %m");
+                                return bus_log_create_error(r);
                 }
 
                 r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
                 if (r < 0)
-                        return log_error_errno(r, "Failed to add device policy: %m");
+                        return bus_log_create_error(r);
 
                 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9,
                                           /* Allow the container to
@@ -1959,9 +1970,23 @@ static int register_machine(pid_t pid, int local_ifindex) {
                 if (r < 0)
                         return log_error_errno(r, "Failed to add device whitelist: %m");
 
+                STRV_FOREACH(i, arg_property) {
+                        r = sd_bus_message_open_container(m, 'r', "sv");
+                        if (r < 0)
+                                return bus_log_create_error(r);
+
+                        r = bus_append_unit_property_assignment(m, *i);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_close_container(m);
+                        if (r < 0)
+                                return bus_log_create_error(r);
+                }
+
                 r = sd_bus_message_close_container(m);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to close container: %m");
+                        return bus_log_create_error(r);
 
                 r = sd_bus_call(bus, m, 0, &error, NULL);
         }
@@ -2485,15 +2510,18 @@ static int setup_seccomp(void) {
         static const int blacklist[] = {
                 SCMP_SYS(kexec_load),
                 SCMP_SYS(open_by_handle_at),
-                SCMP_SYS(init_module),
-                SCMP_SYS(finit_module),
-                SCMP_SYS(delete_module),
                 SCMP_SYS(iopl),
                 SCMP_SYS(ioperm),
                 SCMP_SYS(swapon),
                 SCMP_SYS(swapoff),
         };
 
+        static const int kmod_blacklist[] = {
+                SCMP_SYS(init_module),
+                SCMP_SYS(finit_module),
+                SCMP_SYS(delete_module),
+        };
+
         scmp_filter_ctx seccomp;
         unsigned i;
         int r;
@@ -2518,6 +2546,20 @@ static int setup_seccomp(void) {
                 }
         }
 
+        /* If the CAP_SYS_MODULE capability is not requested then
+         * we'll block the kmod syscalls too */
+        if (!(arg_retain & (1ULL << CAP_SYS_MODULE))) {
+                for (i = 0; i < ELEMENTSOF(kmod_blacklist); i++) {
+                        r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), kmod_blacklist[i], 0);
+                        if (r == -EFAULT)
+                                continue; /* unknown syscall */
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to block syscall: %m");
+                                goto finish;
+                        }
+                }
+        }
+
         /*
            Audit is broken in containers, much of the userspace audit
            hookup will fail if running inside a container. We don't
@@ -2564,10 +2606,10 @@ static int setup_propagate(const char *root) {
 
         (void) mkdir_p("/run/systemd/nspawn/", 0755);
         (void) mkdir_p("/run/systemd/nspawn/propagate", 0600);
-        p = strappenda("/run/systemd/nspawn/propagate/", arg_machine);
+        p = strjoina("/run/systemd/nspawn/propagate/", arg_machine);
         (void) mkdir_p(p, 0600);
 
-        q = strappenda(root, "/run/systemd/nspawn/incoming");
+        q = strjoina(root, "/run/systemd/nspawn/incoming");
         mkdir_parents(q, 0755);
         mkdir_p(q, 0600);
 
@@ -3050,7 +3092,7 @@ static int mount_device(const char *what, const char *where, const char *directo
                 rw = false;
 
         if (directory)
-                p = strappenda(where, directory);
+                p = strjoina(where, directory);
         else
                 p = where;
 
@@ -3685,7 +3727,7 @@ int main(int argc, char *argv[]) {
                 } else {
                         const char *p;
 
-                        p = strappenda(arg_directory,
+                        p = strjoina(arg_directory,
                                        argc > optind && path_is_absolute(argv[optind]) ? argv[optind] : "/usr/bin/");
                         if (access(p, F_OK) < 0) {
                                 log_error("Directory %s lacks the binary to execute or doesn't look like a binary tree. Refusing.", arg_directory);
@@ -4294,7 +4336,7 @@ finish:
         if (arg_machine) {
                 const char *p;
 
-                p = strappenda("/run/systemd/nspawn/propagate/", arg_machine);
+                p = strjoina("/run/systemd/nspawn/propagate/", arg_machine);
                 (void) rm_rf(p, false, true, false);
         }