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:
parent
b1994387d3
commit
e59ccd035c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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" },
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -144,6 +144,7 @@ ReadWritePaths=
|
||||
RemoveIPC=
|
||||
RestartKillSignal=
|
||||
RestrictAddressFamilies=
|
||||
RestrictFileSystems=
|
||||
RestrictNamespaces=
|
||||
RestrictNetworkInterfaces=
|
||||
RestrictRealtime=
|
||||
|
@ -275,6 +275,7 @@ RestartKillSignal=
|
||||
RestartPreventExitStatus=
|
||||
RestartSec=
|
||||
RestrictAddressFamilies=
|
||||
RestrictFileSystems=
|
||||
RestrictNamespaces=
|
||||
RestrictNetworkInterfaces=
|
||||
RestrictRealtime=
|
||||
|
@ -180,6 +180,7 @@ RemoveIPC=
|
||||
RemoveOnStop=
|
||||
RestartKillSignal=
|
||||
RestrictAddressFamilies=
|
||||
RestrictFileSystems=
|
||||
RestrictNamespaces=
|
||||
RestrictNetworkInterfaces=
|
||||
RestrictRealtime=
|
||||
|
@ -141,6 +141,7 @@ ReadWritePaths=
|
||||
RemoveIPC=
|
||||
RestartKillSignal=
|
||||
RestrictAddressFamilies=
|
||||
RestrictFileSystems=
|
||||
RestrictNamespaces=
|
||||
RestrictNetworkInterfaces=
|
||||
RestrictRealtime=
|
||||
|
Loading…
x
Reference in New Issue
Block a user