Merge pull request #14673 from keur/protect_clock

Protect clock
This commit is contained in:
Lennart Poettering
2020-01-28 15:11:41 +01:00
committed by GitHub
9 changed files with 75 additions and 6 deletions
+1
View File
@@ -192,6 +192,7 @@ All execution-related settings are available for transient units.
✓ PrivateUsers=
✓ ProtectSystem=
✓ ProtectHome=
✓ ProtectClock=
✓ MountFlags=
✓ MountAPIVFS=
✓ Personality=
+21 -6
View File
@@ -405,11 +405,11 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<varname>RestrictAddressFamilies=</varname>, <varname>RestrictNamespaces=</varname>,
<varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
<varname>ProtectKernelModules=</varname>, <varname>ProtectKernelLogs=</varname>,
<varname>MemoryDenyWriteExecute=</varname>, <varname>RestrictRealtime=</varname>,
<varname>RestrictSUIDSGID=</varname>, <varname>DynamicUser=</varname> or <varname>LockPersonality=</varname>
are specified. Note that even if this setting is overridden by them, <command>systemctl show</command> shows the
original value of this setting. Also see <ulink
url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
<varname>ProtectClock=</varname>, <varname>MemoryDenyWriteExecute=</varname>,
<varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname>, <varname>DynamicUser=</varname>
or <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by them,
<command>systemctl show</command> shows the original value of this setting.
Also see <ulink url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
Flag</ulink>.</para></listitem>
</varlistentry>
@@ -1296,6 +1296,21 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>ProtectClock=</varname></term>
<listitem><para>Takes a boolean argument. If set, writes to the hardware clock or system clock will be denied.
It is recommended to turn this on for most services that do not need modify the clock. Defaults to off. Enabling
this option removes <constant>CAP_SYS_TIME</constant> and <constant>CAP_WAKE_ALARM</constant> from the
capability bounding set for this unit, installs a system call filter to block calls that can set the
clock, and <varname>DeviceAllow=char-rtc r</varname> is implied. This ensures <filename>/dev/rtc0</filename>,
<filename>/dev/rtc1</filename>, etc are made read only to the service. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for the details about <varname>DeviceAllow=</varname>.</para>
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>ProtectKernelTunables=</varname></term>
@@ -1807,7 +1822,7 @@ SystemCallErrorNumber=EPERM</programlisting>
mappings. Specifically these are the options <varname>PrivateTmp=</varname>,
<varname>PrivateDevices=</varname>, <varname>ProtectSystem=</varname>, <varname>ProtectHome=</varname>,
<varname>ProtectKernelTunables=</varname>, <varname>ProtectControlGroups=</varname>,
<varname>ProtectKernelLogs=</varname>, <varname>ReadOnlyPaths=</varname>,
<varname>ProtectKernelLogs=</varname>, <varname>ProtectClock=</varname>, <varname>ReadOnlyPaths=</varname>,
<varname>InaccessiblePaths=</varname> and <varname>ReadWritePaths=</varname>.</para></listitem>
</varlistentry>
+16
View File
@@ -65,6 +65,7 @@ struct security_info {
bool protect_kernel_modules;
bool protect_kernel_tunables;
bool protect_kernel_logs;
bool protect_clock;
char *protect_home;
char *protect_system;
@@ -783,6 +784,16 @@ static const struct security_assessor security_assessor_table[] = {
.assess = assess_bool,
.offset = offsetof(struct security_info, protect_kernel_logs),
},
{
.id = "ProtectClock=",
.description_good = "Service cannot write to the hardware clock or system clock",
.description_bad = "Service may write to the hardware clock or system clock",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectClock=",
.weight = 1000,
.range = 1,
.assess = assess_bool,
.offset = offsetof(struct security_info, protect_clock),
},
{
.id = "ProtectHome=",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=",
@@ -1907,6 +1918,7 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_
{ "ProtectKernelModules", "b", NULL, offsetof(struct security_info, protect_kernel_modules) },
{ "ProtectKernelTunables", "b", NULL, offsetof(struct security_info, protect_kernel_tunables) },
{ "ProtectKernelLogs", "b", NULL, offsetof(struct security_info, protect_kernel_logs) },
{ "ProtectClock", "b", NULL, offsetof(struct security_info, protect_clock) },
{ "ProtectSystem", "s", NULL, offsetof(struct security_info, protect_system) },
{ "RemoveIPC", "b", NULL, offsetof(struct security_info, remove_ipc) },
{ "RestrictAddressFamilies", "(bas)", property_read_restrict_address_families, 0 },
@@ -1984,6 +1996,10 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_
if (info->protect_kernel_logs)
info->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYSLOG);
if (info->protect_clock)
info->capability_bounding_set &= ~((UINT64_C(1) << CAP_SYS_TIME) |
(UINT64_C(1) << CAP_WAKE_ALARM));
if (info->private_devices)
info->capability_bounding_set &= ~((UINT64_C(1) << CAP_MKNOD) |
(UINT64_C(1) << CAP_SYS_RAWIO));
+3
View File
@@ -1284,6 +1284,9 @@ int bus_exec_context_set_transient_property(
if (streq(name, "ProtectKernelLogs"))
return bus_set_transient_bool(u, name, &c->protect_kernel_logs, message, flags, error);
if (streq(name, "ProtectClock"))
return bus_set_transient_bool(u, name, &c->protect_clock, message, flags, error);
if (streq(name, "ProtectControlGroups"))
return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
+22
View File
@@ -1402,6 +1402,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
c->restrict_realtime ||
c->restrict_suid_sgid ||
exec_context_restrict_namespaces_set(c) ||
c->protect_clock ||
c->protect_kernel_tunables ||
c->protect_kernel_modules ||
c->protect_kernel_logs ||
@@ -1564,6 +1565,19 @@ static int apply_protect_kernel_logs(const Unit *u, const ExecContext *c) {
return seccomp_protect_syslog();
}
static int apply_protect_clock(const Unit *u, const ExecContext *c) {
assert(u);
assert(c);
if (!c->protect_clock)
return 0;
if (skip_seccomp_unavailable(u, "ProtectClock="))
return 0;
return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_CLOCK, SCMP_ACT_ERRNO(EPERM), false);
}
static int apply_private_devices(const Unit *u, const ExecContext *c) {
assert(u);
assert(c);
@@ -3797,6 +3811,12 @@ static int exec_child(
return log_unit_error_errno(unit, r, "Failed to apply kernel log restrictions: %m");
}
r = apply_protect_clock(unit, context);
if (r < 0) {
*exit_status = EXIT_SECCOMP;
return log_unit_error_errno(unit, r, "Failed to apply clock restrictions: %m");
}
r = apply_private_devices(unit, context);
if (r < 0) {
*exit_status = EXIT_SECCOMP;
@@ -4437,6 +4457,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
"%sProtectKernelTunables: %s\n"
"%sProtectKernelModules: %s\n"
"%sProtectKernelLogs: %s\n"
"%sProtectClock: %s\n"
"%sProtectControlGroups: %s\n"
"%sPrivateNetwork: %s\n"
"%sPrivateUsers: %s\n"
@@ -4458,6 +4479,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
prefix, yes_no(c->protect_kernel_tunables),
prefix, yes_no(c->protect_kernel_modules),
prefix, yes_no(c->protect_kernel_logs),
prefix, yes_no(c->protect_clock),
prefix, yes_no(c->protect_control_groups),
prefix, yes_no(c->private_network),
prefix, yes_no(c->private_users),
+1
View File
@@ -258,6 +258,7 @@ struct ExecContext {
bool protect_kernel_tunables;
bool protect_kernel_modules;
bool protect_kernel_logs;
bool protect_clock;
bool protect_control_groups;
ProtectSystem protect_system;
ProtectHome protect_home;
+1
View File
@@ -116,6 +116,7 @@ $1.PrivateDevices, config_parse_bool, 0,
$1.ProtectKernelTunables, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_tunables)
$1.ProtectKernelModules, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_modules)
$1.ProtectKernelLogs, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_logs)
$1.ProtectClock, config_parse_bool, 0, offsetof($1, exec_context.protect_clock)
$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups)
$1.NetworkNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.network_namespace_path)
$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
+9
View File
@@ -4287,6 +4287,9 @@ int unit_patch_contexts(Unit *u) {
if (ec->protect_kernel_logs)
ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYSLOG);
if (ec->protect_clock)
ec->capability_bounding_set &= ~((UINT64_C(1) << CAP_SYS_TIME) | (UINT64_C(1) << CAP_WAKE_ALARM));
if (ec->dynamic_user) {
if (!ec->user) {
r = user_from_unit_name(u, &ec->user);
@@ -4345,6 +4348,12 @@ int unit_patch_contexts(Unit *u) {
if (r < 0)
return r;
}
if (ec->protect_clock) {
r = cgroup_add_device_allow(cc, "char-rtc", "r");
if (r < 0)
return r;
}
}
return 0;
+1
View File
@@ -854,6 +854,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
"ProtectKernelTunables",
"ProtectKernelModules",
"ProtectKernelLogs",
"ProtectClock",
"ProtectControlGroups",
"MountAPIVFS",
"CPUSchedulingResetOnFork",