Merge pull request #6497 from yuwata/bus-prop

core: add missing properties in bus_exec_context_set_transient_property()
This commit is contained in:
Lennart Poettering
2017-08-09 17:06:26 +02:00
committed by GitHub
14 changed files with 1024 additions and 92 deletions
+65
View File
@@ -20,7 +20,10 @@
#include <errno.h>
#include <string.h>
#include "alloc-util.h"
#include "capability-util.h"
#include "cap-list.h"
#include "extract-word.h"
#include "macro.h"
#include "missing.h"
#include "parse-util.h"
@@ -64,3 +67,65 @@ int capability_from_name(const char *name) {
int capability_list_length(void) {
return (int) ELEMENTSOF(capability_names);
}
int capability_set_to_string_alloc(uint64_t set, char **s) {
_cleanup_free_ char *str = NULL;
unsigned long i;
size_t allocated = 0, n = 0;
assert(s);
for (i = 0; i < cap_last_cap(); i++)
if (set & (UINT64_C(1) << i)) {
const char *p;
size_t add;
p = capability_to_name(i);
if (!p)
return -EINVAL;
add = strlen(p);
if (!GREEDY_REALLOC0(str, allocated, n + add + 2))
return -ENOMEM;
strcpy(mempcpy(str + n, p, add), " ");
n += add + 1;
}
if (n != 0)
str[n - 1] = '\0';
*s = str;
str = NULL;
return 0;
}
int capability_set_from_string(const char *s, uint64_t *set) {
uint64_t val = 0;
const char *p;
assert(set);
for (p = s;;) {
_cleanup_free_ char *word = NULL;
int r;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == -ENOMEM)
return r;
if (r <= 0)
break;
r = capability_from_name(word);
if (r < 0)
continue;
val |= ((uint64_t) UINT64_C(1)) << (uint64_t) r;
}
*set = val;
return 0;
}
+3
View File
@@ -22,3 +22,6 @@
const char *capability_to_name(int id);
int capability_from_name(const char *name);
int capability_list_length(void);
int capability_set_to_string_alloc(uint64_t set, char **s);
int capability_set_from_string(const char *s, uint64_t *set);
+46
View File
@@ -112,3 +112,49 @@ int parse_cpu_set_and_warn(
return (int) ncpus;
}
int parse_cpu_set(
const char *rvalue,
cpu_set_t **cpu_set) {
_cleanup_cpu_free_ cpu_set_t *c = NULL;
unsigned ncpus = 0;
assert(rvalue);
for (;;) {
_cleanup_free_ char *word = NULL;
unsigned cpu, cpu_lower, cpu_upper;
int r;
r = extract_first_word(&rvalue, &word, WHITESPACE ",", EXTRACT_QUOTES);
if (r == -ENOMEM)
return r;
if (r <= 0)
break;
if (!c) {
c = cpu_set_malloc(&ncpus);
if (!c)
return -ENOMEM;
}
r = parse_range(word, &cpu_lower, &cpu_upper);
if (r < 0)
return r;
if (cpu_lower >= ncpus || cpu_upper >= ncpus)
return -EINVAL;
if (cpu_lower <= cpu_upper)
for (cpu = cpu_lower; cpu <= cpu_upper; cpu++)
CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
}
/* On success, sets *cpu_set and returns ncpus for the system. */
if (c) {
*cpu_set = c;
c = NULL;
}
return (int) ncpus;
}
+1
View File
@@ -30,3 +30,4 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE);
cpu_set_t* cpu_set_malloc(unsigned *ncpus);
int parse_cpu_set_and_warn(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue);
int parse_cpu_set(const char *rvalue, cpu_set_t **cpu_set);
+2
View File
@@ -139,6 +139,8 @@ basic_sources_plain = files('''
rm-rf.c
rm-rf.h
securebits.h
securebits-util.c
securebits-util.h
selinux-util.c
selinux-util.h
set.h
+9
View File
@@ -20,6 +20,7 @@
***/
#include <alloca.h>
#include <sched.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
@@ -110,6 +111,14 @@ static inline bool nice_is_valid(int n) {
return n >= PRIO_MIN && n < PRIO_MAX;
}
static inline bool sched_policy_is_valid(int i) {
return IN_SET(i, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR);
}
static inline bool sched_priority_is_valid(int i) {
return i >= 0 && i <= sched_get_priority_max(SCHED_RR);
}
static inline bool ioprio_class_is_valid(int i) {
return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE);
}
+84
View File
@@ -0,0 +1,84 @@
/***
This file is part of systemd.
Copyright 2017 Yu Watanabe
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
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include "alloc-util.h"
#include "extract-word.h"
#include "securebits.h"
#include "securebits-util.h"
#include "string-util.h"
int secure_bits_to_string_alloc(int i, char **s) {
_cleanup_free_ char *str = NULL;
size_t len;
int r;
assert(s);
r = asprintf(&str, "%s%s%s%s%s%s",
(i & (1 << SECURE_KEEP_CAPS)) ? "keep-caps " : "",
(i & (1 << SECURE_KEEP_CAPS_LOCKED)) ? "keep-caps-locked " : "",
(i & (1 << SECURE_NO_SETUID_FIXUP)) ? "no-setuid-fixup " : "",
(i & (1 << SECURE_NO_SETUID_FIXUP_LOCKED)) ? "no-setuid-fixup-locked " : "",
(i & (1 << SECURE_NOROOT)) ? "noroot " : "",
(i & (1 << SECURE_NOROOT_LOCKED)) ? "noroot-locked " : "");
if (r < 0)
return -ENOMEM;
len = strlen(str);
if (len != 0)
str[len - 1] = '\0';
*s = str;
str = NULL;
return 0;
}
int secure_bits_from_string(const char *s) {
int secure_bits = 0;
const char *p;
int r;
for (p = s;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == -ENOMEM)
return r;
if (r <= 0)
break;
if (streq(word, "keep-caps"))
secure_bits |= 1 << SECURE_KEEP_CAPS;
else if (streq(word, "keep-caps-locked"))
secure_bits |= 1 << SECURE_KEEP_CAPS_LOCKED;
else if (streq(word, "no-setuid-fixup"))
secure_bits |= 1 << SECURE_NO_SETUID_FIXUP;
else if (streq(word, "no-setuid-fixup-locked"))
secure_bits |= 1 << SECURE_NO_SETUID_FIXUP_LOCKED;
else if (streq(word, "noroot"))
secure_bits |= 1 << SECURE_NOROOT;
else if (streq(word, "noroot-locked"))
secure_bits |= 1 << SECURE_NOROOT_LOCKED;
}
return secure_bits;
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
/***
This file is part of systemd.
Copyright 2017 Yu Watanabe
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
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "securebits.h"
int secure_bits_to_string_alloc(int i, char **s);
int secure_bits_from_string(const char *s);
static inline bool secure_bits_is_valid(int i) {
return ((SECURE_ALL_BITS | SECURE_ALL_LOCKS) & i) == i;
}
+450 -9
View File
@@ -27,8 +27,10 @@
#include "alloc-util.h"
#include "bus-util.h"
#include "capability-util.h"
#include "cap-list.h"
#include "dbus-execute.h"
#include "env-util.h"
#include "errno-list.h"
#include "execute.h"
#include "fd-util.h"
#include "fileio.h"
@@ -43,6 +45,7 @@
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "securebits-util.h"
#include "strv.h"
#include "syslog-util.h"
#include "unit-printf.h"
@@ -1028,6 +1031,41 @@ int bus_exec_context_set_transient_property(
}
return 1;
} else if (streq(name, "SupplementaryGroups")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
STRV_FOREACH(p, l) {
if (!isempty(*p) && !valid_user_group_name_or_id(*p))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
}
if (mode != UNIT_CHECK) {
if (strv_length(l) == 0) {
c->supplementary_groups = strv_free(c->supplementary_groups);
unit_write_drop_in_private_format(u, mode, name, "%s=", name);
} else {
_cleanup_free_ char *joined = NULL;
r = strv_extend_strv(&c->supplementary_groups, l, true);
if (r < 0)
return -ENOMEM;
joined = strv_join(c->supplementary_groups, " ");
if (!joined)
return -ENOMEM;
unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
}
}
return 1;
} else if (streq(name, "SyslogIdentifier")) {
const char *id;
@@ -1077,6 +1115,361 @@ int bus_exec_context_set_transient_property(
unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i", facility);
}
return 1;
} else if (streq(name, "SecureBits")) {
int n;
r = sd_bus_message_read(message, "i", &n);
if (r < 0)
return r;
if (!secure_bits_is_valid(n))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid secure bits");
if (mode != UNIT_CHECK) {
_cleanup_free_ char *str = NULL;
c->secure_bits = n;
r = secure_bits_to_string_alloc(n, &str);
if (r < 0)
return r;
unit_write_drop_in_private_format(u, mode, name, "SecureBits=%s", str);
}
return 1;
} else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
uint64_t n;
r = sd_bus_message_read(message, "t", &n);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
_cleanup_free_ char *str = NULL;
if (streq(name, "CapabilityBoundingSet"))
c->capability_bounding_set = n;
else /* "AmbientCapabilities" */
c->capability_ambient_set = n;
r = capability_set_to_string_alloc(n, &str);
if (r < 0)
return r;
unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
}
return 1;
} else if (streq(name, "Personality")) {
const char *s;
unsigned long p;
r = sd_bus_message_read(message, "s", &s);
if (r < 0)
return r;
p = personality_from_string(s);
if (p == PERSONALITY_INVALID)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid personality");
if (mode != UNIT_CHECK) {
_cleanup_free_ char *str = NULL;
c->personality = p;
unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
}
return 1;
#ifdef HAVE_SECCOMP
} else if (streq(name, "SystemCallFilter")) {
int whitelist;
_cleanup_strv_free_ char **l;
r = sd_bus_message_enter_container(message, 'r', "bas");
if (r < 0)
return r;
r = sd_bus_message_read(message, "b", &whitelist);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
_cleanup_free_ char *joined = NULL;
if (strv_length(l) == 0) {
c->syscall_whitelist = false;
c->syscall_filter = set_free(c->syscall_filter);
} else {
char **s;
c->syscall_whitelist = whitelist;
r = set_ensure_allocated(&c->syscall_filter, NULL);
if (r < 0)
return r;
STRV_FOREACH(s, l) {
if (**s == '@') {
const SyscallFilterSet *set;
const char *i;
set = syscall_filter_set_find(*s);
if (!set)
return -EINVAL;
NULSTR_FOREACH(i, set->value) {
int id;
id = seccomp_syscall_resolve_name(i);
if (id == __NR_SCMP_ERROR)
return -EINVAL;
r = set_put(c->address_families, INT_TO_PTR(id + 1));
if (r < 0)
return r;
}
} else {
int id;
id = seccomp_syscall_resolve_name(*s);
if (id == __NR_SCMP_ERROR)
return -EINVAL;
r = set_put(c->address_families, INT_TO_PTR(id + 1));
if (r < 0)
return r;
}
}
}
joined = strv_join(l, " ");
if (!joined)
return -ENOMEM;
unit_write_drop_in_private_format(u, mode, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
}
return 1;
} else if (streq(name, "SystemCallArchitectures")) {
_cleanup_strv_free_ char **l = NULL;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
_cleanup_free_ char *joined = NULL;
if (strv_length(l) == 0)
c->syscall_archs = set_free(c->syscall_archs);
else {
char **s;
r = set_ensure_allocated(&c->syscall_archs, NULL);
if (r < 0)
return r;
STRV_FOREACH(s, l) {
uint32_t a;
r = seccomp_arch_from_string(*s, &a);
if (r < 0)
return r;
r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
if (r < 0)
return r;
}
}
joined = strv_join(l, " ");
if (!joined)
return -ENOMEM;
unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
}
return 1;
} else if (streq(name, "SystemCallErrorNumber")) {
int32_t n;
const char *str;
r = sd_bus_message_read(message, "i", &n);
if (r < 0)
return r;
str = errno_to_name(n);
if (!str)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SystemCallErrorNumber");
if (mode != UNIT_CHECK) {
c->syscall_errno = n;
unit_write_drop_in_private_format(u, mode, name, "SystemCallErrorNumber=%s", str);
}
return 1;
} else if (streq(name, "RestrictAddressFamilies")) {
int whitelist;
_cleanup_strv_free_ char **l;
r = sd_bus_message_enter_container(message, 'r', "bas");
if (r < 0)
return r;
r = sd_bus_message_read(message, "b", &whitelist);
if (r < 0)
return r;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
_cleanup_free_ char *joined = NULL;
if (strv_length(l) == 0) {
c->address_families_whitelist = false;
c->address_families = set_free(c->address_families);
} else {
char **s;
c->address_families_whitelist = whitelist;
r = set_ensure_allocated(&c->address_families, NULL);
if (r < 0)
return r;
STRV_FOREACH(s, l) {
int af;
af = af_from_name(*s);
if (af <= 0)
return -EINVAL;
r = set_put(c->address_families, INT_TO_PTR(af));
if (r < 0)
return r;
}
}
joined = strv_join(l, " ");
if (!joined)
return -ENOMEM;
unit_write_drop_in_private_format(u, mode, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
}
return 1;
#endif
} else if (streq(name, "CPUSchedulingPolicy")) {
int32_t n;
r = sd_bus_message_read(message, "i", &n);
if (r < 0)
return r;
if (!sched_policy_is_valid(n))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy");
if (mode != UNIT_CHECK) {
_cleanup_free_ char *str = NULL;
c->cpu_sched_policy = n;
r = sched_policy_to_string_alloc(n, &str);
if (r < 0)
return r;
unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPolicy=%s", str);
}
return 1;
} else if (streq(name, "CPUSchedulingPriority")) {
int32_t n;
r = sd_bus_message_read(message, "i", &n);
if (r < 0)
return r;
if (!ioprio_priority_is_valid(n))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority");
if (mode != UNIT_CHECK) {
c->cpu_sched_priority = n;
unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPriority=%i", n);
}
return 1;
} else if (streq(name, "CPUAffinity")) {
const void *a;
size_t n = 0;
r = sd_bus_message_read_array(message, 'y', &a, &n);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
if (n == 0) {
c->cpuset = mfree(c->cpuset);
unit_write_drop_in_private_format(u, mode, name, "%s=", name);
} else {
_cleanup_free_ char *str = NULL;
uint8_t *l;
size_t allocated = 0, len = 0, i;
c->cpuset = (cpu_set_t*) memdup(a, sizeof(cpu_set_t) * n);
if (c->cpuset)
return -ENOMEM;
l = (uint8_t*) a;
for (i = 0; i < n; i++) {
_cleanup_free_ char *p = NULL;
size_t add;
r = asprintf(&p, "%hhi", l[i]);
if (r < 0)
return -ENOMEM;
add = strlen(p);
if (GREEDY_REALLOC(str, allocated, len + add + 2))
return -ENOMEM;
strcpy(mempcpy(str + len, p, add), " ");
len += add + 1;
}
if (len != 0)
str[len - 1] = '\0';
unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
}
}
return 1;
} else if (streq(name, "Nice")) {
int32_t n;
@@ -1297,11 +1690,12 @@ int bus_exec_context_set_transient_property(
return 1;
} else if (STR_IN_SET(name,
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
"NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
"RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
"ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS")) {
"ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
"CPUSchedulingResetOnFork", "NonBlocking")) {
int b;
r = sd_bus_message_read(message, "b", &b);
@@ -1315,6 +1709,8 @@ int bus_exec_context_set_transient_property(
c->tty_vhangup = b;
else if (streq(name, "TTYReset"))
c->tty_reset = b;
else if (streq(name, "TTYVTDisallocate"))
c->tty_vt_disallocate = b;
else if (streq(name, "PrivateTmp"))
c->private_tmp = b;
else if (streq(name, "PrivateDevices"))
@@ -1343,6 +1739,10 @@ int bus_exec_context_set_transient_property(
c->protect_control_groups = b;
else if (streq(name, "MountAPIVFS"))
c->mount_apivfs = b;
else if (streq(name, "CPUSchedulingResetOnFork"))
c->cpu_sched_reset_on_fork = b;
else if (streq(name, "NonBlocking"))
c->non_blocking = b;
unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b));
}
@@ -1709,7 +2109,7 @@ int bus_exec_context_set_transient_property(
return 1;
} else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode")) {
} else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
mode_t m;
r = sd_bus_message_read(message, "u", &m);
@@ -1719,11 +2119,14 @@ int bus_exec_context_set_transient_property(
if (mode != UNIT_CHECK) {
ExecDirectoryType i;
for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
if (startswith(name, exec_directory_type_to_string(i))) {
c->directories[i].mode = m;
break;
}
if (streq(name, "UMask"))
c->umask = m;
else
for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
if (startswith(name, exec_directory_type_to_string(i))) {
c->directories[i].mode = m;
break;
}
unit_write_drop_in_private_format(u, mode, name, "%s=%040o", name, m);
}
@@ -1777,7 +2180,6 @@ int bus_exec_context_set_transient_property(
} else if (streq(name, "SELinuxContext")) {
const char *s;
r = sd_bus_message_read(message, "s", &s);
if (r < 0)
return r;
@@ -1792,6 +2194,45 @@ int bus_exec_context_set_transient_property(
}
return 1;
} else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
int ignore;
const char *s;
r = sd_bus_message_enter_container(message, 'r', "bs");
if (r < 0)
return r;
r = sd_bus_message_read(message, "bs", &ignore, &s);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
char **p;
bool *b;
if (streq(name, "AppArmorProfile")) {
p = &c->apparmor_profile;
b = &c->apparmor_profile_ignore;
} else { /* "SmackProcessLabel" */
p = &c->smack_process_label;
b = &c->smack_process_label_ignore;
}
if (isempty(s)) {
*p = mfree(*p);
*b = false;
} else {
if (free_and_strdup(p, s) < 0)
return -ENOMEM;
*b = ignore;
}
unit_write_drop_in_private_format(u, mode, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
}
return 1;
} else if (streq(name, "RestrictNamespaces")) {
uint64_t flags;
+16 -23
View File
@@ -90,6 +90,7 @@
#include "seccomp-util.h"
#endif
#include "securebits.h"
#include "securebits-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "smack-util.h"
@@ -3599,36 +3600,28 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
fprintf(f, "%sSyslogLevel: %s\n", prefix, lvl_str);
}
if (c->secure_bits)
fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
prefix,
(c->secure_bits & 1<<SECURE_KEEP_CAPS) ? " keep-caps" : "",
(c->secure_bits & 1<<SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
(c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
(c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
(c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
(c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
if (c->secure_bits) {
_cleanup_free_ char *str = NULL;
r = secure_bits_to_string_alloc(c->secure_bits, &str);
if (r >= 0)
fprintf(f, "%sSecure Bits: %s\n", prefix, str);
}
if (c->capability_bounding_set != CAP_ALL) {
unsigned long l;
fprintf(f, "%sCapabilityBoundingSet:", prefix);
_cleanup_free_ char *str = NULL;
for (l = 0; l <= cap_last_cap(); l++)
if (c->capability_bounding_set & (UINT64_C(1) << l))
fprintf(f, " %s", strna(capability_to_name(l)));
fputs("\n", f);
r = capability_set_to_string_alloc(c->capability_bounding_set, &str);
if (r >= 0)
fprintf(f, "%sCapabilityBoundingSet: %s\n", prefix, str);
}
if (c->capability_ambient_set != 0) {
unsigned long l;
fprintf(f, "%sAmbientCapabilities:", prefix);
_cleanup_free_ char *str = NULL;
for (l = 0; l <= cap_last_cap(); l++)
if (c->capability_ambient_set & (UINT64_C(1) << l))
fprintf(f, " %s", strna(capability_to_name(l)));
fputs("\n", f);
r = capability_set_to_string_alloc(c->capability_ambient_set, &str);
if (r >= 0)
fprintf(f, "%sAmbientCapabilities: %s\n", prefix, str);
}
if (c->user)
+19 -55
View File
@@ -58,6 +58,7 @@
#include "seccomp-util.h"
#endif
#include "securebits.h"
#include "securebits-util.h"
#include "signal-util.h"
#include "stat-util.h"
#include "string-util.h"
@@ -1094,7 +1095,6 @@ int config_parse_exec_secure_bits(const char *unit,
void *userdata) {
ExecContext *c = data;
const char *p;
int r;
assert(filename);
@@ -1108,38 +1108,18 @@ int config_parse_exec_secure_bits(const char *unit,
return 0;
}
for (p = rvalue;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (streq(word, "keep-caps"))
c->secure_bits |= 1<<SECURE_KEEP_CAPS;
else if (streq(word, "keep-caps-locked"))
c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
else if (streq(word, "no-setuid-fixup"))
c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
else if (streq(word, "no-setuid-fixup-locked"))
c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
else if (streq(word, "noroot"))
c->secure_bits |= 1<<SECURE_NOROOT;
else if (streq(word, "noroot-locked"))
c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
else {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Failed to parse secure bit \"%s\", ignoring.", word);
return 0;
}
r = secure_bits_from_string(rvalue);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
c->secure_bits = r;
return 0;
}
int config_parse_capability_set(
@@ -1157,7 +1137,7 @@ int config_parse_capability_set(
uint64_t *capability_set = data;
uint64_t sum = 0, initial = 0;
bool invert = false;
const char *p;
int r;
assert(filename);
assert(lvalue);
@@ -1173,28 +1153,12 @@ int config_parse_capability_set(
initial = CAP_ALL; /* initialized to all bits on */
/* else "AmbientCapabilities" initialized to all bits off */
p = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL;
int cap, r;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse word, ignoring: %s", rvalue);
break;
}
cap = capability_from_name(word);
if (cap < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding/ambient set, ignoring: %s", word);
continue;
}
sum |= ((uint64_t) UINT64_C(1)) << (uint64_t) cap;
r = capability_set_from_string(rvalue, &sum);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse word: %s", rvalue);
return 0;
}
sum = invert ? ~sum : sum;
+267 -5
View File
@@ -21,8 +21,11 @@
#include "bus-internal.h"
#include "bus-unit-util.h"
#include "bus-util.h"
#include "cap-list.h"
#include "cgroup-util.h"
#include "cpu-set-util.h"
#include "env-util.h"
#include "errno-list.h"
#include "escape.h"
#include "hashmap.h"
#include "list.h"
@@ -33,10 +36,12 @@
#include "path-util.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "securebits-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "syslog-util.h"
#include "terminal-util.h"
#include "user-util.h"
#include "utf8.h"
#include "util.h"
@@ -204,11 +209,12 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
} else if (STR_IN_SET(field,
"CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", "TasksAccounting",
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate", "RemainAfterExit",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges",
"SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute",
"RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
"ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS")) {
"ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
"CPUSchedulingResetOnFork")) {
r = parse_boolean(eq);
if (r < 0)
@@ -267,10 +273,24 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
"Description", "Slice", "Type", "WorkingDirectory",
"RootDirectory", "SyslogIdentifier", "ProtectSystem",
"ProtectHome", "SELinuxContext", "Restart", "RootImage",
"NotifyAccess", "RuntimeDirectoryPreserve"))
"NotifyAccess", "RuntimeDirectoryPreserve", "Personality"))
r = sd_bus_message_append(m, "v", "s", eq);
else if (streq(field, "SyslogLevel")) {
else if (STR_IN_SET(field, "AppArmorProfile", "SmackProcessLabel")) {
bool ignore;
const char *s;
if (eq[0] == '-') {
ignore = true;
s = eq + 1;
} else {
ignore = false;
s = eq;
}
r = sd_bus_message_append(m, "v", "(bs)", ignore, s);
} else if (streq(field, "SyslogLevel")) {
int level;
level = log_level_from_string(eq);
@@ -292,6 +312,37 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
r = sd_bus_message_append(m, "v", "i", facility);
} else if (streq(field, "SecureBits")) {
r = secure_bits_from_string(eq);
if (r < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "i", r);
} else if (STR_IN_SET(field, "CapabilityBoundingSet", "AmbientCapabilities")) {
uint64_t sum = 0;
bool invert = false;
const char *p;
p = eq;
if (*p == '~') {
invert = true;
p++;
}
r = capability_set_from_string(p, &sum);
if (r < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
sum = invert ? ~sum : sum;
r = sd_bus_message_append(m, "v", "t", sum);
} else if (streq(field, "DeviceAllow")) {
if (isempty(eq))
@@ -381,6 +432,43 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
r = sd_bus_message_append(m, "v", "a(st)", 1, path, u);
}
} else if (streq(field, "CPUSchedulingPolicy")) {
int n;
n = sched_policy_from_string(eq);
if (n < 0)
return log_error_errno(r, "Failed to parse CPUSchedulingPolicy: %s", eq);
r = sd_bus_message_append(m, "v", "i", (int32_t) n);
} else if (streq(field, "CPUSchedulingPriority")) {
int n;
r = safe_atoi(eq, &n);
if (r < 0)
return log_error_errno(r, "Failed to parse CPUSchedulingPriority: %s", eq);
if (!sched_priority_is_valid(n))
return log_error_errno(r, "Invalid CPUSchedulingPriority: %s", eq);
r = sd_bus_message_append(m, "v", "i", (int32_t) n);
} else if (streq(field, "CPUAffinity")) {
_cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
int ncpus;
ncpus = parse_cpu_set(eq, &cpuset);
if (ncpus < 0)
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
r = sd_bus_message_open_container(m, 'v', "ay");
if (r < 0)
return bus_log_create_error(r);
if (cpuset)
sd_bus_message_append_array(m, 'y', cpuset, CPU_ALLOC_SIZE(ncpus));
r = sd_bus_message_close_container(m);
} else if (streq(field, "Nice")) {
int n;
@@ -390,6 +478,142 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
r = sd_bus_message_append(m, "v", "i", (int32_t) n);
#ifdef HAVE_SECCOMP
} else if (streq(field, "SystemCallFilter")) {
int whitelist;
const char *p;
r = sd_bus_message_open_container(m, 'v', "bas");
if (r < 0)
return bus_log_create_error(r);
p = eq;
if (*p == '~') {
whitelist = 0;
p++;
} else
whitelist = 1;
r = sd_bus_message_append_basic(m, 'b', &whitelist);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
if (whitelist != 0) {
r = sd_bus_message_append_basic(m, 's', "@default");
if (r < 0)
return bus_log_create_error(r);
}
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r < 0)
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
if (r == 0)
break;
r = sd_bus_message_append_basic(m, 's', word);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
} else if (streq(field, "SystemCallArchitectures")) {
const char *p;
r = sd_bus_message_open_container(m, 'v', "as");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
for (p = eq;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r < 0)
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
if (r == 0)
break;
r = sd_bus_message_append_basic(m, 's', word);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
} else if (streq(field, "SystemCallErrorNumber")) {
int n;
n = errno_from_name(eq);
if (n < 0)
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
r = sd_bus_message_append(m, "v", "i", (int32_t) n);
} else if (streq(field, "RestrictAddressFamilies")) {
int whitelist;
const char *p;
r = sd_bus_message_open_container(m, 'v', "bas");
if (r < 0)
return bus_log_create_error(r);
p = eq;
if (*p == '~') {
whitelist = 0;
p++;
} else
whitelist = 1;
r = sd_bus_message_append_basic(m, 'b', &whitelist);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r < 0)
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
if (r == 0)
break;
r = sd_bus_message_append_basic(m, 's', word);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
#endif
} else if (streq(field, "FileDescriptorStoreMax")) {
unsigned u;
@@ -548,7 +772,45 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
r = sd_bus_message_close_container(m);
} else if (STR_IN_SET(field, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode")) {
} else if (streq(field, "SupplementaryGroups")) {
const char *p;
r = sd_bus_message_open_container(m, 'v', "as");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
for (p = eq;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r < 0) {
log_error("Failed to parse %s value %s", field, eq);
return -EINVAL;
}
if (r == 0)
break;
if (!valid_user_group_name_or_id(word)) {
log_error("Failed to parse %s value %s", field, eq);
return -EINVAL;
}
r = sd_bus_message_append_basic(m, 's', word);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
} else if (STR_IN_SET(field, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
mode_t mode;
r = parse_mode(eq, &mode);
+32
View File
@@ -30,7 +30,9 @@
#include "macro.h"
#include "nsflags.h"
#include "seccomp-util.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
#include "errno-list.h"
@@ -1313,3 +1315,33 @@ int seccomp_restrict_archs(Set *archs) {
return seccomp_load(seccomp);
}
int parse_syscall_archs(char **l, Set **archs) {
_cleanup_set_free_ Set *_archs;
char **s;
int r;
assert(l);
assert(archs);
r = set_ensure_allocated(&_archs, NULL);
if (r < 0)
return r;
STRV_FOREACH(s, l) {
uint32_t a;
r = seccomp_arch_from_string(*s, &a);
if (r < 0)
return -EINVAL;
r = set_put(_archs, UINT32_TO_PTR(a + 1));
if (r < 0)
return -ENOMEM;
}
*archs = _archs;
_archs = NULL;
return 0;
}
+2
View File
@@ -84,3 +84,5 @@ extern const uint32_t seccomp_local_archs[];
(arch) = seccomp_local_archs[++_i])
DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release);
int parse_syscall_archs(char **l, Set **archs);