diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/ask-password-api.c | 12 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 103 | ||||
-rw-r--r-- | src/shared/bus-util.c | 49 | ||||
-rw-r--r-- | src/shared/bus-util.h | 3 | ||||
-rw-r--r-- | src/shared/condition.c | 7 | ||||
-rw-r--r-- | src/shared/conf-parser.c | 9 | ||||
-rw-r--r-- | src/shared/fdset.c | 273 | ||||
-rw-r--r-- | src/shared/fdset.h | 58 | ||||
-rw-r--r-- | src/shared/install.c | 12 | ||||
-rw-r--r-- | src/shared/logs-show.c | 4 | ||||
-rw-r--r-- | src/shared/pager.c | 2 | ||||
-rw-r--r-- | src/shared/path-lookup.c | 2 | ||||
-rw-r--r-- | src/shared/seccomp-util.c | 233 | ||||
-rw-r--r-- | src/shared/seccomp-util.h | 7 | ||||
-rw-r--r-- | src/shared/vlan-util.c | 69 | ||||
-rw-r--r-- | src/shared/vlan-util.h | 35 |
16 files changed, 775 insertions, 103 deletions
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 4a4bd8d3b8..65151b19a6 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -139,11 +139,7 @@ static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **pa if (r < 0) return r; - /* Truncate trailing NUL */ - assert(n > 0); - assert(p[n-1] == 0); - - serial = add_key("user", keyname, p, n-1, KEY_SPEC_USER_KEYRING); + serial = add_key("user", keyname, p, n, KEY_SPEC_USER_KEYRING); memory_erase(p, n); if (serial == -1) return -errno; @@ -253,10 +249,12 @@ int ask_password_tty( goto finish; } - loop_write(ttyfd, ANSI_HIGHLIGHT, strlen(ANSI_HIGHLIGHT), false); + if (colors_enabled()) + loop_write(ttyfd, ANSI_HIGHLIGHT, strlen(ANSI_HIGHLIGHT), false); loop_write(ttyfd, message, strlen(message), false); loop_write(ttyfd, " ", 1, false); - loop_write(ttyfd, ANSI_NORMAL, strlen(ANSI_NORMAL), false); + if (colors_enabled()) + loop_write(ttyfd, ANSI_NORMAL, strlen(ANSI_NORMAL), false); new_termios = old_termios; new_termios.c_lflag &= ~(ICANON|ECHO); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index f68c4a41ac..ea020b517b 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -83,18 +83,14 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen if (isempty(eq)) r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY); - else if (endswith(eq, "%")) { - double percent; - - if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) { - log_error("CPU quota '%s' invalid.", eq); + else { + r = parse_percent(eq); + if (r <= 0) { + log_error_errno(r, "CPU quota '%s' invalid.", eq); return -EINVAL; } - r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100); - } else { - log_error("CPU quota needs to be in percent."); - return -EINVAL; + r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) r * USEC_PER_SEC / 100U); } goto finish; @@ -110,6 +106,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen char *n; usec_t t; size_t l; + r = parse_sec(eq, &t); if (r < 0) return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq); @@ -123,6 +120,54 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen strcpy(mempcpy(n, field, l - 3), "USec"); r = sd_bus_message_append(m, "sv", n, "t", t); goto finish; + + } else if (STR_IN_SET(field, "MemoryLow", "MemoryHigh", "MemoryMax", "MemoryLimit")) { + uint64_t bytes; + + if (isempty(eq) || streq(eq, "infinity")) + bytes = CGROUP_LIMIT_MAX; + else { + r = parse_percent(eq); + if (r >= 0) { + char *n; + + /* When this is a percentage we'll convert this into a relative value in the range + * 0…UINT32_MAX and pass it in the MemoryLowScale property (and related + * ones). This way the physical memory size can be determined server-side */ + + n = strjoina(field, "Scale"); + r = sd_bus_message_append(m, "sv", n, "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U)); + goto finish; + + } else { + r = parse_size(eq, 1024, &bytes); + if (r < 0) + return log_error_errno(r, "Failed to parse bytes specification %s", assignment); + } + } + + r = sd_bus_message_append(m, "sv", field, "t", bytes); + goto finish; + } else if (streq(field, "TasksMax")) { + uint64_t t; + + if (isempty(eq) || streq(eq, "infinity")) + t = (uint64_t) -1; + else { + r = parse_percent(eq); + if (r >= 0) { + r = sd_bus_message_append(m, "sv", "TasksMaxScale", "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U)); + goto finish; + } else { + r = safe_atou64(eq, &t); + if (r < 0) + return log_error_errno(r, "Failed to parse maximum tasks specification %s", assignment); + } + + } + + r = sd_bus_message_append(m, "sv", "TasksMax", "t", t); + goto finish; } r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); @@ -158,7 +203,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", - "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) { + "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute")) { r = parse_boolean(eq); if (r < 0) @@ -166,36 +211,6 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "b", r); - } else if (streq(field, "MemoryLimit")) { - uint64_t bytes; - - if (isempty(eq) || streq(eq, "infinity")) - bytes = (uint64_t) -1; - else { - r = parse_size(eq, 1024, &bytes); - if (r < 0) { - log_error("Failed to parse bytes specification %s", assignment); - return -EINVAL; - } - } - - r = sd_bus_message_append(m, "v", "t", bytes); - - } else if (streq(field, "TasksMax")) { - uint64_t n; - - if (isempty(eq) || streq(eq, "infinity")) - n = (uint64_t) -1; - else { - r = safe_atou64(eq, &n); - if (r < 0) { - log_error("Failed to parse maximum tasks specification %s", assignment); - return -EINVAL; - } - } - - r = sd_bus_message_append(m, "v", "t", n); - } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) { uint64_t u; @@ -306,7 +321,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen return -EINVAL; } - if (streq(bandwidth, "max")) { + if (streq(bandwidth, "infinity")) { bytes = CGROUP_LIMIT_MAX; } else { r = parse_size(bandwidth, 1000, &bytes); @@ -443,7 +458,8 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen } r = sd_bus_message_append(m, "v", "i", oa); - } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) { + } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories", + "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) { const char *p; r = sd_bus_message_open_container(m, 'v', "as"); @@ -1113,7 +1129,8 @@ static int dump_processes( assert(n == cg->n_children); qsort_safe(children, n, sizeof(struct CGroupInfo*), cgroup_info_compare_func); - n_columns = MAX(LESS_BY(n_columns, 2U), 20U); + if (n_columns != 0) + n_columns = MAX(LESS_BY(n_columns, 2U), 20U); for (i = 0; i < n; i++) { _cleanup_free_ char *pp = NULL; diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 4efbf3710f..52410999cf 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1048,7 +1048,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ case SD_BUS_TYPE_BOOLEAN: { unsigned b; - bool *p = userdata; + int *p = userdata; r = sd_bus_message_read_basic(m, type, &b); if (r < 0) @@ -1085,6 +1085,19 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ break; } + case SD_BUS_TYPE_DOUBLE: { + double d; + double *p = userdata; + + r = sd_bus_message_read_basic(m, type, &d); + if (r < 0) + break; + + *p = d; + + break; + } + default: break; } @@ -1492,40 +1505,6 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send return 1; } -bool is_kdbus_wanted(void) { - _cleanup_free_ char *value = NULL; -#ifdef ENABLE_KDBUS - const bool configured = true; -#else - const bool configured = false; -#endif - - int r; - - if (get_proc_cmdline_key("kdbus", NULL) > 0) - return true; - - r = get_proc_cmdline_key("kdbus=", &value); - if (r <= 0) - return configured; - - return parse_boolean(value) == 1; -} - -bool is_kdbus_available(void) { - _cleanup_close_ int fd = -1; - struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE }; - - if (!is_kdbus_wanted()) - return false; - - fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY); - if (fd < 0) - return false; - - return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0; -} - int bus_property_get_rlimit( sd_bus *bus, const char *path, diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index d792258ecd..db6b1acba2 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -157,7 +157,4 @@ int bus_log_create_error(int r); int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path); int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external); -bool is_kdbus_wanted(void); -bool is_kdbus_available(void); - int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); diff --git a/src/shared/condition.c b/src/shared/condition.c index 3a45ed265c..6bb42c0692 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -182,10 +182,11 @@ static int condition_test_architecture(Condition *c) { if (streq(c->parameter, "native")) b = native_architecture(); - else + else { b = architecture_from_string(c->parameter); - if (b < 0) - return b; + if (b < 0) /* unknown architecture? Then it's definitely not ours */ + return false; + } return a == b; } diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 83be79a4f5..7cf222e4d2 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -323,8 +323,7 @@ int config_parse(const char *unit, if (feof(f)) break; - log_error_errno(errno, "Failed to read configuration file '%s': %m", filename); - return -errno; + return log_error_errno(errno, "Failed to read configuration file '%s': %m", filename); } l = buf; @@ -708,6 +707,7 @@ int config_parse_strv(const char *unit, void *userdata) { char ***sv = data; + int r; assert(filename); assert(lvalue); @@ -721,18 +721,19 @@ int config_parse_strv(const char *unit, * we actually fill in a real empty array here rather * than NULL, since some code wants to know if * something was set at all... */ - empty = strv_new(NULL, NULL); + empty = new0(char*, 1); if (!empty) return log_oom(); strv_free(*sv); *sv = empty; + return 0; } for (;;) { char *word = NULL; - int r; + r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES|EXTRACT_RETAIN_ESCAPE); if (r == 0) break; diff --git a/src/shared/fdset.c b/src/shared/fdset.c new file mode 100644 index 0000000000..527f27bc67 --- /dev/null +++ b/src/shared/fdset.c @@ -0,0 +1,273 @@ +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + 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 <alloca.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stddef.h> + +#include "sd-daemon.h" + +#include "fd-util.h" +#include "fdset.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "set.h" + +#define MAKE_SET(s) ((Set*) s) +#define MAKE_FDSET(s) ((FDSet*) s) + +FDSet *fdset_new(void) { + return MAKE_FDSET(set_new(NULL)); +} + +int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) { + unsigned i; + FDSet *s; + int r; + + assert(ret); + + s = fdset_new(); + if (!s) + return -ENOMEM; + + for (i = 0; i < n_fds; i++) { + + r = fdset_put(s, fds[i]); + if (r < 0) { + set_free(MAKE_SET(s)); + return r; + } + } + + *ret = s; + return 0; +} + +FDSet* fdset_free(FDSet *s) { + void *p; + + while ((p = set_steal_first(MAKE_SET(s)))) { + /* Valgrind's fd might have ended up in this set here, + * due to fdset_new_fill(). We'll ignore all failures + * here, so that the EBADFD that valgrind will return + * us on close() doesn't influence us */ + + /* When reloading duplicates of the private bus + * connection fds and suchlike are closed here, which + * has no effect at all, since they are only + * duplicates. So don't be surprised about these log + * messages. */ + + log_debug("Closing left-over fd %i", PTR_TO_FD(p)); + close_nointr(PTR_TO_FD(p)); + } + + set_free(MAKE_SET(s)); + return NULL; +} + +int fdset_put(FDSet *s, int fd) { + assert(s); + assert(fd >= 0); + + return set_put(MAKE_SET(s), FD_TO_PTR(fd)); +} + +int fdset_put_dup(FDSet *s, int fd) { + int copy, r; + + assert(s); + assert(fd >= 0); + + copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) + return -errno; + + r = fdset_put(s, copy); + if (r < 0) { + safe_close(copy); + return r; + } + + return copy; +} + +bool fdset_contains(FDSet *s, int fd) { + assert(s); + assert(fd >= 0); + + return !!set_get(MAKE_SET(s), FD_TO_PTR(fd)); +} + +int fdset_remove(FDSet *s, int fd) { + assert(s); + assert(fd >= 0); + + return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT; +} + +int fdset_new_fill(FDSet **_s) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + FDSet *s; + + assert(_s); + + /* Creates an fdset and fills in all currently open file + * descriptors. */ + + d = opendir("/proc/self/fd"); + if (!d) + return -errno; + + s = fdset_new(); + if (!s) { + r = -ENOMEM; + goto finish; + } + + while ((de = readdir(d))) { + int fd = -1; + + if (hidden_or_backup_file(de->d_name)) + continue; + + r = safe_atoi(de->d_name, &fd); + if (r < 0) + goto finish; + + if (fd < 3) + continue; + + if (fd == dirfd(d)) + continue; + + r = fdset_put(s, fd); + if (r < 0) + goto finish; + } + + r = 0; + *_s = s; + s = NULL; + +finish: + /* We won't close the fds here! */ + if (s) + set_free(MAKE_SET(s)); + + return r; +} + +int fdset_cloexec(FDSet *fds, bool b) { + Iterator i; + void *p; + int r; + + assert(fds); + + SET_FOREACH(p, MAKE_SET(fds), i) { + r = fd_cloexec(PTR_TO_FD(p), b); + if (r < 0) + return r; + } + + return 0; +} + +int fdset_new_listen_fds(FDSet **_s, bool unset) { + int n, fd, r; + FDSet *s; + + assert(_s); + + /* Creates an fdset and fills in all passed file descriptors */ + + s = fdset_new(); + if (!s) { + r = -ENOMEM; + goto fail; + } + + n = sd_listen_fds(unset); + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { + r = fdset_put(s, fd); + if (r < 0) + goto fail; + } + + *_s = s; + return 0; + + +fail: + if (s) + set_free(MAKE_SET(s)); + + return r; +} + +int fdset_close_others(FDSet *fds) { + void *e; + Iterator i; + int *a; + unsigned j, m; + + j = 0, m = fdset_size(fds); + a = alloca(sizeof(int) * m); + SET_FOREACH(e, MAKE_SET(fds), i) + a[j++] = PTR_TO_FD(e); + + assert(j == m); + + return close_all_fds(a, j); +} + +unsigned fdset_size(FDSet *fds) { + return set_size(MAKE_SET(fds)); +} + +bool fdset_isempty(FDSet *fds) { + return set_isempty(MAKE_SET(fds)); +} + +int fdset_iterate(FDSet *s, Iterator *i) { + void *p; + + if (!set_iterate(MAKE_SET(s), i, &p)) + return -ENOENT; + + return PTR_TO_FD(p); +} + +int fdset_steal_first(FDSet *fds) { + void *p; + + p = set_steal_first(MAKE_SET(fds)); + if (!p) + return -ENOENT; + + return PTR_TO_FD(p); +} diff --git a/src/shared/fdset.h b/src/shared/fdset.h new file mode 100644 index 0000000000..16efe5bdf2 --- /dev/null +++ b/src/shared/fdset.h @@ -0,0 +1,58 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + 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 <stdbool.h> + +#include "hashmap.h" +#include "macro.h" +#include "set.h" + +typedef struct FDSet FDSet; + +FDSet* fdset_new(void); +FDSet* fdset_free(FDSet *s); + +int fdset_put(FDSet *s, int fd); +int fdset_put_dup(FDSet *s, int fd); + +bool fdset_contains(FDSet *s, int fd); +int fdset_remove(FDSet *s, int fd); + +int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds); +int fdset_new_fill(FDSet **ret); +int fdset_new_listen_fds(FDSet **ret, bool unset); + +int fdset_cloexec(FDSet *fds, bool b); + +int fdset_close_others(FDSet *fds); + +unsigned fdset_size(FDSet *fds); +bool fdset_isempty(FDSet *fds); + +int fdset_iterate(FDSet *s, Iterator *i); + +int fdset_steal_first(FDSet *fds); + +#define FDSET_FOREACH(fd, fds, i) \ + for ((i) = ITERATOR_FIRST, (fd) = fdset_iterate((fds), &(i)); (fd) >= 0; (fd) = fdset_iterate((fds), &(i))) + +DEFINE_TRIVIAL_CLEANUP_FUNC(FDSet*, fdset_free); +#define _cleanup_fdset_free_ _cleanup_(fdset_freep) diff --git a/src/shared/install.c b/src/shared/install.c index 64d66a45d3..7b49e1ece9 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -779,7 +779,7 @@ static int find_symlinks( fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (fd < 0) { - if (errno == ENOENT) + if (IN_SET(errno, ENOENT, ENOTDIR, EACCES)) return 0; return -errno; } @@ -1271,7 +1271,7 @@ static int unit_file_search( info->path = path; path = NULL; return r; - } else if (r != -ENOENT) + } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES)) return r; } @@ -1296,7 +1296,7 @@ static int unit_file_search( info->path = path; path = NULL; return r; - } else if (r != -ENOENT) + } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES)) return r; } } @@ -2215,7 +2215,7 @@ int unit_file_enable( config_path = runtime ? paths.runtime_config : paths.persistent_config; STRV_FOREACH(f, files) { - r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD, &i); + r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); if (r < 0) return r; r = install_info_may_process(i, &paths, changes, n_changes); @@ -2870,6 +2870,10 @@ int unit_file_get_list( if (!d) { if (errno == ENOENT) continue; + if (IN_SET(errno, ENOTDIR, EACCES)) { + log_debug("Failed to open \"%s\": %m", *i); + continue; + } return -errno; } diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 9351b85eed..d04728f505 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -489,7 +489,7 @@ static int output_verbose( off = ANSI_NORMAL; } - if (flags & OUTPUT_SHOW_ALL || + if ((flags & OUTPUT_SHOW_ALL) || (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH) && utf8_is_printable(data, length))) { fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data); @@ -607,7 +607,7 @@ void json_escape( if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD) fputs("null", f); - else if (!utf8_is_printable(p, l)) { + else if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(p, l)) { bool not_first = false; fputs("[ ", f); diff --git a/src/shared/pager.c b/src/shared/pager.c index c16bc027be..a2524d4420 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -63,7 +63,7 @@ int pager_open(bool no_pager, bool jump_to_end) { if (pager_pid > 0) return 1; - if (!on_tty()) + if (terminal_is_dumb()) return 0; pager = getenv("SYSTEMD_PAGER"); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index ca593b6963..862096ae7b 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -88,7 +88,7 @@ static int user_data_dir(char **ret, const char *suffix) { assert(suffix); /* We don't treat /etc/xdg/systemd here as the spec - * suggests because we assume that that is a link to + * suggests because we assume that is a link to * /etc/systemd/ anyway. */ e = getenv("XDG_DATA_HOME"); diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index cebe0fce2a..8656d112b8 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -88,3 +88,236 @@ int seccomp_add_secondary_archs(scmp_filter_ctx *c) { return 0; } + +const SystemCallFilterSet syscall_filter_sets[] = { + { + /* Clock */ + .set_name = "@clock", + .value = + "adjtimex\0" + "clock_adjtime\0" + "clock_settime\0" + "settimeofday\0" + "stime\0" + }, { + /* CPU emulation calls */ + .set_name = "@cpu-emulation", + .value = + "modify_ldt\0" + "subpage_prot\0" + "switch_endian\0" + "vm86\0" + "vm86old\0" + }, { + /* Debugging/Performance Monitoring/Tracing */ + .set_name = "@debug", + .value = + "lookup_dcookie\0" + "perf_event_open\0" + "process_vm_readv\0" + "process_vm_writev\0" + "ptrace\0" + "rtas\0" + "s390_runtime_instr\0" + "sys_debug_setcontext\0" + }, { + /* Default list */ + .set_name = "@default", + .value = + "execve\0" + "exit\0" + "exit_group\0" + "rt_sigreturn\0" + "sigreturn\0" + }, { + /* Event loop use */ + .set_name = "@io-event", + .value = + "_newselect\0" + "epoll_create1\0" + "epoll_create\0" + "epoll_ctl\0" + "epoll_ctl_old\0" + "epoll_pwait\0" + "epoll_wait\0" + "epoll_wait_old\0" + "eventfd2\0" + "eventfd\0" + "poll\0" + "ppoll\0" + "pselect6\0" + "select\0" + }, { + /* Message queues, SYSV IPC or other IPC: unusual */ + .set_name = "@ipc", + .value = "ipc\0" + "mq_getsetattr\0" + "mq_notify\0" + "mq_open\0" + "mq_timedreceive\0" + "mq_timedsend\0" + "mq_unlink\0" + "msgctl\0" + "msgget\0" + "msgrcv\0" + "msgsnd\0" + "process_vm_readv\0" + "process_vm_writev\0" + "semctl\0" + "semget\0" + "semop\0" + "semtimedop\0" + "shmat\0" + "shmctl\0" + "shmdt\0" + "shmget\0" + }, { + /* Keyring */ + .set_name = "@keyring", + .value = + "add_key\0" + "keyctl\0" + "request_key\0" + }, { + /* Kernel module control */ + .set_name = "@module", + .value = + "delete_module\0" + "finit_module\0" + "init_module\0" + }, { + /* Mounting */ + .set_name = "@mount", + .value = + "chroot\0" + "mount\0" + "oldumount\0" + "pivot_root\0" + "umount2\0" + "umount\0" + }, { + /* Network or Unix socket IO, should not be needed if not network facing */ + .set_name = "@network-io", + .value = + "accept4\0" + "accept\0" + "bind\0" + "connect\0" + "getpeername\0" + "getsockname\0" + "getsockopt\0" + "listen\0" + "recv\0" + "recvfrom\0" + "recvmmsg\0" + "recvmsg\0" + "send\0" + "sendmmsg\0" + "sendmsg\0" + "sendto\0" + "setsockopt\0" + "shutdown\0" + "socket\0" + "socketcall\0" + "socketpair\0" + }, { + /* Unusual, obsolete or unimplemented, some unknown even to libseccomp */ + .set_name = "@obsolete", + .value = + "_sysctl\0" + "afs_syscall\0" + "break\0" + "create_module\0" + "ftime\0" + "get_kernel_syms\0" + "getpmsg\0" + "gtty\0" + "lock\0" + "mpx\0" + "prof\0" + "profil\0" + "putpmsg\0" + "query_module\0" + "security\0" + "sgetmask\0" + "ssetmask\0" + "stty\0" + "sysfs\0" + "tuxcall\0" + "ulimit\0" + "uselib\0" + "ustat\0" + "vserver\0" + }, { + /* Nice grab-bag of all system calls which need superuser capabilities */ + .set_name = "@privileged", + .value = + "@clock\0" + "@module\0" + "@raw-io\0" + "acct\0" + "bdflush\0" + "bpf\0" + "capset\0" + "chown32\0" + "chown\0" + "chroot\0" + "fchown32\0" + "fchown\0" + "fchownat\0" + "kexec_file_load\0" + "kexec_load\0" + "lchown32\0" + "lchown\0" + "nfsservctl\0" + "pivot_root\0" + "quotactl\0" + "reboot\0" + "setdomainname\0" + "setfsuid32\0" + "setfsuid\0" + "setgroups32\0" + "setgroups\0" + "sethostname\0" + "setresuid32\0" + "setresuid\0" + "setreuid32\0" + "setreuid\0" + "setuid32\0" + "setuid\0" + "swapoff\0" + "swapon\0" + "sysctl\0" + "vhangup\0" + }, { + /* Process control, execution, namespaces */ + .set_name = "@process", + .value = + "arch_prctl\0" + "clone\0" + "execve\0" + "execveat\0" + "fork\0" + "kill\0" + "prctl\0" + "setns\0" + "tgkill\0" + "tkill\0" + "unshare\0" + "vfork\0" + }, { + /* Raw I/O ports */ + .set_name = "@raw-io", + .value = + "ioperm\0" + "iopl\0" + "pciconfig_iobase\0" + "pciconfig_read\0" + "pciconfig_write\0" + "s390_pci_mmio_read\0" + "s390_pci_mmio_write\0" + }, { + .set_name = NULL, + .value = NULL + } +}; diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index 4ed2afc1b2..be33eecb85 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -26,3 +26,10 @@ const char* seccomp_arch_to_string(uint32_t c); int seccomp_arch_from_string(const char *n, uint32_t *ret); int seccomp_add_secondary_archs(scmp_filter_ctx *c); + +typedef struct SystemCallFilterSet { + const char *set_name; + const char *value; +} SystemCallFilterSet; + +extern const SystemCallFilterSet syscall_filter_sets[]; diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c new file mode 100644 index 0000000000..78d66dd3d9 --- /dev/null +++ b/src/shared/vlan-util.c @@ -0,0 +1,69 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + 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 "vlan-util.h" +#include "parse-util.h" +#include "conf-parser.h" + +int parse_vlanid(const char *p, uint16_t *ret) { + uint16_t id; + int r; + + r = safe_atou16(p, &id); + if (r < 0) + return r; + if (!vlanid_is_valid(id)) + return -ERANGE; + + *ret = id; + return 0; +} + +int config_parse_vlanid( + 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) { + + uint16_t *id = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_vlanid(rvalue, id); + if (r == -ERANGE) { + log_syntax(unit, LOG_ERR, filename, line, r, "VLAN identifier outside of valid range 0…4094, ignoring: %s", rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VLAN identifier value, ignoring: %s", rvalue); + return 0; + } + + return 0; +} diff --git a/src/shared/vlan-util.h b/src/shared/vlan-util.h new file mode 100644 index 0000000000..ce6763b3a3 --- /dev/null +++ b/src/shared/vlan-util.h @@ -0,0 +1,35 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + 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 <stdbool.h> +#include <inttypes.h> + +#define VLANID_MAX 4094 +#define VLANID_INVALID UINT16_MAX + +/* Note that we permit VLAN Id 0 here, as that is apparently OK by the Linux kernel */ +static inline bool vlanid_is_valid(uint16_t id) { + return id <= VLANID_MAX; +} + +int parse_vlanid(const char *p, uint16_t *ret); + +int config_parse_vlanid(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); |