summaryrefslogtreecommitdiff
path: root/src/core/load-fragment.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-02-25 20:37:03 +0100
committerLennart Poettering <lennart@poettering.net>2014-02-26 02:19:28 +0100
commit4298d0b5128326621c8f537107c4c8b459490721 (patch)
tree38ed9f6806b45d153f39ea9da61eae5d34530523 /src/core/load-fragment.c
parent9875fd7875d433eea5c6e3319916e1be18722086 (diff)
core: add new RestrictAddressFamilies= switch
This new unit settings allows restricting which address families are available to processes. This is an effective way to minimize the attack surface of services, by turning off entire network stacks for them. This is based on seccomp, and does not work on x86-32, since seccomp cannot filter socketcall() syscalls on that platform.
Diffstat (limited to 'src/core/load-fragment.c')
-rw-r--r--src/core/load-fragment.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 82aed1eb92..478d22c4b5 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -56,6 +56,7 @@
#include "bus-util.h"
#include "bus-error.h"
#include "errno-list.h"
+#include "af-list.h"
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
@@ -2216,6 +2217,81 @@ int config_parse_syscall_errno(
c->syscall_errno = e;
return 0;
}
+
+int config_parse_address_families(
+ 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;
+ Unit *u = userdata;
+ bool invert = false;
+ char *w, *state;
+ size_t l;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(u);
+
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ set_free(c->address_families);
+ c->address_families = NULL;
+ c->address_families_whitelist = false;
+ return 0;
+ }
+
+ if (rvalue[0] == '~') {
+ invert = true;
+ rvalue++;
+ }
+
+ if (!c->address_families) {
+ c->address_families = set_new(trivial_hash_func, trivial_compare_func);
+ if (!c->address_families)
+ return log_oom();
+
+ c->address_families_whitelist = !invert;
+ }
+
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ _cleanup_free_ char *t = NULL;
+ int af;
+
+ t = strndup(w, l);
+ if (!t)
+ return log_oom();
+
+ af = af_from_name(t);
+ if (af <= 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse address family, ignoring: %s", t);
+ continue;
+ }
+
+ /* If we previously wanted to forbid an address family and now
+ * we want to allow it, then remove it from the list
+ */
+ if (!invert == c->address_families_whitelist) {
+ r = set_put(c->address_families, INT_TO_PTR(af));
+ if (r == -EEXIST)
+ continue;
+ if (r < 0)
+ return log_oom();
+ } else
+ set_remove(c->address_families, INT_TO_PTR(af));
+ }
+
+ return 0;
+}
#endif
int config_parse_unit_slice(
@@ -3024,6 +3100,7 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_syscall_filter, "SYSCALLS" },
{ config_parse_syscall_archs, "ARCHS" },
{ config_parse_syscall_errno, "ERRNO" },
+ { config_parse_address_families, "FAMILIES" },
#endif
{ config_parse_cpu_shares, "SHARES" },
{ config_parse_memory_limit, "LIMIT" },
@@ -3039,6 +3116,7 @@ void unit_dump_config_items(FILE *f) {
#endif
{ config_parse_job_mode, "MODE" },
{ config_parse_job_mode_isolate, "BOOLEAN" },
+ { config_parse_personality, "PERSONALITY" },
};
const char *prev = NULL;