+ r = config_parse_unit_strv_printf(unit, filename, line, section, lvalue, ltype,
+ rvalue, data, userdata);
+ if (r < 0)
+ return r;
+
+ for (a = b = u->documentation; a && *a; a++) {
+
+ if (is_valid_documentation_url(*a))
+ *(b++) = *a;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Invalid URL, ignoring: %s", *a);
+ free(*a);
+ }
+ }
+ *b = NULL;
+
+ return r;
+}
+
+static void syscall_set(uint32_t *p, int nr) {
+ nr = SYSCALL_TO_INDEX(nr);
+ p[nr >> 4] |= 1 << (nr & 31);
+}
+
+static void syscall_unset(uint32_t *p, int nr) {
+ nr = SYSCALL_TO_INDEX(nr);
+ p[nr >> 4] &= ~(1 << (nr & 31));
+}
+
+int config_parse_syscall_filter(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ ExecContext *c = data;
+ Unit *u = userdata;
+ bool invert = false;
+ char *w;
+ size_t l;
+ char *state;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(u);
+
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ free(c->syscall_filter);
+ c->syscall_filter = NULL;
+ return 0;
+ }
+
+ if (rvalue[0] == '~') {
+ invert = true;
+ rvalue++;
+ }
+
+ if (!c->syscall_filter) {
+ size_t n;
+
+ n = (syscall_max() + 31) >> 4;
+ c->syscall_filter = new(uint32_t, n);
+ if (!c->syscall_filter)
+ return log_oom();
+
+ memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
+
+ /* Add these by default */
+ syscall_set(c->syscall_filter, __NR_execve);
+ syscall_set(c->syscall_filter, __NR_rt_sigreturn);
+#ifdef __NR_sigreturn
+ syscall_set(c->syscall_filter, __NR_sigreturn);
+#endif
+ syscall_set(c->syscall_filter, __NR_exit_group);
+ syscall_set(c->syscall_filter, __NR_exit);
+ }
+
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ int id;
+ _cleanup_free_ char *t = NULL;
+
+ t = strndup(w, l);
+ if (!t)
+ return log_oom();
+
+ id = syscall_from_name(t);
+ if (id < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Failed to parse syscall, ignoring: %s", t);
+ continue;
+ }
+
+ if (invert)
+ syscall_unset(c->syscall_filter, id);
+ else
+ syscall_set(c->syscall_filter, id);
+ }
+
+ c->no_new_privileges = true;