]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: mount custom paths before writing to /etc
authorMotiejus Jakštys <desired.mta@gmail.com>
Mon, 4 May 2020 16:57:40 +0000 (19:57 +0300)
committerLennart Poettering <lennart@poettering.net>
Tue, 5 May 2020 07:02:57 +0000 (09:02 +0200)
Consider such configuration:

    $ systemd-nspawn --read-only --timezone=copy --resolv-conf=copy-host \
        --overlay="+/etc::/etc" <...>

Assuming one wants `/` to be read-only, DNS and `/etc/localtime` to
work. One way to do it is to create an overlay filesystem in `/etc/`.
However, systemd-nspawn tries to create `/etc/resolv.conf` and
`/etc/localtime` before mounting the custom paths, while `/` (and, by
extension, `/etc`) is read-only. Thus it fails to create those files.

Mounting custom paths before modifying anything in `/etc/` makes this
possible.

Full example:

```
$ debootstrap buster /var/lib/machines/t1 http://deb.debian.org/debian
$ systemd-nspawn --private-users=false --timezone=copy --resolv-conf=copy-host --read-only --tmpfs=/var --tmpfs=/run --overlay="+/etc::/etc" -D /var/lib/machines/t1 ping -c 1 example.com
Spawning container t1 on /var/lib/machines/t1.
Press ^] three times within 1s to kill container.
ping: example.com: Temporary failure in name resolution
Container t1 failed with error code 130.
```

With the patch:

```
$ sudo ./build/systemd-nspawn --private-users=false --timezone=copy --resolv-conf=copy-host --read-only --tmpfs=/var --tmpfs=/run --overlay="+/etc::/etc" -D /var/lib/machines/t1 ping -qc 1 example.com
Spawning container t1 on /var/lib/machines/t1.
Press ^] three times within 1s to kill container.
PING example.com (93.184.216.34) 56(84) bytes of data.

--- example.org ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 110.912/110.912/110.912/0.000 ms
Container t1 exited successfully.
```

src/nspawn/nspawn.c

index c2148596b79ef903437f85cf8cf32a119097b1ad..43c6b6845ed1960bef344941780866edf8ad8b37 100644 (file)
@@ -3486,6 +3486,16 @@ static int outer_child(
         if (r < 0)
                 return r;
 
+        r = mount_custom(
+                        directory,
+                        arg_custom_mounts,
+                        arg_n_custom_mounts,
+                        arg_uid_shift,
+                        arg_selinux_apifs_context,
+                        MOUNT_NON_ROOT_ONLY);
+        if (r < 0)
+                return r;
+
         r = setup_timezone(directory);
         if (r < 0)
                 return r;
@@ -3502,16 +3512,6 @@ static int outer_child(
         if (r < 0)
                 return r;
 
-        r = mount_custom(
-                        directory,
-                        arg_custom_mounts,
-                        arg_n_custom_mounts,
-                        arg_uid_shift,
-                        arg_selinux_apifs_context,
-                        MOUNT_NON_ROOT_ONLY);
-        if (r < 0)
-                return r;
-
         if (!arg_use_cgns) {
                 r = mount_cgroups(
                                 directory,