chiark / gitweb /
nspawn: add new --personality= switch to make it easier to run 32bit containers on...
[elogind.git] / src / nspawn / nspawn.c
index 34e72db063faf4c65916167df36017070295cfba..98e90fe3c9207ab51dde3c3ece05bea4aca7a24e 100644 (file)
@@ -43,6 +43,7 @@
 #include <sys/eventfd.h>
 #include <net/if.h>
 #include <linux/veth.h>
+#include <sys/personality.h>
 
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #include "rtnl-util.h"
 #include "udev-util.h"
 
+#ifdef HAVE_SECCOMP
+#include "seccomp-util.h"
+#endif
+
 typedef enum LinkJournal {
         LINK_NO,
         LINK_AUTO,
@@ -134,6 +139,7 @@ static bool arg_keep_unit = false;
 static char **arg_network_interfaces = NULL;
 static bool arg_network_veth = false;
 static char *arg_network_bridge = NULL;
+static unsigned long arg_personality = 0xffffffffLU;
 
 static int help(void) {
 
@@ -152,10 +158,10 @@ static int help(void) {
                "     --network-interface=INTERFACE\n"
                "                            Assign an existing network interface to the\n"
                "                            container\n"
-               "     --network-veth         Add a virtual ethernet connection between host\n"
+               "     --network-veth         Add a virtual ethernet connection between host\n"
                "                            and container\n"
                "     --network-bridge=INTERFACE\n"
-               "                            Add a virtual ethernet connection between host\n"
+               "                            Add a virtual ethernet connection between host\n"
                "                            and container and add it to an existing bridge on\n"
                "                            the host\n"
                "  -Z --selinux-context=SECLABEL\n"
@@ -202,6 +208,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NETWORK_INTERFACE,
                 ARG_NETWORK_VETH,
                 ARG_NETWORK_BRIDGE,
+                ARG_PERSONALITY,
         };
 
         static const struct option options[] = {
@@ -230,6 +237,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "network-interface",     required_argument, NULL, ARG_NETWORK_INTERFACE },
                 { "network-veth",          no_argument,       NULL, ARG_NETWORK_VETH      },
                 { "network-bridge",        required_argument, NULL, ARG_NETWORK_BRIDGE    },
+                { "personality",           required_argument, NULL, ARG_PERSONALITY       },
                 {}
         };
 
@@ -470,6 +478,16 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_keep_unit = true;
                         break;
 
+                case ARG_PERSONALITY:
+
+                        arg_personality = parse_personality(optarg);
+                        if (arg_personality == 0xffffffffLU) {
+                                log_error("Unknown or unsupported personality '%s'.", optarg);
+                                return -EINVAL;
+                        }
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -1303,7 +1321,7 @@ static int setup_veth(pid_t pid, char iface_name[]) {
                 return r;
         }
 
-        r = sd_rtnl_message_new_link(RTM_NEWLINK, 0, &m);
+        r = sd_rtnl_message_new_link(rtnl, RTM_NEWLINK, 0, &m);
         if (r < 0) {
                 log_error("Failed to allocate netlink message: %s", strerror(-r));
                 return r;
@@ -1404,7 +1422,7 @@ static int setup_bridge(const char veth_name[]) {
                 return r;
         }
 
-        r = sd_rtnl_message_new_link(RTM_SETLINK, 0, &m);
+        r = sd_rtnl_message_new_link(rtnl, RTM_SETLINK, 0, &m);
         if (r < 0) {
                 log_error("Failed to allocate netlink message: %s", strerror(-r));
                 return r;
@@ -1479,7 +1497,7 @@ static int move_network_interfaces(pid_t pid) {
                         return -EBUSY;
                 }
 
-                r = sd_rtnl_message_new_link(RTM_NEWLINK, ifi, &m);
+                r = sd_rtnl_message_new_link(rtnl, RTM_NEWLINK, ifi, &m);
                 if (r < 0) {
                         log_error("Failed to allocate netlink message: %s", strerror(-r));
                         return r;
@@ -1521,7 +1539,13 @@ static int audit_still_doesnt_work_in_containers(void) {
         if (!seccomp)
                 return log_oom();
 
-        r = seccomp_rule_add_exact(
+        r = seccomp_add_secondary_archs(seccomp);
+        if (r < 0 && r != -EEXIST) {
+                log_error("Failed to add secondary archs to seccomp filter: %s", strerror(-r));
+                goto finish;
+        }
+
+        r = seccomp_rule_add(
                         seccomp,
                         SCMP_ACT_ERRNO(EAFNOSUPPORT),
                         SCMP_SYS(socket),
@@ -1554,7 +1578,7 @@ finish:
 
 int main(int argc, char *argv[]) {
 
-        _cleanup_close_ int master = -1, kdbus_fd = -1, sync_fd = -1, netns_fd = -1;
+        _cleanup_close_ int master = -1, kdbus_fd = -1, sync_fd = -1;
         _cleanup_close_pipe_ int kmsg_socket_pair[2] = { -1, -1 };
         _cleanup_free_ char *kdbus_domain = NULL;
         _cleanup_fdset_free_ FDSet *fds = NULL;
@@ -1973,6 +1997,13 @@ int main(int argc, char *argv[]) {
 
                         setup_hostname();
 
+                        if (arg_personality != 0xffffffffLU) {
+                                if (personality(arg_personality) < 0) {
+                                        log_error("personality() failed: %m");
+                                        goto child_fail;
+                                }
+                        }
+
                         eventfd_read(sync_fd, &x);
                         close_nointr_nofail(sync_fd);
                         sync_fd = -1;