diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 7a88436bcf..ffd707092c 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -277,7 +277,15 @@
the container. This makes all network
interfaces unavailable in the
container, with the exception of the
- loopback device.
+ loopback device and those specified
+ with
+ . If
+ this option is specified the
+ CAP_NET_ADMIN capability will be added
+ to the set of capabilities the
+ container retains. The latter may be
+ disabled by using
+ .
@@ -290,7 +298,13 @@
namespace and place it in the
container. When the container
terminates it is moved back to the
- host namespace.
+ host namespace. Note that
+
+ implies
+ . This
+ option may be used more than once to
+ add multiple network interfaces to the
+ container.
@@ -323,8 +337,11 @@
CAP_SYS_CHROOT, CAP_SYS_NICE,
CAP_SYS_PTRACE, CAP_SYS_TTY_CONFIG,
CAP_SYS_RESOURCE, CAP_SYS_BOOT,
- CAP_AUDIT_WRITE, CAP_AUDIT_CONTROL. If
- the special value
+ CAP_AUDIT_WRITE,
+ CAP_AUDIT_CONTROL. Also CAP_NET_ADMIN
+ is retained if
+ is
+ specified. If the special value
all is passed all
capabilities are
retained.
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 679c005071..9ce1fa9b49 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -216,6 +216,7 @@ static int parse_argv(int argc, char *argv[]) {
};
int c, r;
+ uint64_t plus = 0, minus = 0;
assert(argc >= 0);
assert(argv);
@@ -325,9 +326,9 @@ static int parse_argv(int argc, char *argv[]) {
if (streq(t, "all")) {
if (c == ARG_CAPABILITY)
- arg_retain = (uint64_t) -1;
+ plus = (uint64_t) -1;
else
- arg_retain = 0;
+ minus = (uint64_t) -1;
} else {
if (cap_from_name(t, &cap) < 0) {
log_error("Failed to parse capability %s.", t);
@@ -335,9 +336,9 @@ static int parse_argv(int argc, char *argv[]) {
}
if (c == ARG_CAPABILITY)
- arg_retain |= 1ULL << (uint64_t) cap;
+ plus |= 1ULL << (uint64_t) cap;
else
- arg_retain &= ~(1ULL << (uint64_t) cap);
+ minus |= 1ULL << (uint64_t) cap;
}
}
@@ -460,6 +461,8 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
+ arg_retain = (arg_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus;
+
return 1;
}