Introduction

In a prior post, ARMing Yourself - Working with ARM on x86_64, I showed how to transparently run arm32v7 and arm64v8 on x86_64 enabling the configuration/creation of ARM images and debootstrap‘ped root file systems. We can do the same on ARM to allow the transparent execution of x86_64 containers/chroots.

TLDR - Assuming you have installed the packages in the Required Packages (Ubuntu 18.04) section, go to The How section below.

Required Packages (Ubuntu 18.04)

We need to install QEMU and binfmt support so that we can leverage the binfmt_misc support in the Linux kernel.

sudo apt-get update
sudo apt-get install -y --no-install-recommends \
                     qemu qemu-system-misc qemu-user-static qemu-user binfmt-support

The What

The details behind the next steps is explained in detail in the The What section of ARMing Yourself. We’re going to summarize here.

Getting the Magic and Mask

We’ll need to set up a string in the format :name:type:offset:magic:mask:interpreter:flags for x86_64. With QEMU and binfmt-support installed, getting the magic and header is straightforward:

$ cat /var/lib/binfmts/qemu-x86_64  
qemu-user-static
0
\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00
\xff\xff\xff\xff\xff\xfe\xfe\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
/usr/bin/qemu-x86_64-static

yes

Note that \x7f\x45\x4c\x46 is \\x7fELF, the ELF format magic number.

  • Our magic is:
    • \x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00
  • Our mask:
    • We can use the same masks discussed in The What. \xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff

The How

Write the Failing Test

If you try to run container with an unknown format, it should error with something close to

  • standard_init_linux.go:211: exec user process caused "exec format error"
  • standard_init_linux.go:211: exec user process caused "no such file or directory"

Go ahead and give it a try, we’ll come back to these after configuring the system to verify functionality.

$ docker run amd64/ubuntu uname -m

standard_init_linux.go:211: exec user process caused "exec format error"

Configuration

With the details hashed out, it is time to set up our systemd-binfmt.service configuration:

# Create the binfmt.d directory which is read at boot to configure
# additional binary executable formats which can be handled by the system.
sudo mkdir -p /lib/binfmt.d

sudo sh -c 'echo :qemu-x86_64:M::\\x7f\\x45\\x4c\\x46\\x02\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x3e\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfe\\xff\\xff\\xff:/usr/bin/qemu-x86_64-static:F > /lib/binfmt.d/qemu-x86_64-static.conf'

# Restart the service to force an evaluation of the /lib/binfmt.d directory
sudo systemctl restart systemd-binfmt.service

Run the Tests

We should now be able to transparently run x86_64 containers/chroots on arm32v7 and arm64v8 hosts transparently.

$ docker run amd64/ubuntu uname -m
x86_64