nspawn: add new --personality= switch to make it easier to run 32bit containers on a 64bit host

This commit is contained in:
Lennart Poettering 2014-02-18 23:35:19 +01:00
parent 0bc8e31b35
commit 6afc95b736
5 changed files with 75 additions and 0 deletions

4
NEWS
View File

@ -379,6 +379,10 @@ CHANGES WITH 209:
switch then allows assigning the host side of this virtual switch then allows assigning the host side of this virtual
Ethernet connection to a bridge device. 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 * logind will now also track a "Desktop" identifier for each
session which encodes the desktop environment of it. This is session which encodes the desktop environment of it. This is
useful for desktop environments that want to identify useful for desktop environments that want to identify

View File

@ -555,6 +555,24 @@
session.</para></listitem> session.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--personality=</option></term>
<listitem><para>Control the
architecture ("personality") reported
by
<citerefentry><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
in the container. Currently, only
<literal>x86</literal> and
<literal>x86-64</literal> 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.</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -43,6 +43,7 @@
#include <sys/eventfd.h> #include <sys/eventfd.h>
#include <net/if.h> #include <net/if.h>
#include <linux/veth.h> #include <linux/veth.h>
#include <sys/personality.h>
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
#include <selinux/selinux.h> #include <selinux/selinux.h>
@ -138,6 +139,7 @@ static bool arg_keep_unit = false;
static char **arg_network_interfaces = NULL; static char **arg_network_interfaces = NULL;
static bool arg_network_veth = false; static bool arg_network_veth = false;
static char *arg_network_bridge = NULL; static char *arg_network_bridge = NULL;
static unsigned long arg_personality = 0xffffffffLU;
static int help(void) { static int help(void) {
@ -206,6 +208,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NETWORK_INTERFACE, ARG_NETWORK_INTERFACE,
ARG_NETWORK_VETH, ARG_NETWORK_VETH,
ARG_NETWORK_BRIDGE, ARG_NETWORK_BRIDGE,
ARG_PERSONALITY,
}; };
static const struct option options[] = { 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-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
{ "network-veth", no_argument, NULL, ARG_NETWORK_VETH }, { "network-veth", no_argument, NULL, ARG_NETWORK_VETH },
{ "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE }, { "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; arg_keep_unit = true;
break; 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 '?': case '?':
return -EINVAL; return -EINVAL;
@ -1983,6 +1997,13 @@ int main(int argc, char *argv[]) {
setup_hostname(); setup_hostname();
if (arg_personality != 0xffffffffLU) {
if (personality(arg_personality) < 0) {
log_error("personality() failed: %m");
goto child_fail;
}
}
eventfd_read(sync_fd, &x); eventfd_read(sync_fd, &x);
close_nointr_nofail(sync_fd); close_nointr_nofail(sync_fd);
sync_fd = -1; sync_fd = -1;

View File

@ -58,6 +58,7 @@
#include <limits.h> #include <limits.h>
#include <langinfo.h> #include <langinfo.h>
#include <locale.h> #include <locale.h>
#include <sys/personality.h>
#include <libgen.h> #include <libgen.h>
#undef basename #undef basename
@ -6192,3 +6193,32 @@ int fd_warn_permissions(const char *path, int fd) {
return 0; 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;
}

View File

@ -870,3 +870,5 @@ int mkostemp_safe(char *pattern, int flags);
int open_tmpfile(const char *path, int flags); int open_tmpfile(const char *path, int flags);
int fd_warn_permissions(const char *path, int fd); int fd_warn_permissions(const char *path, int fd);
unsigned long parse_personality(const char *p);