core: allow using seccomp without no_new_privs when unprivileged

Until now, using any form of seccomp while being unprivileged (User=)
resulted in systemd enabling no_new_privs.

There's no need for doing this because:

* We trust the filters we apply
* If User= is set and a process wants to apply a new seccomp filter, it
will need to set no_new_privs itself

An example of application that might want seccomp + !no_new_privs is a
program that wants to run as an unprivileged user but uses file
capabilities to start a web server on a privileged port while
benefitting from a restrictive seccomp profile.

We now keep the privileges needed to do seccomp before calling
enforce_user() and drop them after the seccomp filters are applied.

If the syscall filter doesn't allow the needed syscalls to drop the
privileges, we keep the previous behavior by enabling no_new_privs.
This commit is contained in:
Iago López Galeiras
2023-11-07 11:31:53 +01:00
parent b3e199cec8
commit 24832d10b6
4 changed files with 181 additions and 101 deletions
+12 -4
View File
@@ -367,16 +367,16 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
return 0;
}
int drop_capability(cap_value_t cv) {
static int change_capability(cap_value_t cv, cap_flag_value_t flag) {
_cleanup_cap_free_ cap_t tmp_cap = NULL;
tmp_cap = cap_get_proc();
if (!tmp_cap)
return -errno;
if ((cap_set_flag(tmp_cap, CAP_INHERITABLE, 1, &cv, CAP_CLEAR) < 0) ||
(cap_set_flag(tmp_cap, CAP_PERMITTED, 1, &cv, CAP_CLEAR) < 0) ||
(cap_set_flag(tmp_cap, CAP_EFFECTIVE, 1, &cv, CAP_CLEAR) < 0))
if ((cap_set_flag(tmp_cap, CAP_INHERITABLE, 1, &cv, flag) < 0) ||
(cap_set_flag(tmp_cap, CAP_PERMITTED, 1, &cv, flag) < 0) ||
(cap_set_flag(tmp_cap, CAP_EFFECTIVE, 1, &cv, flag) < 0))
return -errno;
if (cap_set_proc(tmp_cap) < 0)
@@ -385,6 +385,14 @@ int drop_capability(cap_value_t cv) {
return 0;
}
int drop_capability(cap_value_t cv) {
return change_capability(cv, CAP_CLEAR);
}
int keep_capability(cap_value_t cv) {
return change_capability(cv, CAP_SET);
}
bool ambient_capabilities_supported(void) {
static int cache = -1;
+1
View File
@@ -31,6 +31,7 @@ int capability_update_inherited_set(cap_t caps, uint64_t ambient_set);
int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities);
int drop_capability(cap_value_t cv);
int keep_capability(cap_value_t cv);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(cap_t, cap_free, NULL);
#define _cleanup_cap_free_ _cleanup_(cap_freep)