mirror of
https://github.com/systemd/systemd.git
synced 2025-03-11 20:58:27 +03:00
core: Add ProtectHostname=private
This allows an option for systemd exec units to enable UTS namespaces but not restrict changing hostname via seccomp. Thus, units can change hostname without affecting the host. Fixes: #30348
This commit is contained in:
parent
6746f28854
commit
cf48bde7ae
@ -2055,8 +2055,11 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
|
||||
<varlistentry>
|
||||
<term><varname>ProtectHostname=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. When set, sets up a new UTS namespace for the executed
|
||||
processes. In addition, changing hostname or domainname is prevented. Defaults to off.</para>
|
||||
<listitem><para>Takes a boolean argument or <literal>private</literal>. If enabled, sets up a new UTS namespace
|
||||
for the executed processes. If set to a true value, changing hostname or domainname via
|
||||
<function>sethostname()</function> and <function>setdomainname()</function> system calls is prevented. If set to
|
||||
<literal>private</literal>, changing hostname or domainname is allowed but only affects the unit's UTS namespace.
|
||||
Defaults to off.</para>
|
||||
|
||||
<para>Note that the implementation of this setting might be impossible (for example if UTS namespaces
|
||||
are not available), and the unit should be written in a way that does not solely rely on this setting
|
||||
@ -2066,6 +2069,12 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
|
||||
the system into the service, it is hence not suitable for services that need to take notice of system
|
||||
hostname changes dynamically.</para>
|
||||
|
||||
<para>Note that this option does not prevent changing system hostname via <command>hostnamectl</command>.
|
||||
However, <varname>User=</varname> and <varname>Group=</varname> may be used to run as an unprivileged user
|
||||
to disallow changing system hostname. See <function>SetHostname()</function> in
|
||||
<citerefentry project="man-pages"><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for more details.</para>
|
||||
|
||||
<xi:include href="system-or-user-ns.xml" xpointer="singular"/>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v242"/></listitem>
|
||||
|
@ -101,6 +101,7 @@ Packages=
|
||||
gdb
|
||||
grep
|
||||
gzip
|
||||
hostname
|
||||
jq
|
||||
kbd
|
||||
kexec-tools
|
||||
|
@ -1726,15 +1726,17 @@ static int apply_protect_hostname(const ExecContext *c, const ExecParameters *p,
|
||||
"support UTS namespaces, ignoring namespace setup.");
|
||||
|
||||
#if HAVE_SECCOMP
|
||||
int r;
|
||||
if (c->protect_hostname == PROTECT_HOSTNAME_YES) {
|
||||
int r;
|
||||
|
||||
if (skip_seccomp_unavailable(c, p, "ProtectHostname="))
|
||||
return 0;
|
||||
if (skip_seccomp_unavailable(c, p, "ProtectHostname="))
|
||||
return 0;
|
||||
|
||||
r = seccomp_protect_hostname();
|
||||
if (r < 0) {
|
||||
*ret_exit_status = EXIT_SECCOMP;
|
||||
return log_exec_error_errno(c, p, r, "Failed to apply hostname restrictions: %m");
|
||||
r = seccomp_protect_hostname();
|
||||
if (r < 0) {
|
||||
*ret_exit_status = EXIT_SECCOMP;
|
||||
return log_exec_error_errno(c, p, r, "Failed to apply hostname restrictions: %m");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3417,6 +3419,9 @@ static int apply_mount_namespace(
|
||||
.protect_kernel_tunables = needs_sandboxing && context->protect_kernel_tunables,
|
||||
.protect_kernel_modules = needs_sandboxing && context->protect_kernel_modules,
|
||||
.protect_kernel_logs = needs_sandboxing && context->protect_kernel_logs,
|
||||
/* Only mount /proc/sys/kernel/hostname and domainname read-only if ProtectHostname=yes. Otherwise, ProtectHostname=no
|
||||
* allows changing hostname for the host and ProtectHostname=private allows changing the hostname in the unit's UTS
|
||||
* namespace. */
|
||||
.protect_hostname = needs_sandboxing && context->protect_hostname == PROTECT_HOSTNAME_YES,
|
||||
|
||||
.private_dev = needs_sandboxing && context->private_devices,
|
||||
|
@ -3308,6 +3308,7 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(protect_home, ProtectHome, PROTECT_HOME_
|
||||
static const char *const protect_hostname_table[_PROTECT_HOSTNAME_MAX] = {
|
||||
[PROTECT_HOSTNAME_NO] = "no",
|
||||
[PROTECT_HOSTNAME_YES] = "yes",
|
||||
[PROTECT_HOSTNAME_PRIVATE] = "private",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(protect_hostname, ProtectHostname, PROTECT_HOSTNAME_YES);
|
||||
|
@ -31,6 +31,7 @@ typedef enum ProtectHome {
|
||||
typedef enum ProtectHostname {
|
||||
PROTECT_HOSTNAME_NO,
|
||||
PROTECT_HOSTNAME_YES,
|
||||
PROTECT_HOSTNAME_PRIVATE,
|
||||
_PROTECT_HOSTNAME_MAX,
|
||||
_PROTECT_HOSTNAME_INVALID = -EINVAL,
|
||||
} ProtectHostname;
|
||||
|
44
test/units/TEST-07-PID1.protect-hostname.sh
Executable file
44
test/units/TEST-07-PID1.protect-hostname.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
# shellcheck disable=SC2016
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
# shellcheck source=test/units/test-control.sh
|
||||
. "$(dirname "$0")"/test-control.sh
|
||||
# shellcheck source=test/units/util.sh
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
LEGACY_HOSTNAME="$(hostname)"
|
||||
HOSTNAME_FROM_SYSTEMD="$(hostnamectl hostname)"
|
||||
|
||||
testcase_yes() {
|
||||
# hostnamectl calls SetHostname method via dbus socket which executes in homenamed
|
||||
# in the init namespace. So hostnamectl is not affected by ProtectHostname=yes or
|
||||
# private since sethostname() system call is executed in the init namespace.
|
||||
#
|
||||
# hostnamed does authentication based on UID via polkit so this guarantees admins
|
||||
# can only set hostname.
|
||||
(! systemd-run --wait -p ProtectHostname=yes hostname foo)
|
||||
|
||||
systemd-run --wait -p ProtectHostname=yes -p PrivateMounts=yes \
|
||||
findmnt --mountpoint /proc/sys/kernel/hostname
|
||||
}
|
||||
|
||||
testcase_private() {
|
||||
systemd-run --wait -p ProtectHostnameEx=private \
|
||||
-P bash -xec '
|
||||
hostname foo
|
||||
test "$(hostname)" = "foo"
|
||||
'
|
||||
|
||||
# Verify host hostname is unchanged.
|
||||
test "$(hostname)" = "$LEGACY_HOSTNAME"
|
||||
test "$(hostnamectl hostname)" = "$HOSTNAME_FROM_SYSTEMD"
|
||||
|
||||
# Verify /proc/sys/kernel/hostname is not bind mounted from host read-only.
|
||||
(! systemd-run --wait -p ProtectHostnameEx=private -p PrivateMounts=yes \
|
||||
findmnt --mountpoint /proc/sys/kernel/hostname)
|
||||
}
|
||||
|
||||
run_testcases
|
Loading…
x
Reference in New Issue
Block a user