1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-06-03 09:07:45 +03:00

core: add RestrictFileSystems= fragment parser

It takes an allow or deny list of filesystems services should have
access to.
This commit is contained in:
Iago López Galeiras 2021-02-11 16:59:30 +01:00 committed by Iago Lopez Galeiras
parent b1994387d3
commit e59ccd035c
10 changed files with 145 additions and 1 deletions

View File

@ -325,3 +325,57 @@ void lsm_bpf_destroy(struct restrict_fs_bpf *prog) {
return;
}
#endif
int lsm_bpf_parse_filesystem(
const char *name,
Set **filesystems,
FilesystemParseFlags flags,
const char *unit,
const char *filename,
unsigned line) {
int r;
assert(name);
assert(filesystems);
if (name[0] == '@') {
const FilesystemSet *set;
const char *i;
set = filesystem_set_find(name);
if (!set) {
log_syntax(unit, flags & FILESYSTEM_PARSE_LOG ? LOG_WARNING : LOG_DEBUG, filename, line, 0,
"Unknown filesystem group, ignoring: %s", name);
return 0;
}
NULSTR_FOREACH(i, set->value) {
/* Call ourselves again, for the group to parse. Note that we downgrade logging here (i.e. take
* away the FILESYSTEM_PARSE_LOG flag) since any issues in the group table are our own problem,
* not a problem in user configuration data and we shouldn't pretend otherwise by complaining
* about them. */
r = lsm_bpf_parse_filesystem(i, filesystems, flags &~ FILESYSTEM_PARSE_LOG, unit, filename, line);
if (r < 0)
return r;
}
} else {
/* If we previously wanted to forbid access to a filesystem and now
* we want to allow it, then remove it from the list. */
if (!(flags & FILESYSTEM_PARSE_INVERT) == !!(flags & FILESYSTEM_PARSE_ALLOW_LIST)) {
r = set_put_strdup(filesystems, name);
if (r < 0)
switch (r) {
case -ENOMEM:
return flags & FILESYSTEM_PARSE_LOG ? log_oom() : -ENOMEM;
case -EEXIST:
/* Alredy in set, ignore */
break;
default:
return r;
}
} else
free(set_remove(*filesystems, name));
}
return 0;
}

View File

@ -3,6 +3,12 @@
#include "hashmap.h"
typedef enum FilesystemParseFlags {
FILESYSTEM_PARSE_INVERT = 1 << 0,
FILESYSTEM_PARSE_ALLOW_LIST = 1 << 1,
FILESYSTEM_PARSE_LOG = 1 << 2,
} FilesystemParseFlags;
typedef struct Unit Unit;
typedef struct Manager Manager;
@ -14,3 +20,9 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo
int lsm_bpf_cleanup(const Unit *u);
int lsm_bpf_map_restrict_fs_fd(Unit *u);
void lsm_bpf_destroy(struct restrict_fs_bpf *prog);
int lsm_bpf_parse_filesystem(const char *name,
Set **filesystems,
FilesystemParseFlags flags,
const char *unit,
const char *filename,
unsigned line);

View File

@ -81,6 +81,7 @@
{{type}}.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
{{type}}.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
{% endif %}
{{type}}.RestrictFileSystems, config_parse_restrict_filesystems, 0, offsetof({{type}}, exec_context)
{{type}}.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof({{type}}, exec_context.rlimit)
{{type}}.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof({{type}}, exec_context.rlimit)
{{type}}.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof({{type}}, exec_context.rlimit)

View File

@ -19,6 +19,7 @@
#include "all-units.h"
#include "alloc-util.h"
#include "bpf-firewall.h"
#include "bpf-lsm.h"
#include "bpf-program.h"
#include "bpf-socket-bind.h"
#include "bus-error.h"
@ -3597,6 +3598,76 @@ int config_parse_restrict_namespaces(
}
#endif
int config_parse_restrict_filesystems(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
bool invert = false;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
/* Empty assignment resets the list */
c->restrict_filesystems = set_free(c->restrict_filesystems);
c->restrict_filesystems_allow_list = false;
return 0;
}
if (rvalue[0] == '~') {
invert = true;
rvalue++;
}
if (!c->restrict_filesystems) {
if (invert)
/* Allow everything but the ones listed */
c->restrict_filesystems_allow_list = false;
else
/* Allow nothing but the ones listed */
c->restrict_filesystems_allow_list = true;
}
for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
break;
}
r = lsm_bpf_parse_filesystem(
word,
&c->restrict_filesystems,
FILESYSTEM_PARSE_LOG|
(invert ? FILESYSTEM_PARSE_INVERT : 0)|
(c->restrict_filesystems_allow_list ? FILESYSTEM_PARSE_ALLOW_LIST : 0),
unit, filename, line);
if (r < 0)
return r;
}
return 0;
}
int config_parse_unit_slice(
const char *unit,
const char *filename,
@ -6030,6 +6101,7 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_address_families, "FAMILIES" },
{ config_parse_restrict_namespaces, "NAMESPACES" },
#endif
{ config_parse_restrict_filesystems, "FILESYSTEMS" },
{ config_parse_cpu_shares, "SHARES" },
{ config_parse_cg_weight, "WEIGHT" },
{ config_parse_memory_limit, "LIMIT" },

View File

@ -113,6 +113,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_sec_fix_0);
CONFIG_PARSER_PROTOTYPE(config_parse_user_group_compat);
CONFIG_PARSER_PROTOTYPE(config_parse_user_group_strv_compat);
CONFIG_PARSER_PROTOTYPE(config_parse_restrict_namespaces);
CONFIG_PARSER_PROTOTYPE(config_parse_restrict_filesystems);
CONFIG_PARSER_PROTOTYPE(config_parse_bind_paths);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_keyring_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_protect_proc);

View File

@ -1023,7 +1023,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
return 1;
} else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies", "RestrictNetworkInterfaces")) {
} else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies", "RestrictNetworkInterfaces", "RestrictFileSystems")) {
_cleanup_strv_free_ char **l = NULL;
int allow_list;

View File

@ -144,6 +144,7 @@ ReadWritePaths=
RemoveIPC=
RestartKillSignal=
RestrictAddressFamilies=
RestrictFileSystems=
RestrictNamespaces=
RestrictNetworkInterfaces=
RestrictRealtime=

View File

@ -275,6 +275,7 @@ RestartKillSignal=
RestartPreventExitStatus=
RestartSec=
RestrictAddressFamilies=
RestrictFileSystems=
RestrictNamespaces=
RestrictNetworkInterfaces=
RestrictRealtime=

View File

@ -180,6 +180,7 @@ RemoveIPC=
RemoveOnStop=
RestartKillSignal=
RestrictAddressFamilies=
RestrictFileSystems=
RestrictNamespaces=
RestrictNetworkInterfaces=
RestrictRealtime=

View File

@ -141,6 +141,7 @@ ReadWritePaths=
RemoveIPC=
RestartKillSignal=
RestrictAddressFamilies=
RestrictFileSystems=
RestrictNamespaces=
RestrictNetworkInterfaces=
RestrictRealtime=