This file is part of systemd.
Copyright 2010 Lennart Poettering
+ Copyright 2012 Holger Hans Peter Freyther
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
#include "securebits.h"
#include "missing.h"
#include "unit-name.h"
+#include "unit-printf.h"
#include "bus-errors.h"
#include "utf8.h"
#include "path-util.h"
+#include "syscall-list.h"
#ifndef HAVE_SYSV_COMPAT
int config_parse_warn_compat(
k = unit_full_printf(u, rvalue);
if (!k)
- return -ENOMEM;
+ return log_oom();
r = config_parse_path(filename, line, section, lvalue, ltype, k, data, userdata);
free(k);
s = SOCKET(data);
- if ((b = socket_address_bind_ipv6_only_from_string(rvalue)) < 0) {
+ b = socket_address_bind_ipv6_only_from_string(rvalue);
+ if (b < 0) {
int r;
- if ((r = parse_boolean(rvalue)) < 0) {
+ r = parse_boolean(rvalue);
+ if (r < 0) {
log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue);
return 0;
}
e += ltype;
for (;;) {
+ int i;
char *w;
size_t l;
char *state;
if (rvalue[0] == 0)
break;
- if (rvalue[0] == '-') {
- ignore = true;
- rvalue ++;
- }
+ for (i = 0; i < 2; i++) {
+ if (rvalue[0] == '-' && !ignore) {
+ ignore = true;
+ rvalue ++;
+ }
- if (rvalue[0] == '@') {
- honour_argv0 = true;
- rvalue ++;
+ if (rvalue[0] == '@' && !honour_argv0) {
+ honour_argv0 = true;
+ rvalue ++;
+ }
}
if (*rvalue != '/') {
- log_error("[%s:%u] Invalid executable path in command line, ignoring: %s", filename, line, rvalue);
+ log_error("[%s:%u] Executable path is not absolute, ignoring: %s",
+ filename, line, rvalue);
return 0;
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (strncmp(w, ";", MAX(l, 1U)) == 0)
break;
+ else if (strncmp(w, "\\;", MAX(l, 1U)) == 0)
+ w ++;
if (honour_argv0 && w == rvalue) {
assert(!path);
assert(rvalue);
assert(data);
- if ((x = ioprio_class_from_string(rvalue)) < 0) {
+ x = ioprio_class_from_string(rvalue);
+ if (x < 0) {
log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue);
return 0;
}
assert(rvalue);
assert(data);
- if ((x = sched_policy_from_string(rvalue)) < 0) {
+ x = sched_policy_from_string(rvalue);
+ if (x < 0) {
log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue);
return 0;
}
c->cpu_sched_policy = x;
+ /* Moving to or from real-time policy? We need to adjust the priority */
+ c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
c->cpu_sched_set = true;
return 0;
void *userdata) {
ExecContext *c = data;
- int i;
+ int i, min, max;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- /* On Linux RR/FIFO have the same range */
- if (safe_atoi(rvalue, &i) < 0 || i < sched_get_priority_min(SCHED_RR) || i > sched_get_priority_max(SCHED_RR)) {
+ if (safe_atoi(rvalue, &i) < 0) {
log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue);
return 0;
}
+
+ /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
+ min = sched_get_priority_min(c->cpu_sched_policy);
+ max = sched_get_priority_max(c->cpu_sched_policy);
+
+ if (i < min || i > max) {
+ log_error("[%s:%u] CPU scheduling priority is out of range, ignoring: %s", filename, line, rvalue);
+ return 0;
+ }
+
c->cpu_sched_priority = i;
c->cpu_sched_set = true;
if (r < 0) {
log_error("[%s:%u] Failed to parse capability bounding set, ignoring: %s", filename, line, rvalue);
- return 0;
+ continue;
}
sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
Path *p = data;
PathSpec *s;
PathType b;
+ char *k;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if ((b = path_type_from_string(lvalue)) < 0) {
+ b = path_type_from_string(lvalue);
+ if (b < 0) {
log_error("[%s:%u] Failed to parse path type, ignoring: %s", filename, line, lvalue);
return 0;
}
- if (!path_is_absolute(rvalue)) {
- log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, rvalue);
+ k = unit_full_printf(UNIT(p), rvalue);
+ if (!k)
+ return log_oom();
+
+ if (!path_is_absolute(k)) {
+ log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, k);
+ free(k);
return 0;
}
- if (!(s = new0(PathSpec, 1)))
- return -ENOMEM;
-
- if (!(s->path = strdup(rvalue))) {
- free(s);
- return -ENOMEM;
+ s = new0(PathSpec, 1);
+ if (!s) {
+ free(k);
+ return log_oom();
}
- path_kill_slashes(s->path);
-
+ s->path = path_kill_slashes(k);
s->type = b;
s->inotify_fd = -1;
r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
- if (!r)
- s->timeout_defined = true;
+ if (r)
+ return r;
- return r;
+ if (streq(lvalue, "TimeoutSec")) {
+ s->start_timeout_defined = true;
+ s->timeout_stop_usec = s->timeout_start_usec;
+ } else if (streq(lvalue, "TimeoutStartSec"))
+ s->start_timeout_defined = true;
+
+ return 0;
}
int config_parse_unit_env_file(
assert(rvalue);
assert(data);
- if ((x = ip_tos_from_string(rvalue)) < 0)
- if (safe_atoi(rvalue, &x) < 0) {
- log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
+ x = ip_tos_from_string(rvalue);
+ if (x < 0) {
+ log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
+ return 0;
+ }
*ip_tos = x;
return 0;
Unit *u = data;
bool trigger, negate;
Condition *c;
+ _cleanup_free_ char *p = NULL;
assert(filename);
assert(lvalue);
if (negate)
rvalue++;
- if (!path_is_absolute(rvalue)) {
- log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, rvalue);
+ p = unit_full_printf(u, rvalue);
+ if (!p)
+ return -ENOMEM;
+
+ if (!path_is_absolute(p)) {
+ log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, p);
return 0;
}
- c = condition_new(cond, rvalue, trigger, negate);
+ c = condition_new(cond, p, trigger, negate);
if (!c)
return -ENOMEM;
Unit *u = data;
bool trigger, negate;
Condition *c;
+ _cleanup_free_ char *s = NULL;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if ((trigger = rvalue[0] == '|'))
+ trigger = rvalue[0] == '|';
+ if (trigger)
rvalue++;
- if ((negate = rvalue[0] == '!'))
+ negate = rvalue[0] == '!';
+ if (negate)
rvalue++;
- if (!(c = condition_new(cond, rvalue, trigger, negate)))
+ s = unit_full_printf(u, rvalue);
+ if (!s)
return -ENOMEM;
+ c = condition_new(cond, s, trigger, negate);
+ if (!c)
+ return log_oom();
+
LIST_PREPEND(Condition, conditions, u->conditions, c);
return 0;
}
}
if (parse_bytes(l[1], &bytes) < 0 || bytes <= 0) {
- log_error("[%s:%u] Failed to parse block IO bandwith value, ignoring: %s", filename, line, rvalue);
+ log_error("[%s:%u] Failed to parse block IO bandwidth value, ignoring: %s", filename, line, rvalue);
strv_free(l);
return 0;
}
return r;
}
+static void syscall_set(uint32_t *p, int nr) {
+ p[nr >> 4] |= 1 << (nr & 31);
+}
+
+static void syscall_unset(uint32_t *p, int nr) {
+ p[nr >> 4] &= ~(1 << (nr & 31));
+}
+
+int config_parse_syscall_filter(
+ 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 (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 -ENOMEM;
+
+ 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;
+ char *t;
+
+ t = strndup(w, l);
+ if (!t)
+ return -ENOMEM;
+
+ id = syscall_from_name(t);
+ free(t);
+
+ if (id < 0) {
+ log_error("[%s:%u] Failed to parse syscall, ignoring: %s", filename, line, rvalue);
+ continue;
+ }
+
+ if (invert)
+ syscall_unset(c->syscall_filter, id);
+ else
+ syscall_set(c->syscall_filter, id);
+ }
+
+ c->no_new_privileges = true;
+
+ return 0;
+}
+
#define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
goto finish;
}
- zero(st);
if (fstat(fileno(f), &st) < 0) {
r = -errno;
goto finish;