From 6afc95b73605833e6e966af1c466b5c08feb953f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Feb 2014 23:35:19 +0100 Subject: [PATCH] nspawn: add new --personality= switch to make it easier to run 32bit containers on a 64bit host --- NEWS | 4 ++++ man/systemd-nspawn.xml | 18 ++++++++++++++++++ src/nspawn/nspawn.c | 21 +++++++++++++++++++++ src/shared/util.c | 30 ++++++++++++++++++++++++++++++ src/shared/util.h | 2 ++ 5 files changed, 75 insertions(+) diff --git a/NEWS b/NEWS index b40d36974..c240d11dc 100644 --- a/NEWS +++ b/NEWS @@ -379,6 +379,10 @@ CHANGES WITH 209: switch then allows assigning the host side of this virtual Ethernet connection to a bridge device. + * systemd-nspawn gained a new --personality= switch for + setting the kernel personality for the container. This is + useful when running a 32bit container on a 64bit host. + * logind will now also track a "Desktop" identifier for each session which encodes the desktop environment of it. This is useful for desktop environments that want to identify diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index b34d38c9b..6518eb819 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -555,6 +555,24 @@ session. + + + + Control the + architecture ("personality") reported + by + uname2 + in the container. Currently, only + x86 and + x86-64 are + supported. This is useful when running + a 32bit container on a 64bit + host. If this setting is not used + the personality reported in the + container is the same as the one + reported on the + host. + diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 379ea9235..98e90fe3c 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef HAVE_SELINUX #include @@ -138,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) { @@ -206,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[] = { @@ -234,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 }, {} }; @@ -474,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; @@ -1983,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; diff --git a/src/shared/util.c b/src/shared/util.c index 72b1e2f3c..99658f097 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #undef basename @@ -6192,3 +6193,32 @@ int fd_warn_permissions(const char *path, int fd) { return 0; } + +unsigned long parse_personality(const char *p) { + + /* Parse a personality specifier. We introduce our own + * identifiers that indicate specific ABIs, rather than just + * hints regarding the register size, since we want to keep + * things open for multiple locally supported ABIs for the + * same register size. We try to reuse the ABI identifiers + * used by libseccomp. */ + +#if defined(__x86_64__) + + if (streq(p, "x86")) + return PER_LINUX32; + + if (streq(p, "x86-64")) + return PER_LINUX; + +#elif defined(__i386__) + + if (streq(p, "x86")) + return PER_LINUX; +#endif + + /* personality(7) documents that 0xffffffffUL is used for + * querying the current personality, hence let's use that here + * as error indicator. */ + return 0xffffffffUL; +} diff --git a/src/shared/util.h b/src/shared/util.h index a41348e32..e379c30e6 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -870,3 +870,5 @@ int mkostemp_safe(char *pattern, int flags); int open_tmpfile(const char *path, int flags); int fd_warn_permissions(const char *path, int fd); + +unsigned long parse_personality(const char *p); -- 2.30.2