Commit 160d4953 authored by Martin Pitt's avatar Martin Pitt
Browse files

Make systemd-nspawn@.service work out of the box

 - Pre-create /var/lib/container with a secure mode (0700) via tmpfiles.d.
 - Add new try-{guest,host} modes for --link-journal to silently skip
   setting up the guest journal if the host has no persistant journal.
 - Extend boot-and-services autopkgtest to cover systemd-nspawn@.service.

Patch cherry-picked from upstream git.

Closes: #770275
parent 75e8e1b2
......@@ -6,6 +6,11 @@ systemd (215-7) UNRELEASED; urgency=medium
that the most crucial services behave as expected.
* logind autopkgtest: Fix stderr output in waiting loop for scsi_debug.
* Add nspawn test to boot-and-services autopkgtest.
* Make systemd-nspawn@.service work out of the box: (Closes: #770275)
- Pre-create /var/lib/container with a secure mode (0700) via tmpfiles.d.
- Add new try-{guest,host} modes for --link-journal to silently skip
setting up the guest journal if the host has no persistant journal.
- Extend boot-and-services autopkgtest to cover systemd-nspawn@.service.
[ Jon Severinsson]
* Add /run/shm -> /dev/shm symlink in debian/tmpfiles.d/debian.conf. This
......
From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Thu, 20 Nov 2014 14:30:52 +0100
Subject: nspawn: Add try-{host,guest} journal link modes
--link-journal={host,guest} fail if the host does not have persistent
journalling enabled and /var/log/journal/ does not exist. Even worse, as there
is no stdout/err any more, there is no error message to point that out.
Introduce two new modes "try-host" and "try-guest" which don't fail in this
case, and instead just silently skip the guest journal setup.
Change -j to mean "try-guest" instead of "guest", and fix the wrong --help
output for it (it said "host" before).
Change systemd-nspawn@.service.in to use "try-guest" so that this unit works
with both persistent and non-persistent journals on the host without failing.
https://bugs.debian.org/770275
---
man/systemd-nspawn.xml | 11 ++++++++---
src/nspawn/nspawn.c | 37 +++++++++++++++++++++++++++++--------
units/systemd-nspawn@.service.in | 2 +-
3 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 950558f..4d43888 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -439,7 +439,9 @@
versa). Takes one of
<literal>no</literal>,
<literal>host</literal>,
+ <literal>try-host</literal>,
<literal>guest</literal>,
+ <literal>try-guest</literal>,
<literal>auto</literal>. If
<literal>no</literal>, the journal is
not linked. If <literal>host</literal>,
@@ -453,8 +455,11 @@
guest file system (beneath
<filename>/var/log/journal/<replaceable>machine-id</replaceable></filename>)
and the subdirectory is symlinked into the host
- at the same location. If
- <literal>auto</literal> (the default),
+ at the same location. <literal>try-host</literal>
+ and <literal>try-guest</literal> do the same
+ but do not fail if the host does not have
+ persistant journalling enabled.
+ If <literal>auto</literal> (the default),
and the right subdirectory of
<filename>/var/log/journal</filename>
exists, it will be bind mounted
@@ -473,7 +478,7 @@
<term><option>-j</option></term>
<listitem><para>Equivalent to
- <option>--link-journal=guest</option>.</para></listitem>
+ <option>--link-journal=try-guest</option>.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 0d538c2..c13e625 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -118,6 +118,7 @@ static bool arg_private_network = false;
static bool arg_read_only = false;
static bool arg_boot = false;
static LinkJournal arg_link_journal = LINK_AUTO;
+static bool arg_link_journal_try = false;
static uint64_t arg_retain =
(1ULL << CAP_CHOWN) |
(1ULL << CAP_DAC_OVERRIDE) |
@@ -196,8 +197,9 @@ static int help(void) {
" --capability=CAP In addition to the default, retain specified\n"
" capability\n"
" --drop-capability=CAP Drop the specified capability from the default set\n"
- " --link-journal=MODE Link up guest journal, one of no, auto, guest, host\n"
- " -j Equivalent to --link-journal=host\n"
+ " --link-journal=MODE Link up guest journal, one of no, auto, guest, host,\n"
+ " try-guest, try-host\n"
+ " -j Equivalent to --link-journal=try-guest\n"
" --read-only Mount the root directory read-only\n"
" --bind=PATH[:PATH] Bind mount a file or directory from the host into\n"
" the container\n"
@@ -420,6 +422,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'j':
arg_link_journal = LINK_GUEST;
+ arg_link_journal_try = true;
break;
case ARG_LINK_JOURNAL:
@@ -431,7 +434,13 @@ static int parse_argv(int argc, char *argv[]) {
arg_link_journal = LINK_GUEST;
else if (streq(optarg, "host"))
arg_link_journal = LINK_HOST;
- else {
+ else if (streq(optarg, "try-guest")) {
+ arg_link_journal = LINK_GUEST;
+ arg_link_journal_try = true;
+ } else if (streq(optarg, "try-host")) {
+ arg_link_journal = LINK_HOST;
+ arg_link_journal_try = true;
+ } else {
log_error("Failed to parse link journal mode %s", optarg);
return -EINVAL;
}
@@ -1198,8 +1207,13 @@ static int setup_journal(const char *directory) {
if (arg_link_journal == LINK_GUEST) {
if (symlink(q, p) < 0) {
- log_error("Failed to symlink %s to %s: %m", q, p);
- return -errno;
+ if (arg_link_journal_try) {
+ log_debug("Failed to symlink %s to %s, skipping journal setup: %m", q, p);
+ return 0;
+ } else {
+ log_error("Failed to symlink %s to %s: %m", q, p);
+ return -errno;
+ }
}
r = mkdir_p(q, 0755);
@@ -1209,10 +1223,17 @@ static int setup_journal(const char *directory) {
}
if (arg_link_journal == LINK_HOST) {
- r = mkdir_p(p, 0755);
+ /* don't create parents here -- if the host doesn't have
+ * permanent journal set up, don't force it here */
+ r = mkdir(p, 0755);
if (r < 0) {
- log_error("Failed to create %s: %m", p);
- return r;
+ if (arg_link_journal_try) {
+ log_debug("Failed to create %s, skipping journal setup: %m", p);
+ return 0;
+ } else {
+ log_error("Failed to create %s: %m", p);
+ return r;
+ }
}
} else if (access(p, F_OK) < 0)
diff --git a/units/systemd-nspawn@.service.in b/units/systemd-nspawn@.service.in
index 574d0de..05dd2b3 100644
--- a/units/systemd-nspawn@.service.in
+++ b/units/systemd-nspawn@.service.in
@@ -10,7 +10,7 @@ Description=Container %i
Documentation=man:systemd-nspawn(1)
[Service]
-ExecStart=@bindir@/systemd-nspawn --quiet --keep-unit --boot --link-journal=guest --directory=/var/lib/container/%i
+ExecStart=@bindir@/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --directory=/var/lib/container/%i
KillMode=mixed
Type=notify
RestartForceExitStatus=133
......@@ -109,6 +109,8 @@ udev-link-config-fix-crash-due-to-missing-hwaddr.patch
tests-fix-some-tests-to-pass-in-koji.patch
Make-emergency.service-conflict-with-rescue.service.patch
udev-hwdb-Support-shipping-pre-compiled-database-in-.patch
tmpfiles.d-Create-var-lib-containers.patch
nspawn-Add-try-host-guest-journal-link-modes.patch
## Debian specific patches:
Add-back-support-for-Debian-specific-config-files.patch
......
From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Thu, 20 Nov 2014 14:37:08 +0100
Subject: tmpfiles.d: Create /var/lib/container
Create /var/lib/container so that it exists with an appropriate mode. We want
0700 by default so that users on the host aren't able to call suid root
binaries in the container. This becomes a security issue if a user can enter a
container as root, create a suid root binary, and call that from the host.
(This assumes that containers are caged by mandatory access control or are
started as user).
---
tmpfiles.d/var.conf | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tmpfiles.d/var.conf b/tmpfiles.d/var.conf
index 4b63e41..b4bf3bc 100644
--- a/tmpfiles.d/var.conf
+++ b/tmpfiles.d/var.conf
@@ -18,4 +18,6 @@ f /var/log/btmp 0600 root utmp -
d /var/cache 0755 - - -
d /var/lib 0755 - - -
+d /var/lib/container 0700 - - -
+
d /var/spool 0755 - - -
......@@ -9,6 +9,7 @@ import unittest
import subprocess
import tempfile
import shutil
import time
class ServicesTest(unittest.TestCase):
......@@ -122,6 +123,8 @@ echo fake container started
ps aux
poweroff\n''')
os.fchmod(f.fileno(), 0o755)
subprocess.check_call(['systemd-machine-id-setup', '--root',
kls.c_busybox], stderr=subprocess.PIPE)
def setUp(self):
self.workdir = tempfile.TemporaryDirectory()
......@@ -129,7 +132,6 @@ poweroff\n''')
def test_boot(self):
cont = os.path.join(self.workdir.name, 'c1')
shutil.copytree(self.c_busybox, cont, symlinks=True)
shutil.copytree(self.c_busybox, '/tmp/cont', symlinks=True)
out = subprocess.check_output(['systemd-nspawn', '-D', cont, '-b'],
timeout=60, stderr=subprocess.STDOUT)
self.assertIn(b'Spawning container c1', out)
......@@ -138,6 +140,20 @@ poweroff\n''')
self.assertRegex(out, b'\n\s+2+\s+0\s.*rcS[\r\n]')
self.assertRegex(out, b'Container c1.*shut down')
def test_service(self):
self.assertTrue(os.path.isdir('/var/lib/container'))
cont = '/var/lib/container/c1'
shutil.copytree(self.c_busybox, cont, symlinks=True)
subprocess.check_call(['systemctl', 'start', 'systemd-nspawn@c1'])
time.sleep(5)
systemctl = subprocess.Popen(
['systemctl', 'status', '-l', 'systemd-nspawn@c1'],
stdout=subprocess.PIPE)
out = systemctl.communicate()[0]
self.assertEqual(systemctl.returncode, 3, out)
self.assertIn(b'Requesting system poweroff', out)
def boot_with_systemd():
'''Reboot with systemd as init
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment