chiark / gitweb /
sd-rtnl: message_open_container - don't take a 'size' argument
[elogind.git] / src / nspawn / nspawn.c
index b4c5a549443b2036335d12ebcf4be09a2e459c28..fcc0f17aee011a9542262bd0d18177d6dcdadf62 100644 (file)
 #include <selinux/selinux.h>
 #endif
 
+#ifdef HAVE_SECCOMP
+#include <seccomp.h>
+#endif
+
 #include "sd-daemon.h"
 #include "sd-bus.h"
 #include "sd-id128.h"
@@ -1299,7 +1303,7 @@ static int setup_veth(int netns_fd) {
                 return r;
         }
 
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO, 0);
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
         if (r < 0) {
                 log_error("Failed to open netlink container: %s", strerror(-r));
                 return r;
@@ -1311,13 +1315,13 @@ static int setup_veth(int netns_fd) {
                 return r;
         }
 
-        r = sd_rtnl_message_open_container(m, IFLA_INFO_DATA, 0);
+        r = sd_rtnl_message_open_container(m, IFLA_INFO_DATA);
         if (r < 0) {
                 log_error("Failed to open netlink container: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_rtnl_message_open_container(m, VETH_INFO_PEER, sizeof(struct ifinfomsg));
+        r = sd_rtnl_message_open_container(m, VETH_INFO_PEER);
         if (r < 0) {
                 log_error("z Failed to open netlink container: %s", strerror(-r));
                 return r;
@@ -1432,6 +1436,57 @@ static int move_network_interfaces(pid_t pid) {
         return 0;
 }
 
+static int audit_still_doesnt_work_in_containers(void) {
+
+#ifdef HAVE_SECCOMP
+        scmp_filter_ctx seccomp;
+        int r;
+
+        /*
+           Audit is broken in containers, much of the userspace audit
+           hookup will fail if running inside a container. We don't
+           care and just turn off creation of audit sockets.
+
+           This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail
+           with EAFNOSUPPORT which audit userspace uses as indication
+           that audit is disabled in the kernel.
+         */
+
+        seccomp = seccomp_init(SCMP_ACT_ALLOW);
+        if (!seccomp)
+                return log_oom();
+
+        r = seccomp_rule_add_exact(
+                        seccomp,
+                        SCMP_ACT_ERRNO(EAFNOSUPPORT),
+                        SCMP_SYS(socket),
+                        2,
+                        SCMP_A0(SCMP_CMP_EQ, AF_NETLINK),
+                        SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT));
+        if (r < 0) {
+                log_error("Failed to add audit seccomp rule: %s", strerror(-r));
+                goto finish;
+        }
+
+        r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
+        if (r < 0) {
+                log_error("Failed to unset NO_NEW_PRIVS: %s", strerror(-r));
+                goto finish;
+        }
+
+        r = seccomp_load(seccomp);
+        if (r < 0)
+                log_error("Failed to install seccomp audit filter: %s", strerror(-r));
+
+finish:
+        seccomp_release(seccomp);
+        return r;
+#else
+        return 0;
+#endif
+
+}
+
 int main(int argc, char *argv[]) {
 
         _cleanup_close_ int master = -1, kdbus_fd = -1, sync_fd = -1, netns_fd = -1;
@@ -1500,9 +1555,21 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        if (arg_boot && path_is_os_tree(arg_directory) <= 0) {
-                log_error("Directory %s doesn't look like an OS root directory (/etc/os-release is missing). Refusing.", arg_directory);
-                goto finish;
+        if (arg_boot) {
+                if (path_is_os_tree(arg_directory) <= 0) {
+                        log_error("Directory %s doesn't look like an OS root directory (/etc/os-release is missing). Refusing.", arg_directory);
+                        goto finish;
+                }
+        } else {
+                const char *p;
+
+                p = strappenda(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);
+                        goto finish;
+
+                }
         }
 
         log_close();
@@ -1707,6 +1774,9 @@ int main(int argc, char *argv[]) {
                                 netns_fd = -1;
                         }
 
+                        if (audit_still_doesnt_work_in_containers() < 0)
+                                goto child_fail;
+
                         if (setup_dev_console(arg_directory, console) < 0)
                                 goto child_fail;
 
@@ -1898,6 +1968,7 @@ int main(int argc, char *argv[]) {
                         else {
                                 chdir(home ? home : "/root");
                                 execle("/bin/bash", "-bash", NULL, env_use);
+                                execle("/bin/sh", "-sh", NULL, env_use);
                         }
 
                         log_error("execv() failed: %m");