summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/dissect-image.c39
-rw-r--r--src/shared/dropin.c88
-rw-r--r--src/shared/dropin.h37
-rw-r--r--src/shared/gpt.h2
-rw-r--r--src/shared/install.c150
-rw-r--r--src/shared/seccomp-util.c137
-rw-r--r--src/shared/seccomp-util.h14
7 files changed, 311 insertions, 156 deletions
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 66ddf3a872..410a7764ed 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -352,9 +352,6 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
sd_id128_t type_id, id;
bool rw = true;
- if (pflags & GPT_FLAG_NO_AUTO)
- continue;
-
sid = blkid_partition_get_uuid(pp);
if (!sid)
continue;
@@ -368,18 +365,37 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
continue;
if (sd_id128_equal(type_id, GPT_HOME)) {
+
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
designator = PARTITION_HOME;
rw = !(pflags & GPT_FLAG_READ_ONLY);
} else if (sd_id128_equal(type_id, GPT_SRV)) {
+
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
designator = PARTITION_SRV;
rw = !(pflags & GPT_FLAG_READ_ONLY);
} else if (sd_id128_equal(type_id, GPT_ESP)) {
+
+ /* Note that we don't check the GPT_FLAG_NO_AUTO flag for the ESP, as it is not defined
+ * there. We instead check the GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as recommended by the
+ * UEFI spec (See "12.3.3 Number and Location of System Partitions"). */
+
+ if (pflags & GPT_FLAG_NO_BLOCK_IO_PROTOCOL)
+ continue;
+
designator = PARTITION_ESP;
fstype = "vfat";
}
#ifdef GPT_ROOT_NATIVE
else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
/* If a root ID is specified, ignore everything but the root id */
if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
continue;
@@ -389,6 +405,9 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
rw = !(pflags & GPT_FLAG_READ_ONLY);
} else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) {
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
m->can_verity = true;
/* Ignore verity unless a root hash is specified */
@@ -404,6 +423,9 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
#ifdef GPT_ROOT_SECONDARY
else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) {
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
/* If a root ID is specified, ignore everything but the root id */
if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
continue;
@@ -412,6 +434,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
architecture = SECONDARY_ARCHITECTURE;
rw = !(pflags & GPT_FLAG_READ_ONLY);
} else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) {
+
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
m->can_verity = true;
/* Ignore verity unless root has is specified */
@@ -425,10 +451,17 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
}
#endif
else if (sd_id128_equal(type_id, GPT_SWAP)) {
+
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
designator = PARTITION_SWAP;
fstype = "swap";
} else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
+ if (pflags & GPT_FLAG_NO_AUTO)
+ continue;
+
if (generic_node)
multiple_generic = true;
else {
diff --git a/src/shared/dropin.c b/src/shared/dropin.c
index 06cf3de620..3917eb8f23 100644
--- a/src/shared/dropin.c
+++ b/src/shared/dropin.c
@@ -117,17 +117,12 @@ int write_drop_in_format(const char *dir, const char *unit, unsigned level,
return write_drop_in(dir, unit, level, name, p);
}
-static int iterate_dir(
- const char *path,
+static int unit_file_find_dir(
const char *original_root,
- UnitDependency dependency,
- dependency_consumer_t consumer,
- void *arg,
- char ***strv) {
+ const char *path,
+ char ***dirs) {
_cleanup_free_ char *chased = NULL;
- _cleanup_closedir_ DIR *d = NULL;
- struct dirent *de;
int r;
assert(path);
@@ -137,52 +132,21 @@ static int iterate_dir(
return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING,
r, "Failed to canonicalize path %s: %m", path);
- /* The config directories are special, since the order of the
- * drop-ins matters */
- if (dependency < 0) {
- r = strv_push(strv, chased);
- if (r < 0)
- return log_oom();
-
- chased = NULL;
- return 0;
- }
-
- assert(consumer);
-
- d = opendir(chased);
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- return log_warning_errno(errno, "Failed to open directory %s: %m", path);
- }
-
- FOREACH_DIRENT(de, d, return log_warning_errno(errno, "Failed to read directory %s: %m", path)) {
- _cleanup_free_ char *f = NULL;
-
- f = strjoin(path, "/", de->d_name);
- if (!f)
- return log_oom();
-
- r = consumer(dependency, de->d_name, f, arg);
- if (r < 0)
- return r;
- }
+ r = strv_push(dirs, chased);
+ if (r < 0)
+ return log_oom();
+ chased = NULL;
return 0;
}
-int unit_file_process_dir(
+static int unit_file_find_dirs(
const char *original_root,
Set *unit_path_cache,
const char *unit_path,
const char *name,
const char *suffix,
- UnitDependency dependency,
- dependency_consumer_t consumer,
- void *arg,
- char ***strv) {
+ char ***dirs) {
_cleanup_free_ char *path = NULL;
int r;
@@ -195,8 +159,11 @@ int unit_file_process_dir(
if (!path)
return log_oom();
- if (!unit_path_cache || set_get(unit_path_cache, path))
- (void) iterate_dir(path, original_root, dependency, consumer, arg, strv);
+ if (!unit_path_cache || set_get(unit_path_cache, path)) {
+ r = unit_file_find_dir(original_root, path, dirs);
+ if (r < 0)
+ return r;
+ }
if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) {
_cleanup_free_ char *template = NULL, *p = NULL;
@@ -210,8 +177,11 @@ int unit_file_process_dir(
if (!p)
return log_oom();
- if (!unit_path_cache || set_get(unit_path_cache, p))
- (void) iterate_dir(p, original_root, dependency, consumer, arg, strv);
+ if (!unit_path_cache || set_get(unit_path_cache, p)) {
+ r = unit_file_find_dir(original_root, p, dirs);
+ if (r < 0)
+ return r;
+ }
}
return 0;
@@ -221,30 +191,28 @@ int unit_file_find_dropin_paths(
const char *original_root,
char **lookup_path,
Set *unit_path_cache,
+ const char *dir_suffix,
+ const char *file_suffix,
Set *names,
char ***paths) {
- _cleanup_strv_free_ char **strv = NULL, **ans = NULL;
+ _cleanup_strv_free_ char **dirs = NULL, **ans = NULL;
Iterator i;
- char *t;
+ char *t, **p;
int r;
assert(paths);
- SET_FOREACH(t, names, i) {
- char **p;
-
+ SET_FOREACH(t, names, i)
STRV_FOREACH(p, lookup_path)
- unit_file_process_dir(original_root, unit_path_cache, *p, t, ".d",
- _UNIT_DEPENDENCY_INVALID, NULL, NULL, &strv);
- }
+ unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs);
- if (strv_isempty(strv))
+ if (strv_isempty(dirs))
return 0;
- r = conf_files_list_strv(&ans, ".conf", NULL, (const char**) strv);
+ r = conf_files_list_strv(&ans, file_suffix, NULL, (const char**) dirs);
if (r < 0)
- return log_warning_errno(r, "Failed to get list of configuration files: %m");
+ return log_warning_errno(r, "Failed to sort the list of configuration files: %m");
*paths = ans;
ans = NULL;
diff --git a/src/shared/dropin.h b/src/shared/dropin.h
index 761b250886..a2b8cdce61 100644
--- a/src/shared/dropin.h
+++ b/src/shared/dropin.h
@@ -33,31 +33,24 @@ int write_drop_in(const char *dir, const char *unit, unsigned level,
int write_drop_in_format(const char *dir, const char *unit, unsigned level,
const char *name, const char *format, ...) _printf_(5, 6);
-/**
- * This callback will be called for each directory entry @entry,
- * with @filepath being the full path to the entry.
- *
- * If return value is negative, loop will be aborted.
- */
-typedef int (*dependency_consumer_t)(UnitDependency dependency,
- const char *entry,
- const char* filepath,
- void *arg);
-
-int unit_file_process_dir(
- const char *original_root,
- Set * unit_path_cache,
- const char *unit_path,
- const char *name,
- const char *suffix,
- UnitDependency dependency,
- dependency_consumer_t consumer,
- void *arg,
- char ***strv);
-
int unit_file_find_dropin_paths(
const char *original_root,
char **lookup_path,
Set *unit_path_cache,
+ const char *dir_suffix,
+ const char *file_suffix,
Set *names,
char ***paths);
+
+static inline int unit_file_find_dropin_conf_paths(
+ const char *original_root,
+ char **lookup_path,
+ Set *unit_path_cache,
+ Set *names,
+ char ***paths) {
+ return unit_file_find_dropin_paths(original_root,
+ lookup_path,
+ unit_path_cache,
+ ".d", ".conf",
+ names, paths);
+}
diff --git a/src/shared/gpt.h b/src/shared/gpt.h
index 13d80d611c..cc752006fa 100644
--- a/src/shared/gpt.h
+++ b/src/shared/gpt.h
@@ -71,6 +71,8 @@
# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_ARM_VERITY
#endif
+#define GPT_FLAG_NO_BLOCK_IO_PROTOCOL (1ULL << 1)
+
/* Flags we recognize on the root, swap, home and srv partitions when
* doing auto-discovery. These happen to be identical to what
* Microsoft defines for its own Basic Data Partitions, but that's
diff --git a/src/shared/install.c b/src/shared/install.c
index 478abac8ab..f25ed685f6 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -208,7 +208,7 @@ static int path_is_control(const LookupPaths *p, const char *path) {
path_equal_ptr(parent, p->runtime_control);
}
-static int path_is_config(const LookupPaths *p, const char *path) {
+static int path_is_config(const LookupPaths *p, const char *path, bool check_parent) {
_cleanup_free_ char *parent = NULL;
assert(p);
@@ -217,15 +217,19 @@ static int path_is_config(const LookupPaths *p, const char *path) {
/* Note that we do *not* have generic checks for /etc or /run in place, since with
* them we couldn't discern configuration from transient or generated units */
- parent = dirname_malloc(path);
- if (!parent)
- return -ENOMEM;
+ if (check_parent) {
+ parent = dirname_malloc(path);
+ if (!parent)
+ return -ENOMEM;
- return path_equal_ptr(parent, p->persistent_config) ||
- path_equal_ptr(parent, p->runtime_config);
+ path = parent;
+ }
+
+ return path_equal_ptr(path, p->persistent_config) ||
+ path_equal_ptr(path, p->runtime_config);
}
-static int path_is_runtime(const LookupPaths *p, const char *path) {
+static int path_is_runtime(const LookupPaths *p, const char *path, bool check_parent) {
_cleanup_free_ char *parent = NULL;
const char *rpath;
@@ -239,16 +243,20 @@ static int path_is_runtime(const LookupPaths *p, const char *path) {
if (rpath && path_startswith(rpath, "/run"))
return true;
- parent = dirname_malloc(path);
- if (!parent)
- return -ENOMEM;
+ if (check_parent) {
+ parent = dirname_malloc(path);
+ if (!parent)
+ return -ENOMEM;
- return path_equal_ptr(parent, p->runtime_config) ||
- path_equal_ptr(parent, p->generator) ||
- path_equal_ptr(parent, p->generator_early) ||
- path_equal_ptr(parent, p->generator_late) ||
- path_equal_ptr(parent, p->transient) ||
- path_equal_ptr(parent, p->runtime_control);
+ path = parent;
+ }
+
+ return path_equal_ptr(path, p->runtime_config) ||
+ path_equal_ptr(path, p->generator) ||
+ path_equal_ptr(path, p->generator_early) ||
+ path_equal_ptr(path, p->generator_late) ||
+ path_equal_ptr(path, p->transient) ||
+ path_equal_ptr(path, p->runtime_control);
}
static int path_is_vendor(const LookupPaths *p, const char *path) {
@@ -677,7 +685,6 @@ static int find_symlinks_fd(
int fd,
const char *path,
const char *config_path,
- const LookupPaths *lp,
bool *same_name_link) {
_cleanup_closedir_ DIR *d = NULL;
@@ -688,7 +695,6 @@ static int find_symlinks_fd(
assert(fd >= 0);
assert(path);
assert(config_path);
- assert(lp);
assert(same_name_link);
d = fdopendir(fd);
@@ -722,7 +728,7 @@ static int find_symlinks_fd(
}
/* This will close nfd, regardless whether it succeeds or not */
- q = find_symlinks_fd(root_dir, name, nfd, p, config_path, lp, same_name_link);
+ q = find_symlinks_fd(root_dir, name, nfd, p, config_path, same_name_link);
if (q > 0)
return 1;
if (r == 0)
@@ -800,7 +806,6 @@ static int find_symlinks(
const char *root_dir,
const char *name,
const char *config_path,
- const LookupPaths *lp,
bool *same_name_link) {
int fd;
@@ -817,44 +822,82 @@ static int find_symlinks(
}
/* This takes possession of fd and closes it */
- return find_symlinks_fd(root_dir, name, fd, config_path, config_path, lp, same_name_link);
+ return find_symlinks_fd(root_dir, name, fd, config_path, config_path, same_name_link);
}
static int find_symlinks_in_scope(
- UnitFileScope scope,
const LookupPaths *paths,
const char *name,
UnitFileState *state) {
- bool same_name_link_runtime = false, same_name_link = false;
+ bool same_name_link_runtime = false, same_name_link_config = false;
+ bool enabled_in_runtime = false, enabled_at_all = false;
+ char **p;
int r;
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(paths);
assert(name);
- /* First look in the persistent config path */
- r = find_symlinks(paths->root_dir, name, paths->persistent_config, paths, &same_name_link);
- if (r < 0)
- return r;
- if (r > 0) {
- *state = UNIT_FILE_ENABLED;
- return r;
+ STRV_FOREACH(p, paths->search_path) {
+ bool same_name_link = false;
+
+ r = find_symlinks(paths->root_dir, name, *p, &same_name_link);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
+
+ r = path_is_config(paths, *p, false);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ /* This is the best outcome, let's return it immediately. */
+ *state = UNIT_FILE_ENABLED;
+ return 1;
+ }
+
+ r = path_is_runtime(paths, *p, false);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ enabled_in_runtime = true;
+ else
+ enabled_at_all = true;
+
+ } else if (same_name_link) {
+
+ r = path_is_config(paths, *p, false);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ same_name_link_config = true;
+ else {
+ r = path_is_runtime(paths, *p, false);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ same_name_link_runtime = true;
+ }
+ }
}
- /* Then look in runtime config path */
- r = find_symlinks(paths->root_dir, name, paths->runtime_config, paths, &same_name_link_runtime);
- if (r < 0)
- return r;
- if (r > 0) {
+ if (enabled_in_runtime) {
*state = UNIT_FILE_ENABLED_RUNTIME;
- return r;
+ return 1;
+ }
+
+ /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
+ * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
+ * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
+ * something, and hence are a much stronger concept. */
+ if (enabled_at_all && unit_name_is_valid(name, UNIT_NAME_INSTANCE)) {
+ *state = UNIT_FILE_STATIC;
+ return 1;
}
/* Hmm, we didn't find it, but maybe we found the same name
* link? */
- if (same_name_link) {
+ if (same_name_link_config) {
*state = UNIT_FILE_LINKED;
return 1;
}
@@ -1354,7 +1397,8 @@ static int install_info_follow(
InstallContext *c,
UnitFileInstallInfo *i,
const char *root_dir,
- SearchFlags flags) {
+ SearchFlags flags,
+ bool ignore_different_name) {
assert(c);
assert(i);
@@ -1367,7 +1411,7 @@ static int install_info_follow(
/* If the basename doesn't match, the caller should add a
* complete new entry for this. */
- if (!streq(basename(i->symlink_target), i->name))
+ if (!ignore_different_name && !streq(basename(i->symlink_target), i->name))
return -EXDEV;
free_and_replace(i->path, i->symlink_target);
@@ -1408,14 +1452,14 @@ static int install_info_traverse(
return -ELOOP;
if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
- r = path_is_config(paths, i->path);
+ r = path_is_config(paths, i->path, true);
if (r < 0)
return r;
if (r > 0)
return -ELOOP;
}
- r = install_info_follow(c, i, paths->root_dir, flags);
+ r = install_info_follow(c, i, paths->root_dir, flags, false);
if (r == -EXDEV) {
_cleanup_free_ char *buffer = NULL;
const char *bn;
@@ -1439,6 +1483,18 @@ static int install_info_traverse(
if (r < 0)
return r;
+ if (streq(buffer, i->name)) {
+
+ /* We filled in the instance, and the target stayed the same? If so, then let's
+ * honour the link as it is. */
+
+ r = install_info_follow(c, i, paths->root_dir, flags, true);
+ if (r < 0)
+ return r;
+
+ continue;
+ }
+
bn = buffer;
}
@@ -2027,7 +2083,7 @@ static int path_shall_revert(const LookupPaths *paths, const char *path) {
/* Checks whether the path is one where the drop-in directories shall be removed. */
- r = path_is_config(paths, path);
+ r = path_is_config(paths, path, true);
if (r != 0)
return r;
@@ -2135,7 +2191,7 @@ int unit_file_revert(
if (errno != ENOENT)
return -errno;
} else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
- r = path_is_config(&paths, path);
+ r = path_is_config(&paths, path, true);
if (r < 0)
return r;
if (r > 0) {
@@ -2481,7 +2537,7 @@ static int unit_file_lookup_state(
switch (i->type) {
case UNIT_FILE_TYPE_MASKED:
- r = path_is_runtime(paths, i->path);
+ r = path_is_runtime(paths, i->path, true);
if (r < 0)
return r;
@@ -2505,7 +2561,7 @@ static int unit_file_lookup_state(
break;
}
- r = find_symlinks_in_scope(scope, paths, i->name, &state);
+ r = find_symlinks_in_scope(paths, i->name, &state);
if (r < 0)
return r;
if (r == 0) {
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 609e0619af..e35f18471c 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -750,10 +750,35 @@ int seccomp_restrict_namespaces(unsigned long retain) {
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
+ int clone_reversed_order = -1;
unsigned i;
log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ switch (arch) {
+
+ case SCMP_ARCH_X86_64:
+ case SCMP_ARCH_X86:
+ case SCMP_ARCH_X32:
+ clone_reversed_order = 0;
+ break;
+
+ case SCMP_ARCH_S390:
+ case SCMP_ARCH_S390X:
+ /* On s390/s390x the first two parameters to clone are switched */
+ clone_reversed_order = 1;
+ break;
+
+ /* Please add more definitions here, if you port systemd to other architectures! */
+
+#if !defined(__i386__) && !defined(__x86_64__) && !defined(__s390__) && !defined(__s390x__)
+#warning "Consider adding the right clone() syscall definitions here!"
+#endif
+ }
+
+ if (clone_reversed_order < 0) /* we don't know the right order, let's ignore this arch... */
+ continue;
+
r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
if (r < 0)
return r;
@@ -802,12 +827,20 @@ int seccomp_restrict_namespaces(unsigned long retain) {
break;
}
- r = seccomp_rule_add_exact(
- seccomp,
- SCMP_ACT_ERRNO(EPERM),
- SCMP_SYS(clone),
- 1,
- SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
+ if (clone_reversed_order == 0)
+ r = seccomp_rule_add_exact(
+ seccomp,
+ SCMP_ACT_ERRNO(EPERM),
+ SCMP_SYS(clone),
+ 1,
+ SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
+ else
+ r = seccomp_rule_add_exact(
+ seccomp,
+ SCMP_ACT_ERRNO(EPERM),
+ SCMP_SYS(clone),
+ 1,
+ SCMP_A1(SCMP_CMP_MASKED_EQ, f, f));
if (r < 0) {
log_debug_errno(r, "Failed to add clone() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
break;
@@ -1086,27 +1119,81 @@ int seccomp_restrict_realtime(void) {
}
int seccomp_memory_deny_write_execute(void) {
+
uint32_t arch;
int r;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
+ int filter_syscall = 0, block_syscall = 0, shmat_syscall = 0;
log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ switch (arch) {
+
+ case SCMP_ARCH_X86:
+ filter_syscall = SCMP_SYS(mmap2);
+ block_syscall = SCMP_SYS(mmap);
+
+ /* Note that shmat() isn't available on i386, where the call is multiplexed through ipc(). We
+ * ignore that here, which means there's still a way to get writable/executable memory, if an
+ * IPC key is mapped like this on i386. That's a pity, but no total loss. */
+ break;
+
+ case SCMP_ARCH_X86_64:
+ case SCMP_ARCH_X32:
+ filter_syscall = SCMP_SYS(mmap);
+ shmat_syscall = SCMP_SYS(shmat);
+ break;
+
+ /* Please add more definitions here, if you port systemd to other architectures! */
+
+#if !defined(__i386__) && !defined(__x86_64__)
+#warning "Consider adding the right mmap() syscall definitions here!"
+#endif
+ }
+
+ /* Can't filter mmap() on this arch, then skip it */
+ if (filter_syscall == 0)
+ continue;
+
r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
if (r < 0)
return r;
- r = seccomp_rule_add_exact(
- seccomp,
- SCMP_ACT_ERRNO(EPERM),
- SCMP_SYS(mmap),
- 1,
- SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC|PROT_WRITE, PROT_EXEC|PROT_WRITE));
- if (r < 0) {
- log_debug_errno(r, "Failed to add mmap() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
- continue;
+ if (filter_syscall != 0) {
+ r = seccomp_rule_add_exact(
+ seccomp,
+ SCMP_ACT_ERRNO(EPERM),
+ filter_syscall,
+ 1,
+ SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC|PROT_WRITE, PROT_EXEC|PROT_WRITE));
+ if (r < 0) {
+ _cleanup_free_ char *n = NULL;
+
+ n = seccomp_syscall_resolve_num_arch(arch, filter_syscall);
+ log_debug_errno(r, "Failed to add %s() rule for architecture %s, skipping: %m",
+ strna(n),
+ seccomp_arch_to_string(arch));
+ continue;
+ }
+ }
+
+ if (block_syscall != 0) {
+ r = seccomp_rule_add_exact(
+ seccomp,
+ SCMP_ACT_ERRNO(EPERM),
+ block_syscall,
+ 0);
+ if (r < 0) {
+ _cleanup_free_ char *n = NULL;
+
+ n = seccomp_syscall_resolve_num_arch(arch, block_syscall);
+ log_debug_errno(r, "Failed to add %s() rule for architecture %s, skipping: %m",
+ strna(n),
+ seccomp_arch_to_string(arch));
+ continue;
+ }
}
r = seccomp_rule_add_exact(
@@ -1120,15 +1207,17 @@ int seccomp_memory_deny_write_execute(void) {
continue;
}
- r = seccomp_rule_add_exact(
- seccomp,
- SCMP_ACT_ERRNO(EPERM),
- SCMP_SYS(shmat),
- 1,
- SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC));
- if (r < 0) {
- log_debug_errno(r, "Failed to add shmat() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
- continue;
+ if (shmat_syscall != 0) {
+ r = seccomp_rule_add_exact(
+ seccomp,
+ SCMP_ACT_ERRNO(EPERM),
+ SCMP_SYS(shmat),
+ 1,
+ SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC));
+ if (r < 0) {
+ log_debug_errno(r, "Failed to add shmat() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ continue;
+ }
}
r = seccomp_load(seccomp);
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index 2563fcd38a..61f94de638 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -84,6 +84,20 @@ int seccomp_memory_deny_write_execute(void);
#define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
#endif
+/* mmap() blocking is only available on some archs for now */
+#if defined(__x86_64__) || defined(__i386__)
+#define SECCOMP_MEMORY_DENY_WRITE_EXECUTE_BROKEN 0
+#else
+#define SECCOMP_MEMORY_DENY_WRITE_EXECUTE_BROKEN 1
+#endif
+
+/* we don't know the right order of the clone() parameters except for these archs, for now */
+#if defined(__x86_64__) || defined(__i386__) || defined(__s390x__) || defined(__s390__)
+#define SECCOMP_RESTRICT_NAMESPACES_BROKEN 0
+#else
+#define SECCOMP_RESTRICT_NAMESPACES_BROKEN 1
+#endif
+
extern const uint32_t seccomp_local_archs[];
#define SECCOMP_FOREACH_LOCAL_ARCH(arch) \