mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
core: Add ProtectHostname=private (#35447)
This PR 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. This is useful for OS-like containers running as units where they should have freedom to change their container hostname if they want, but not the host's hostname. Fixes: #30348
This commit is contained in:
commit
627d1a9ac1
@ -3359,6 +3359,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@ -3958,8 +3960,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<!--property ProcSubset is not documented!-->
|
||||
|
||||
<!--property ProtectHostname is not documented!-->
|
||||
|
||||
<!--property MemoryKSM is not documented!-->
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
@ -4682,6 +4682,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostname"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostnameEx"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="MemoryKSM"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
@ -4879,6 +4881,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
unit file setting <varname>PrivatePIDs=</varname> listed in
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
Note <varname>PrivatePIDs</varname> is a string type to allow adding more values in the future.</para>
|
||||
|
||||
<para><varname>ProtectHostnameEx</varname> implement the destination parameter of the
|
||||
unit file setting <varname>ProtectHostname=</varname> listed in
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
Unlike boolean <varname>ProtectHostname</varname>, <varname>ProtectHostnameEx</varname>
|
||||
is a string type.</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
@ -5544,6 +5552,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@ -6155,8 +6165,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
|
||||
<!--property ProcSubset is not documented!-->
|
||||
|
||||
<!--property ProtectHostname is not documented!-->
|
||||
|
||||
<!--property MemoryKSM is not documented!-->
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
@ -6851,6 +6859,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostname"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostnameEx"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="MemoryKSM"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
@ -7551,6 +7561,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@ -8088,8 +8100,6 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<!--property ProcSubset is not documented!-->
|
||||
|
||||
<!--property ProtectHostname is not documented!-->
|
||||
|
||||
<!--property MemoryKSM is not documented!-->
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
@ -8696,6 +8706,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostname"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostnameEx"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="MemoryKSM"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
@ -9525,6 +9537,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@ -10048,8 +10062,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
|
||||
<!--property ProcSubset is not documented!-->
|
||||
|
||||
<!--property ProtectHostname is not documented!-->
|
||||
|
||||
<!--property MemoryKSM is not documented!-->
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
@ -10642,6 +10654,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostname"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHostnameEx"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="MemoryKSM"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
@ -12305,6 +12319,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
|
||||
<varname>ProtectControlGroupsEx</varname>,
|
||||
<varname>PrivateUsersEx</varname>, and
|
||||
<varname>PrivatePIDs</varname> were added in version 257.</para>
|
||||
<para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Socket Unit Objects</title>
|
||||
@ -12348,6 +12363,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
|
||||
<varname>ManagedOOMMemoryPressureDurationUSec</varname>,
|
||||
<varname>ProtectControlGroupsEx</varname>, and
|
||||
<varname>PrivatePIDs</varname> were added in version 257.</para>
|
||||
<para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Mount Unit Objects</title>
|
||||
@ -12388,6 +12404,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
|
||||
<varname>ManagedOOMMemoryPressureDurationUSec</varname>,
|
||||
<varname>ProtectControlGroupsEx</varname>, and
|
||||
<varname>PrivatePIDs</varname> were added in version 257.</para>
|
||||
<para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Swap Unit Objects</title>
|
||||
@ -12428,6 +12445,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
|
||||
<varname>ManagedOOMMemoryPressureDurationUSec</varname>,
|
||||
<varname>ProtectControlGroupsEx</varname>, and
|
||||
<varname>PrivatePIDs</varname> were added in version 257.</para>
|
||||
<para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Slice Unit Objects</title>
|
||||
|
@ -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>
|
||||
|
@ -95,6 +95,7 @@ Packages=
|
||||
gdb
|
||||
grep
|
||||
gzip
|
||||
hostname
|
||||
jq
|
||||
kbd
|
||||
kexec-tools
|
||||
|
@ -64,6 +64,7 @@ static BUS_DEFINE_PROPERTY_GET_REF(property_get_private_tmp_ex, "s", PrivateTmp,
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_private_users_ex, "s", PrivateUsers, private_users_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_protect_control_groups_ex, "s", ProtectControlGroups, protect_control_groups_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_private_pids, "s", PrivatePIDs, private_pids_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_protect_hostname_ex, "s", ProtectHostname, protect_hostname_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
|
||||
static BUS_DEFINE_PROPERTY_GET(property_get_cpu_affinity_from_numa, "b", ExecContext, exec_context_get_cpu_affinity_from_numa);
|
||||
@ -1068,6 +1069,21 @@ static int property_get_protect_control_groups(
|
||||
return sd_bus_message_append_basic(reply, 'b', &b);
|
||||
}
|
||||
|
||||
static int property_get_protect_hostname(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
ProtectHostname *p = ASSERT_PTR(userdata);
|
||||
int b = *p != PROTECT_HOSTNAME_NO;
|
||||
|
||||
return sd_bus_message_append_basic(reply, 'b', &b);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -1242,7 +1258,8 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc, offsetof(ExecContext, protect_proc), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHostname", "b", property_get_protect_hostname, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHostnameEx", "s", property_get_protect_hostname_ex, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MemoryKSM", "b", bus_property_get_tristate, offsetof(ExecContext, memory_ksm), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -1993,6 +2010,43 @@ int bus_exec_context_set_transient_property(
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (streq(name, "ProtectHostname")) {
|
||||
int v;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->protect_hostname = v ? PROTECT_HOSTNAME_YES : PROTECT_HOSTNAME_NO;
|
||||
(void) unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(v));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
if (streq(name, "ProtectHostnameEx")) {
|
||||
const char *s;
|
||||
ProtectHostname t;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
t = protect_hostname_from_string(s);
|
||||
if (t < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s setting: %s", name, s);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->protect_hostname = t;
|
||||
(void) unit_write_settingf(u, flags, name, "ProtectHostname=%s",
|
||||
protect_hostname_to_string(c->protect_hostname));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (streq(name, "PrivateDevices"))
|
||||
return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error);
|
||||
|
||||
@ -2053,9 +2107,6 @@ int bus_exec_context_set_transient_property(
|
||||
if (streq(name, "LockPersonality"))
|
||||
return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error);
|
||||
|
||||
if (streq(name, "ProtectHostname"))
|
||||
return bus_set_transient_bool(u, name, &c->protect_hostname, message, flags, error);
|
||||
|
||||
if (streq(name, "MemoryKSM"))
|
||||
return bus_set_transient_tristate(u, name, &c->memory_ksm, message, flags, error);
|
||||
|
||||
|
@ -1341,7 +1341,7 @@ static bool context_has_seccomp(const ExecContext *c) {
|
||||
c->memory_deny_write_execute ||
|
||||
c->private_devices ||
|
||||
c->protect_clock ||
|
||||
c->protect_hostname ||
|
||||
c->protect_hostname == PROTECT_HOSTNAME_YES ||
|
||||
c->protect_kernel_tunables ||
|
||||
c->protect_kernel_modules ||
|
||||
c->protect_kernel_logs ||
|
||||
@ -1701,7 +1701,7 @@ static int apply_protect_hostname(const ExecContext *c, const ExecParameters *p,
|
||||
assert(c);
|
||||
assert(p);
|
||||
|
||||
if (!c->protect_hostname)
|
||||
if (c->protect_hostname == PROTECT_HOSTNAME_NO)
|
||||
return 0;
|
||||
|
||||
if (ns_type_supported(NAMESPACE_UTS)) {
|
||||
@ -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,7 +3419,10 @@ 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,
|
||||
.protect_hostname = needs_sandboxing && context->protect_hostname,
|
||||
/* 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,
|
||||
.private_network = needs_sandboxing && exec_needs_network_namespace(context),
|
||||
@ -4055,7 +4060,7 @@ static bool exec_context_need_unprivileged_private_users(
|
||||
context->protect_kernel_logs ||
|
||||
exec_needs_cgroup_mount(context, params) ||
|
||||
context->protect_clock ||
|
||||
context->protect_hostname ||
|
||||
context->protect_hostname != PROTECT_HOSTNAME_NO ||
|
||||
!strv_isempty(context->read_write_paths) ||
|
||||
!strv_isempty(context->read_only_paths) ||
|
||||
!strv_isempty(context->inaccessible_paths) ||
|
||||
|
@ -1978,7 +1978,7 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = serialize_bool_elide(f, "exec-context-protect-hostname", c->protect_hostname);
|
||||
r = serialize_item(f, "exec-context-protect-hostname", protect_hostname_to_string(c->protect_hostname));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2881,10 +2881,9 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
if (c->keyring_mode < 0)
|
||||
return -EINVAL;
|
||||
} else if ((val = startswith(l, "exec-context-protect-hostname="))) {
|
||||
r = parse_boolean(val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
c->protect_hostname = r;
|
||||
c->protect_hostname = protect_hostname_from_string(val);
|
||||
if (c->protect_hostname < 0)
|
||||
return -EINVAL;
|
||||
} else if ((val = startswith(l, "exec-context-protect-proc="))) {
|
||||
c->protect_proc = protect_proc_from_string(val);
|
||||
if (c->protect_proc < 0)
|
||||
|
@ -1071,7 +1071,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
prefix, yes_no(c->restrict_realtime),
|
||||
prefix, yes_no(c->restrict_suid_sgid),
|
||||
prefix, exec_keyring_mode_to_string(c->keyring_mode),
|
||||
prefix, yes_no(c->protect_hostname),
|
||||
prefix, protect_hostname_to_string(c->protect_hostname),
|
||||
prefix, protect_proc_to_string(c->protect_proc),
|
||||
prefix, proc_subset_to_string(c->proc_subset));
|
||||
|
||||
|
@ -336,7 +336,7 @@ struct ExecContext {
|
||||
ProtectSystem protect_system;
|
||||
ProtectHome protect_home;
|
||||
PrivatePIDs private_pids;
|
||||
bool protect_hostname;
|
||||
ProtectHostname protect_hostname;
|
||||
|
||||
bool dynamic_user;
|
||||
bool remove_ipc;
|
||||
|
@ -180,7 +180,7 @@
|
||||
{% else %}
|
||||
{{type}}.SmackProcessLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||
{% endif %}
|
||||
{{type}}.ProtectHostname, config_parse_bool, 0, offsetof({{type}}, exec_context.protect_hostname)
|
||||
{{type}}.ProtectHostname, config_parse_protect_hostname, 0, offsetof({{type}}, exec_context.protect_hostname)
|
||||
{{type}}.MemoryKSM, config_parse_tristate, 0, offsetof({{type}}, exec_context.memory_ksm)
|
||||
{%- endmacro -%}
|
||||
|
||||
|
@ -141,6 +141,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMo
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_hostname, protect_hostname, ProtectHostname);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType);
|
||||
|
@ -119,6 +119,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_protect_control_groups);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_allowed_cpuset);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_hostname);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_bus_name);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_utmp_mode);
|
||||
|
@ -250,7 +250,7 @@ static const MountEntry protect_system_strict_table[] = {
|
||||
};
|
||||
|
||||
/* ProtectHostname=yes able */
|
||||
static const MountEntry protect_hostname_table[] = {
|
||||
static const MountEntry protect_hostname_yes_table[] = {
|
||||
{ "/proc/sys/kernel/hostname", MOUNT_READ_ONLY, false },
|
||||
{ "/proc/sys/kernel/domainname", MOUNT_READ_ONLY, false },
|
||||
};
|
||||
@ -2642,8 +2642,8 @@ int setup_namespace(const NamespaceParameters *p, char **reterr_path) {
|
||||
if (p->protect_hostname) {
|
||||
r = append_static_mounts(
|
||||
&ml,
|
||||
protect_hostname_table,
|
||||
ELEMENTSOF(protect_hostname_table),
|
||||
protect_hostname_yes_table,
|
||||
ELEMENTSOF(protect_hostname_yes_table),
|
||||
ignore_protect_proc);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -3305,6 +3305,14 @@ static const char *const protect_home_table[_PROTECT_HOME_MAX] = {
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(protect_home, ProtectHome, PROTECT_HOME_YES);
|
||||
|
||||
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);
|
||||
|
||||
static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = {
|
||||
[PROTECT_SYSTEM_NO] = "no",
|
||||
[PROTECT_SYSTEM_YES] = "yes",
|
||||
|
@ -28,6 +28,14 @@ typedef enum ProtectHome {
|
||||
_PROTECT_HOME_INVALID = -EINVAL,
|
||||
} ProtectHome;
|
||||
|
||||
typedef enum ProtectHostname {
|
||||
PROTECT_HOSTNAME_NO,
|
||||
PROTECT_HOSTNAME_YES,
|
||||
PROTECT_HOSTNAME_PRIVATE,
|
||||
_PROTECT_HOSTNAME_MAX,
|
||||
_PROTECT_HOSTNAME_INVALID = -EINVAL,
|
||||
} ProtectHostname;
|
||||
|
||||
typedef enum ProtectSystem {
|
||||
PROTECT_SYSTEM_NO,
|
||||
PROTECT_SYSTEM_YES,
|
||||
@ -215,6 +223,9 @@ int open_shareable_ns_path(int netns_storage_socket[static 2], const char *path,
|
||||
const char* protect_home_to_string(ProtectHome p) _const_;
|
||||
ProtectHome protect_home_from_string(const char *s) _pure_;
|
||||
|
||||
const char* protect_hostname_to_string(ProtectHostname p) _const_;
|
||||
ProtectHostname protect_hostname_from_string(const char *s) _pure_;
|
||||
|
||||
const char* protect_system_to_string(ProtectSystem p) _const_;
|
||||
ProtectSystem protect_system_from_string(const char *s) _pure_;
|
||||
|
||||
|
@ -1045,6 +1045,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
"SyslogIdentifier",
|
||||
"ProtectSystem",
|
||||
"ProtectHome",
|
||||
"ProtectHostnameEx",
|
||||
"PrivateTmpEx",
|
||||
"PrivateUsersEx",
|
||||
"ProtectControlGroupsEx",
|
||||
|
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…
Reference in New Issue
Block a user