Compare commits
14 Commits
7be830c6e8
...
f0bfae7265
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | f0bfae7265 | |
Lennart Poettering | 8af381679d | |
Lennart Poettering | e41e9ba8bf | |
Lennart Poettering | c59e2ec696 | |
Lennart Poettering | 385d581b74 | |
Kevin Kuehler | 82dce83b19 | |
Kevin Kuehler | 6168ae5840 | |
Kevin Kuehler | 806aea3879 | |
Kevin Kuehler | d916e35b9f | |
Kevin Kuehler | 97d05f3b70 | |
Kevin Kuehler | 94a7b2759d | |
Kevin Kuehler | 07cab0f72b | |
Kevin Kuehler | 8470304018 | |
Kevin Kuehler | 620dbdd248 |
|
@ -402,11 +402,11 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
|||
<varname>SystemCallFilter=</varname>, <varname>SystemCallArchitectures=</varname>,
|
||||
<varname>RestrictAddressFamilies=</varname>, <varname>RestrictNamespaces=</varname>,
|
||||
<varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
|
||||
<varname>ProtectKernelModules=</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
|
||||
<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
|
||||
Flag</ulink>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
@ -1321,6 +1321,22 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
|
|||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ProtectKernelLogs=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. If true, access to the kernel log ring buffer will be denied. It is
|
||||
recommended to turn this on for most services that do not need to read from or write to the kernel log ring
|
||||
buffer. Enabling this option removes <constant>CAP_SYSLOG</constant> from the capability bounding set for this
|
||||
unit, and installs a system call filter to block the
|
||||
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
system call (not to be confused with the libc API
|
||||
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
for userspace logging). The kernel exposes its log buffer to userspace via <filename>/dev/kmsg</filename> and
|
||||
<filename>/proc/kmsg</filename>. If enabled, these are made inaccessible to all the processes in the unit.</para>
|
||||
|
||||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ProtectControlGroups=</varname></term>
|
||||
|
||||
|
@ -1772,8 +1788,8 @@ 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>ReadOnlyPaths=</varname>, <varname>InaccessiblePaths=</varname> and
|
||||
<varname>ReadWritePaths=</varname>.</para></listitem>
|
||||
<varname>ProtectKernelLogs=</varname>, <varname>ReadOnlyPaths=</varname>,
|
||||
<varname>InaccessiblePaths=</varname> and <varname>ReadWritePaths=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -64,6 +64,7 @@ struct security_info {
|
|||
bool protect_control_groups;
|
||||
bool protect_kernel_modules;
|
||||
bool protect_kernel_tunables;
|
||||
bool protect_kernel_logs;
|
||||
|
||||
char *protect_home;
|
||||
char *protect_system;
|
||||
|
@ -772,6 +773,16 @@ static const struct security_assessor security_assessor_table[] = {
|
|||
.assess = assess_bool,
|
||||
.offset = offsetof(struct security_info, protect_kernel_tunables),
|
||||
},
|
||||
{
|
||||
.id = "ProtectKernelLogs=",
|
||||
.description_good = "Service cannot read from or write to the kernel log ring buffer",
|
||||
.description_bad = "Service may read from or write to the kernel log ring buffer",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelLogs=",
|
||||
.weight = 1000,
|
||||
.range = 1,
|
||||
.assess = assess_bool,
|
||||
.offset = offsetof(struct security_info, protect_kernel_logs),
|
||||
},
|
||||
{
|
||||
.id = "ProtectHome=",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=",
|
||||
|
@ -1906,6 +1917,7 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_
|
|||
{ "ProtectHostname", "b", NULL, offsetof(struct security_info, protect_hostname) },
|
||||
{ "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) },
|
||||
{ "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 },
|
||||
|
@ -1980,6 +1992,9 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_
|
|||
if (info->protect_kernel_modules)
|
||||
info->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYS_MODULE);
|
||||
|
||||
if (info->protect_kernel_logs)
|
||||
info->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYSLOG);
|
||||
|
||||
if (info->private_devices)
|
||||
info->capability_bounding_set &= ~((UINT64_C(1) << CAP_MKNOD) |
|
||||
(UINT64_C(1) << CAP_SYS_RAWIO));
|
||||
|
|
|
@ -783,6 +783,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
|||
SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectKernelLogs", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_logs), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
@ -1274,6 +1275,9 @@ int bus_exec_context_set_transient_property(
|
|||
if (streq(name, "ProtectKernelModules"))
|
||||
return bus_set_transient_bool(u, name, &c->protect_kernel_modules, message, flags, error);
|
||||
|
||||
if (streq(name, "ProtectKernelLogs"))
|
||||
return bus_set_transient_bool(u, name, &c->protect_kernel_logs, message, flags, error);
|
||||
|
||||
if (streq(name, "ProtectControlGroups"))
|
||||
return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
|
||||
|
||||
|
|
|
@ -1396,6 +1396,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
|
|||
exec_context_restrict_namespaces_set(c) ||
|
||||
c->protect_kernel_tunables ||
|
||||
c->protect_kernel_modules ||
|
||||
c->protect_kernel_logs ||
|
||||
c->private_devices ||
|
||||
context_has_syscall_filters(c) ||
|
||||
!set_isempty(c->syscall_archs) ||
|
||||
|
@ -1542,6 +1543,19 @@ static int apply_protect_kernel_modules(const Unit *u, const ExecContext *c) {
|
|||
return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM), false);
|
||||
}
|
||||
|
||||
static int apply_protect_kernel_logs(const Unit *u, const ExecContext *c) {
|
||||
assert(u);
|
||||
assert(c);
|
||||
|
||||
if (!c->protect_kernel_logs)
|
||||
return 0;
|
||||
|
||||
if (skip_seccomp_unavailable(u, "ProtectKernelLogs="))
|
||||
return 0;
|
||||
|
||||
return seccomp_protect_syslog();
|
||||
}
|
||||
|
||||
static int apply_private_devices(const Unit *u, const ExecContext *c) {
|
||||
assert(u);
|
||||
assert(c);
|
||||
|
@ -1858,6 +1872,7 @@ static bool exec_needs_mount_namespace(
|
|||
context->protect_home != PROTECT_HOME_NO ||
|
||||
context->protect_kernel_tunables ||
|
||||
context->protect_kernel_modules ||
|
||||
context->protect_kernel_logs ||
|
||||
context->protect_control_groups)
|
||||
return true;
|
||||
|
||||
|
@ -2493,6 +2508,7 @@ static int apply_mount_namespace(
|
|||
.protect_control_groups = context->protect_control_groups,
|
||||
.protect_kernel_tunables = context->protect_kernel_tunables,
|
||||
.protect_kernel_modules = context->protect_kernel_modules,
|
||||
.protect_kernel_logs = context->protect_kernel_logs,
|
||||
.protect_hostname = context->protect_hostname,
|
||||
.mount_apivfs = context->mount_apivfs,
|
||||
.private_mounts = context->private_mounts,
|
||||
|
@ -3679,6 +3695,12 @@ static int exec_child(
|
|||
return log_unit_error_errno(unit, r, "Failed to apply module loading restrictions: %m");
|
||||
}
|
||||
|
||||
r = apply_protect_kernel_logs(unit, context);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_SECCOMP;
|
||||
return log_unit_error_errno(unit, r, "Failed to apply kernel log restrictions: %m");
|
||||
}
|
||||
|
||||
r = apply_private_devices(unit, context);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_SECCOMP;
|
||||
|
@ -4318,6 +4340,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
|||
"%sPrivateDevices: %s\n"
|
||||
"%sProtectKernelTunables: %s\n"
|
||||
"%sProtectKernelModules: %s\n"
|
||||
"%sProtectKernelLogs: %s\n"
|
||||
"%sProtectControlGroups: %s\n"
|
||||
"%sPrivateNetwork: %s\n"
|
||||
"%sPrivateUsers: %s\n"
|
||||
|
@ -4338,6 +4361,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
|||
prefix, yes_no(c->private_devices),
|
||||
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_control_groups),
|
||||
prefix, yes_no(c->private_network),
|
||||
prefix, yes_no(c->private_users),
|
||||
|
|
|
@ -257,6 +257,7 @@ struct ExecContext {
|
|||
bool private_mounts;
|
||||
bool protect_kernel_tunables;
|
||||
bool protect_kernel_modules;
|
||||
bool protect_kernel_logs;
|
||||
bool protect_control_groups;
|
||||
ProtectSystem protect_system;
|
||||
ProtectHome protect_home;
|
||||
|
|
|
@ -115,6 +115,7 @@ $1.PrivateTmp, config_parse_bool, 0,
|
|||
$1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices)
|
||||
$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.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)
|
||||
|
|
|
@ -109,6 +109,12 @@ static const MountEntry protect_kernel_modules_table[] = {
|
|||
{ "/usr/lib/modules", INACCESSIBLE, true },
|
||||
};
|
||||
|
||||
/* ProtectKernelLogs= option */
|
||||
static const MountEntry protect_kernel_logs_table[] = {
|
||||
{ "/proc/kmsg", INACCESSIBLE, true },
|
||||
{ "/dev/kmsg", INACCESSIBLE, true },
|
||||
};
|
||||
|
||||
/*
|
||||
* ProtectHome=read-only table, protect $HOME and $XDG_RUNTIME_DIR and rest of
|
||||
* system should be protected by ProtectSystem=
|
||||
|
@ -1147,8 +1153,9 @@ static size_t namespace_calculate_mounts(
|
|||
n_temporary_filesystems +
|
||||
ns_info->private_dev +
|
||||
(ns_info->protect_kernel_tunables ? ELEMENTSOF(protect_kernel_tunables_table) : 0) +
|
||||
(ns_info->protect_control_groups ? 1 : 0) +
|
||||
(ns_info->protect_kernel_modules ? ELEMENTSOF(protect_kernel_modules_table) : 0) +
|
||||
(ns_info->protect_kernel_logs ? ELEMENTSOF(protect_kernel_logs_table) : 0) +
|
||||
(ns_info->protect_control_groups ? 1 : 0) +
|
||||
protect_home_cnt + protect_system_cnt +
|
||||
(ns_info->protect_hostname ? 2 : 0) +
|
||||
(namespace_info_mount_apivfs(ns_info) ? ELEMENTSOF(apivfs_table) : 0);
|
||||
|
@ -1319,6 +1326,12 @@ int setup_namespace(
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (ns_info->protect_kernel_logs) {
|
||||
r = append_static_mounts(&m, protect_kernel_logs_table, ELEMENTSOF(protect_kernel_logs_table), ns_info->ignore_protect_paths);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (ns_info->protect_control_groups) {
|
||||
*(m++) = (MountEntry) {
|
||||
.path_const = "/sys/fs/cgroup",
|
||||
|
|
|
@ -51,6 +51,7 @@ struct NamespaceInfo {
|
|||
bool protect_control_groups:1;
|
||||
bool protect_kernel_tunables:1;
|
||||
bool protect_kernel_modules:1;
|
||||
bool protect_kernel_logs:1;
|
||||
bool mount_apivfs:1;
|
||||
bool protect_hostname:1;
|
||||
};
|
||||
|
|
|
@ -4269,6 +4269,9 @@ int unit_patch_contexts(Unit *u) {
|
|||
if (ec->protect_kernel_modules)
|
||||
ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYS_MODULE);
|
||||
|
||||
if (ec->protect_kernel_logs)
|
||||
ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYSLOG);
|
||||
|
||||
if (ec->dynamic_user) {
|
||||
if (!ec->user) {
|
||||
r = user_from_unit_name(u, &ec->user);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "sigbus.h"
|
||||
#include "signal-util.h"
|
||||
#include "sort-util.h"
|
||||
#include "spawn-ask-password-agent.h"
|
||||
#include "spawn-polkit-agent.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
|
@ -1722,6 +1723,7 @@ static int start_machine(int argc, char *argv[], void *userdata) {
|
|||
assert(bus);
|
||||
|
||||
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
ask_password_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
|
||||
r = bus_wait_for_jobs_new(bus, &w);
|
||||
if (r < 0)
|
||||
|
|
|
@ -818,8 +818,8 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
|||
"PrivateDevices", "PrivateNetwork", "PrivateUsers", "PrivateMounts",
|
||||
"NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", "RestrictRealtime",
|
||||
"DynamicUser", "RemoveIPC", "ProtectKernelTunables", "ProtectKernelModules",
|
||||
"ProtectControlGroups", "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality",
|
||||
"ProtectHostname", "RestrictSUIDSGID"))
|
||||
"ProtectKernelLogs", "ProtectControlGroups", "MountAPIVFS", "CPUSchedulingResetOnFork",
|
||||
"LockPersonality", "ProtectHostname", "RestrictSUIDSGID"))
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field,
|
||||
|
|
|
@ -1281,6 +1281,38 @@ int seccomp_protect_sysctl(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int seccomp_protect_syslog(void) {
|
||||
uint32_t arch;
|
||||
int r;
|
||||
|
||||
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
|
||||
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
|
||||
|
||||
r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = seccomp_rule_add_exact(
|
||||
seccomp,
|
||||
SCMP_ACT_ERRNO(EPERM),
|
||||
SCMP_SYS(syslog),
|
||||
0);
|
||||
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to add syslog() rule for architecture %s, skipping %m", seccomp_arch_to_string(arch));
|
||||
continue;
|
||||
}
|
||||
|
||||
r = seccomp_load(seccomp);
|
||||
if (ERRNO_IS_SECCOMP_FATAL(r))
|
||||
return r;
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to install syslog protection rules for architecture %s, skipping %m", seccomp_arch_to_string(arch));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
|
||||
uint32_t arch;
|
||||
int r;
|
||||
|
|
|
@ -82,6 +82,7 @@ int seccomp_parse_syscall_filter(
|
|||
int seccomp_restrict_archs(Set *archs);
|
||||
int seccomp_restrict_namespaces(unsigned long retain);
|
||||
int seccomp_protect_sysctl(void);
|
||||
int seccomp_protect_syslog(void);
|
||||
int seccomp_restrict_address_families(Set *address_families, bool whitelist);
|
||||
int seccomp_restrict_realtime(void);
|
||||
int seccomp_memory_deny_write_execute(void);
|
||||
|
|
|
@ -46,3 +46,16 @@ void ask_password_agent_close(void) {
|
|||
(void) wait_for_terminate(agent_pid, NULL);
|
||||
agent_pid = 0;
|
||||
}
|
||||
|
||||
int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password) {
|
||||
|
||||
/* Open the ask password agent as a child process if necessary */
|
||||
|
||||
if (transport != BUS_TRANSPORT_LOCAL)
|
||||
return 0;
|
||||
|
||||
if (!ask_password)
|
||||
return 0;
|
||||
|
||||
return ask_password_agent_open();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bus-util.h"
|
||||
|
||||
int ask_password_agent_open(void);
|
||||
void ask_password_agent_close(void);
|
||||
|
||||
int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password);
|
||||
|
|
|
@ -83,3 +83,16 @@ void polkit_agent_close(void) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
int polkit_agent_open_if_enabled(BusTransport transport, bool ask_password) {
|
||||
|
||||
/* Open the polkit agent as a child process if necessary */
|
||||
|
||||
if (transport != BUS_TRANSPORT_LOCAL)
|
||||
return 0;
|
||||
|
||||
if (!ask_password)
|
||||
return 0;
|
||||
|
||||
return polkit_agent_open();
|
||||
}
|
||||
|
|
|
@ -1,22 +1,11 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bus-util.h"
|
||||
|
||||
int polkit_agent_open(void);
|
||||
void polkit_agent_close(void);
|
||||
|
||||
static inline int polkit_agent_open_if_enabled(
|
||||
BusTransport transport,
|
||||
bool ask_password) {
|
||||
|
||||
/* Open the polkit agent as a child process if necessary */
|
||||
|
||||
if (transport != BUS_TRANSPORT_LOCAL)
|
||||
return 0;
|
||||
|
||||
if (!ask_password)
|
||||
return 0;
|
||||
|
||||
return polkit_agent_open();
|
||||
}
|
||||
int polkit_agent_open_if_enabled(BusTransport transport, bool ask_password);
|
||||
|
|
|
@ -236,22 +236,16 @@ static void release_busses(void) {
|
|||
buses[w] = sd_bus_flush_close_unref(buses[w]);
|
||||
}
|
||||
|
||||
static void ask_password_agent_open_if_enabled(void) {
|
||||
static void ask_password_agent_open_maybe(void) {
|
||||
/* Open the password agent as a child process if necessary */
|
||||
|
||||
if (arg_dry_run)
|
||||
return;
|
||||
|
||||
if (!arg_ask_password)
|
||||
return;
|
||||
|
||||
if (arg_scope != UNIT_FILE_SYSTEM)
|
||||
return;
|
||||
|
||||
if (arg_transport != BUS_TRANSPORT_LOCAL)
|
||||
return;
|
||||
|
||||
ask_password_agent_open();
|
||||
ask_password_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
}
|
||||
|
||||
static void polkit_agent_open_maybe(void) {
|
||||
|
@ -3071,7 +3065,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ask_password_agent_open_if_enabled();
|
||||
ask_password_agent_open_maybe();
|
||||
polkit_agent_open_maybe();
|
||||
|
||||
if (arg_action == ACTION_SYSTEMCTL) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@ -9,7 +10,9 @@
|
|||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
#include "virt.h"
|
||||
|
||||
static void test_tmpdir(const char *id, const char *A, const char *B) {
|
||||
_cleanup_free_ char *a, *b;
|
||||
|
@ -48,14 +51,16 @@ static void test_tmpdir(const char *id, const char *A, const char *B) {
|
|||
assert_se(rmdir(b) >= 0);
|
||||
}
|
||||
|
||||
static int test_netns(void) {
|
||||
static void test_netns(void) {
|
||||
_cleanup_close_pair_ int s[2] = { -1, -1 };
|
||||
pid_t pid1, pid2, pid3;
|
||||
int r, n = 0;
|
||||
siginfo_t si;
|
||||
|
||||
if (geteuid() > 0)
|
||||
return log_tests_skipped("not root");
|
||||
if (geteuid() > 0) {
|
||||
(void) log_tests_skipped("not root");
|
||||
return;
|
||||
}
|
||||
|
||||
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, s) >= 0);
|
||||
|
||||
|
@ -102,7 +107,62 @@ static int test_netns(void) {
|
|||
n += si.si_status;
|
||||
|
||||
assert_se(n == 1);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void test_protect_kernel_logs(void) {
|
||||
int r;
|
||||
pid_t pid;
|
||||
static const NamespaceInfo ns_info = {
|
||||
.protect_kernel_logs = true,
|
||||
};
|
||||
|
||||
if (geteuid() > 0) {
|
||||
(void) log_tests_skipped("not root");
|
||||
return;
|
||||
}
|
||||
|
||||
/* In a container we likely don't have access to /dev/kmsg */
|
||||
if (detect_container() > 0) {
|
||||
(void) log_tests_skipped("in container");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC);
|
||||
assert_se(fd > 0);
|
||||
|
||||
r = setup_namespace(NULL,
|
||||
NULL,
|
||||
&ns_info,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL,
|
||||
NULL,
|
||||
PROTECT_HOME_NO,
|
||||
PROTECT_SYSTEM_NO,
|
||||
0,
|
||||
0,
|
||||
NULL);
|
||||
assert_se(r == 0);
|
||||
|
||||
assert_se(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) >= 0);
|
||||
assert_se(open("/dev/kmsg", O_RDONLY | O_CLOEXEC) < 0);
|
||||
assert_se(errno == EACCES);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
@ -133,5 +193,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
test_tmpdir("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz);
|
||||
|
||||
return test_netns();
|
||||
test_netns();
|
||||
test_protect_kernel_logs();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -323,6 +323,48 @@ static void test_protect_sysctl(void) {
|
|||
assert_se(wait_for_terminate_and_check("sysctlseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void test_protect_syslog(void) {
|
||||
pid_t pid;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (geteuid() != 0) {
|
||||
log_notice("Not root, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* in containers syslog() is likely missing anyway */
|
||||
if (detect_container() > 0) {
|
||||
log_notice("Testing in container, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
#if defined __NR_syslog && __NR_syslog > 0
|
||||
assert_se(syscall(__NR_syslog, -1, NULL, 0) < 0);
|
||||
assert_se(errno == EINVAL);
|
||||
#endif
|
||||
|
||||
assert_se(seccomp_protect_syslog() >= 0);
|
||||
|
||||
#if defined __NR_syslog && __NR_syslog > 0
|
||||
assert_se(syscall(__NR_syslog, 0, 0, 0) < 0);
|
||||
assert_se(errno == EPERM);
|
||||
#endif
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("syslogseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void test_restrict_address_families(void) {
|
||||
pid_t pid;
|
||||
|
||||
|
@ -983,6 +1025,7 @@ int main(int argc, char *argv[]) {
|
|||
test_filter_sets_ordered();
|
||||
test_restrict_namespace();
|
||||
test_protect_sysctl();
|
||||
test_protect_syslog();
|
||||
test_restrict_address_families();
|
||||
test_restrict_realtime();
|
||||
test_memory_deny_write_execute_mmap();
|
||||
|
|
|
@ -109,6 +109,8 @@ test_data_files = '''
|
|||
test-execute/exec-privatetmp-no.service
|
||||
test-execute/exec-privatetmp-yes.service
|
||||
test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service
|
||||
test-execute/exec-protectkernellogs-yes-capabilities.service
|
||||
test-execute/exec-protectkernellogs-no-capabilities.service
|
||||
test-execute/exec-protectkernelmodules-no-capabilities.service
|
||||
test-execute/exec-protectkernelmodules-yes-capabilities.service
|
||||
test-execute/exec-protectkernelmodules-yes-mount-propagation.service
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
[Unit]
|
||||
Description=Test CAP_SYSLOG for ProtectKernelLogs=no
|
||||
|
||||
[Service]
|
||||
ProtectKernelLogs=no
|
||||
ExecStart=/bin/sh -x -c 'capsh --print | grep cap_syslog'
|
||||
Type=oneshot
|
|
@ -0,0 +1,7 @@
|
|||
[Unit]
|
||||
Description=Test CAP_SYSLOG for ProtectKernelLogs=yes
|
||||
|
||||
[Service]
|
||||
ProtectKernelLogs=yes
|
||||
ExecStart=/bin/sh -x -c '! capsh --print | grep cap_syslog'
|
||||
Type=oneshot
|
|
@ -32,6 +32,7 @@ ProtectHome=yes
|
|||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
RestrictNamespaces=yes
|
||||
|
|
|
@ -27,6 +27,7 @@ ProtectControlGroups=yes
|
|||
ProtectHome=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
|
|
|
@ -24,6 +24,7 @@ ProtectHome=yes
|
|||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
|
|
|
@ -26,6 +26,7 @@ ProtectHome=yes
|
|||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
RestrictNamespaces=yes
|
||||
|
|
|
@ -24,6 +24,7 @@ ProtectHome=yes
|
|||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
|
|
|
@ -28,6 +28,7 @@ ProtectHome=yes
|
|||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
|
|
|
@ -41,6 +41,7 @@ ProtectControlGroups=yes
|
|||
ProtectHome=yes
|
||||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc /run
|
||||
Restart=always
|
||||
|
|
|
@ -24,6 +24,7 @@ LockPersonality=yes
|
|||
MemoryDenyWriteExecute=yes
|
||||
NoNewPrivileges=yes
|
||||
ProtectHostname=yes
|
||||
ProtectKernelLogs=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
|
||||
RestrictRealtime=yes
|
||||
SystemCallArchitectures=native
|
||||
|
|
|
@ -29,6 +29,7 @@ NoNewPrivileges=yes
|
|||
ProtectControlGroups=yes
|
||||
ProtectHome=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
Restart=on-failure
|
||||
RestartSec=0
|
||||
|
|
|
@ -18,6 +18,7 @@ BusName=org.freedesktop.portable1
|
|||
CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD
|
||||
MemoryDenyWriteExecute=yes
|
||||
ProtectHostname=yes
|
||||
ProtectKernelLogs=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
|
||||
SystemCallFilter=@system-service @mount
|
||||
|
|
|
@ -32,6 +32,7 @@ ProtectControlGroups=yes
|
|||
ProtectHome=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
|
|
|
@ -27,6 +27,7 @@ ProtectHome=yes
|
|||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
|
|
|
@ -32,6 +32,7 @@ ProtectHome=yes
|
|||
ProtectHostname=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
|
|
Loading…
Reference in New Issue