+
+ /* Already reset? */
+ if (streq(p, "4294967295"))
+ return 0;
+
+ r = write_string_file("/proc/self/loginuid", "4294967295");
+ if (r < 0) {
+ log_error("Failed to reset audit login UID. This probably means that your kernel is too\n"
+ "old and you have audit enabled. Note that the auditing subsystem is known to\n"
+ "be incompatible with containers on old kernels. Please make sure to upgrade\n"
+ "your kernel or to off auditing with 'audit=0' on the kernel command line before\n"
+ "using systemd-nspawn. Sleeping for 5s... (%s)\n", strerror(-r));
+
+ sleep(5);
+ }
+
+ return 0;
+}
+
+static int setup_veth(pid_t pid, char iface_name[IFNAMSIZ]) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ int r;
+
+ if (!arg_private_network)
+ return 0;
+
+ if (!arg_network_veth)
+ return 0;
+
+ /* Use two different interface name prefixes depending whether
+ * we are in bridge mode or not. */
+ if (arg_network_bridge)
+ memcpy(iface_name, "vb-", 3);
+ else
+ memcpy(iface_name, "ve-", 3);
+
+ strncpy(iface_name+3, arg_machine, IFNAMSIZ - 3);
+
+ r = sd_rtnl_open(&rtnl, 0);
+ if (r < 0) {
+ log_error("Failed to connect to netlink: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0);
+ if (r < 0) {
+ log_error("Failed to allocate netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_IFNAME, iface_name);
+ if (r < 0) {
+ log_error("Failed to add netlink interface name: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+ if (r < 0) {
+ log_error("Failed to open netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "veth");
+ if (r < 0) {
+ log_error("Failed to append netlink kind: %s", strerror(-r));
+ return r;
+ }
+
+ 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);
+ if (r < 0) {
+ log_error("Failed to open netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_IFNAME, "host0");
+ if (r < 0) {
+ log_error("Failed to add netlink interface name: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_PID, pid);
+ if (r < 0) {
+ log_error("Failed to add netlink namespace field: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_call(rtnl, m, 0, NULL);
+ if (r < 0) {
+ log_error("Failed to add new veth interfaces: %s", strerror(-r));
+ return r;
+ }
+
+ return 0;
+}
+
+static int setup_bridge(const char veth_name[]) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ int r, bridge;
+
+ if (!arg_private_network)
+ return 0;
+
+ if (!arg_network_veth)
+ return 0;
+
+ if (!arg_network_bridge)
+ return 0;
+
+ bridge = (int) if_nametoindex(arg_network_bridge);
+ if (bridge <= 0) {
+ log_error("Failed to resolve interface %s: %m", arg_network_bridge);
+ return -errno;
+ }
+
+ r = sd_rtnl_open(&rtnl, 0);
+ if (r < 0) {
+ log_error("Failed to connect to netlink: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, 0);
+ if (r < 0) {
+ log_error("Failed to allocate netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_IFNAME, veth_name);
+ if (r < 0) {
+ log_error("Failed to add netlink interface name field: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_u32(m, IFLA_MASTER, bridge);
+ if (r < 0) {
+ log_error("Failed to add netlink master field: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_call(rtnl, m, 0, NULL);
+ if (r < 0) {
+ log_error("Failed to add veth interface to bridge: %s", strerror(-r));
+ return r;
+ }
+
+ return 0;
+}
+
+static int parse_interface(struct udev *udev, const char *name) {
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ char ifi_str[2 + DECIMAL_STR_MAX(int)];
+ int ifi;
+
+ ifi = (int) if_nametoindex(name);
+ if (ifi <= 0) {
+ log_error("Failed to resolve interface %s: %m", name);
+ return -errno;
+ }
+
+ sprintf(ifi_str, "n%i", ifi);
+ d = udev_device_new_from_device_id(udev, ifi_str);
+ if (!d) {
+ log_error("Failed to get udev device for interface %s: %m", name);
+ return -errno;
+ }
+
+ if (udev_device_get_is_initialized(d) <= 0) {
+ log_error("Network interface %s is not initialized yet.", name);
+ return -EBUSY;
+ }
+
+ return ifi;
+}
+
+static int move_network_interfaces(pid_t pid) {
+ _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ char **i;
+ int r;
+
+ if (!arg_private_network)
+ return 0;
+
+ if (strv_isempty(arg_network_interfaces))
+ return 0;
+
+ r = sd_rtnl_open(&rtnl, 0);
+ if (r < 0) {
+ log_error("Failed to connect to netlink: %s", strerror(-r));
+ return r;
+ }
+
+ udev = udev_new();
+ if (!udev) {
+ log_error("Failed to connect to udev.");
+ return -ENOMEM;
+ }
+
+ STRV_FOREACH(i, arg_network_interfaces) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ int ifi;
+
+ ifi = parse_interface(udev, *i);
+ if (ifi < 0)
+ return ifi;
+
+ r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, ifi);
+ if (r < 0) {
+ log_error("Failed to allocate netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_PID, pid);
+ if (r < 0) {
+ log_error("Failed to append namespace PID to netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_call(rtnl, m, 0, NULL);
+ if (r < 0) {
+ log_error("Failed to move interface %s to namespace: %s", *i, strerror(-r));
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+static int setup_macvlan(pid_t pid) {
+ _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ char **i;
+ int r;
+
+ if (!arg_private_network)
+ return 0;
+
+ if (strv_isempty(arg_network_macvlan))
+ return 0;
+
+ r = sd_rtnl_open(&rtnl, 0);
+ if (r < 0) {
+ log_error("Failed to connect to netlink: %s", strerror(-r));
+ return r;
+ }
+
+ udev = udev_new();
+ if (!udev) {
+ log_error("Failed to connect to udev.");
+ return -ENOMEM;
+ }
+
+ STRV_FOREACH(i, arg_network_macvlan) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+ _cleanup_free_ char *n = NULL;
+ int ifi;
+
+ ifi = parse_interface(udev, *i);
+ if (ifi < 0)
+ return ifi;
+
+ r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0);
+ if (r < 0) {
+ log_error("Failed to allocate netlink message: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_u32(m, IFLA_LINK, ifi);
+ if (r < 0) {
+ log_error("Failed to add netlink interface index: %s", strerror(-r));
+ return r;
+ }
+
+ n = strappend("mv-", *i);
+ if (!n)
+ return log_oom();
+
+ strshorten(n, IFNAMSIZ-1);
+
+ r = sd_rtnl_message_append_string(m, IFLA_IFNAME, n);
+ if (r < 0) {
+ log_error("Failed to add netlink interface name: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_PID, pid);
+ if (r < 0) {
+ log_error("Failed to add netlink namespace field: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+ if (r < 0) {
+ log_error("Failed to open netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "macvlan");
+ if (r < 0) {
+ log_error("Failed to append netlink kind: %s", strerror(-r));
+ return r;
+ }
+
+ 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_append_u32(m, IFLA_MACVLAN_MODE, MACVLAN_MODE_BRIDGE);
+ if (r < 0) {
+ log_error("Failed to append macvlan mode: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_message_close_container(m);
+ if (r < 0) {
+ log_error("Failed to close netlink container: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_rtnl_call(rtnl, m, 0, NULL);
+ if (r < 0) {
+ log_error("Failed to add new macvlan interfaces: %s", strerror(-r));
+ return r;
+ }
+ }
+
+ 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_add_secondary_archs(seccomp);
+ if (r < 0) {
+ 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),
+ 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
+