Compare commits

..

4 Commits

Author SHA1 Message Date
Torsten Hilbrich 7be830c6e8 nspawn: Allow Capability= to overrule private network setting
The commit:

a3fc6b55ac nspawn: mask out CAP_NET_ADMIN again if settings file turns off private networking

turned off the CAP_NET_ADMIN capability whenever no private networking
feature was enabled. This broke configurations where the CAP_NET_ADMIN
capability was explicitly requested in the configuration.

Changing the order of evalution here to allow the Capability= setting
to overrule this implicit setting:

Order of evaluation:

1. if no private network setting is enabled, CAP_NET_ADMIN is removed
2. if a private network setting is enabled, CAP_NET_ADMIN is added
3. the settings of Capability= are added
4. the settings of DropCapability= are removed

This allows the fix for #11755 to be retained and to still allow the
admin to specify CAP_NET_ADMIN as additional capability.

Fixes: a3fc6b55ac
Fixes: #13995
2019-11-15 10:13:51 +01:00
Zbigniew Jędrzejewski-Szmek 7edd8fb198 core: do not propagate polkit error to caller
If we fail to start polkit, we get a message like
"org.freedesktop.DBus.Error.NameHasNoOwner: Could not activate remote peer.",
which has no meaning for the caller of our StartUnit method. Let's just
return -EACCES.

$ systemctl start apache
Failed to start apache.service: Could not activate remote peer. (before)
Failed to start apache.service: Access denied                   (after)

Fixes #13865.
2019-11-15 08:17:01 +01:00
Lennart Poettering 4df8fe8415 seccomp: more comprehensive protection against libseccomp's __NR_xyz namespace invasion
A follow-up for 59b657296a, adding the
same conditioning for all cases of our __NR_xyz use.

Fixes: #14031
2019-11-15 08:13:36 +01:00
Tommy J 48daf51026 PrefixDelegationHint-section: typo 2019-11-15 07:57:32 +01:00
5 changed files with 23 additions and 19 deletions

View File

@ -1701,7 +1701,7 @@
<varlistentry> <varlistentry>
<term><varname>PrefixDelegationHint=</varname></term> <term><varname>PrefixDelegationHint=</varname></term>
<listitem> <listitem>
<para>Takes an IPv6 address with prefix length as <varname>Addresss=</varname> in <para>Takes an IPv6 address with prefix length as <varname>Address=</varname> in
the "[Network]" section. Specifies the DHCPv6 client for the requesting router to include the "[Network]" section. Specifies the DHCPv6 client for the requesting router to include
a prefix-hint in the DHCPv6 solicitation. Prefix ranges 1-128. Defaults to unset.</para> a prefix-hint in the DHCPv6 solicitation. Prefix ranges 1-128. Defaults to unset.</para>
</listitem> </listitem>

View File

@ -274,7 +274,7 @@ static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, c
#if !HAVE_KCMP #if !HAVE_KCMP
static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) { static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
# ifdef __NR_kcmp # if defined __NR_kcmp && __NR_kcmp > 0
return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
# else # else
errno = ENOSYS; errno = ENOSYS;
@ -289,7 +289,7 @@ static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long i
#if !HAVE_KEYCTL #if !HAVE_KEYCTL
static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) {
# ifdef __NR_keyctl # if defined __NR_keyctl && __NR_keyctl > 0
return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
# else # else
errno = ENOSYS; errno = ENOSYS;
@ -300,7 +300,7 @@ static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg
} }
static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) { static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
# ifdef __NR_add_key # if defined __NR_add_key && __NR_add_key > 0
return syscall(__NR_add_key, type, description, payload, plen, ringid); return syscall(__NR_add_key, type, description, payload, plen, ringid);
# else # else
errno = ENOSYS; errno = ENOSYS;
@ -311,7 +311,7 @@ static inline key_serial_t missing_add_key(const char *type, const char *descrip
} }
static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) { static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
# ifdef __NR_request_key # if defined __NR_request_key && __NR_request_key > 0
return syscall(__NR_request_key, type, description, callout_info, destringid); return syscall(__NR_request_key, type, description, callout_info, destringid);
# else # else
errno = ENOSYS; errno = ENOSYS;
@ -496,7 +496,7 @@ enum {
static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask, static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask,
unsigned long maxnode) { unsigned long maxnode) {
long i; long i;
# ifdef __NR_set_mempolicy # if defined __NR_set_mempolicy && __NR_set_mempolicy > 0
i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode); i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode);
# else # else
errno = ENOSYS; errno = ENOSYS;

View File

@ -3770,6 +3770,7 @@ static int merge_settings(Settings *settings, const char *path) {
if ((arg_settings_mask & SETTING_CAPABILITY) == 0) { if ((arg_settings_mask & SETTING_CAPABILITY) == 0) {
uint64_t plus, minus; uint64_t plus, minus;
uint64_t network_minus = 0;
/* Note that we copy both the simple plus/minus caps here, and the full quintet from the /* Note that we copy both the simple plus/minus caps here, and the full quintet from the
* Settings structure */ * Settings structure */
@ -3781,14 +3782,16 @@ static int merge_settings(Settings *settings, const char *path) {
if (settings_private_network(settings)) if (settings_private_network(settings))
plus |= UINT64_C(1) << CAP_NET_ADMIN; plus |= UINT64_C(1) << CAP_NET_ADMIN;
else else
minus |= UINT64_C(1) << CAP_NET_ADMIN; network_minus |= UINT64_C(1) << CAP_NET_ADMIN;
} }
if (!arg_settings_trusted && plus != 0) { if (!arg_settings_trusted && plus != 0) {
if (settings->capability != 0) if (settings->capability != 0)
log_warning("Ignoring Capability= setting, file %s is not trusted.", path); log_warning("Ignoring Capability= setting, file %s is not trusted.", path);
} else } else {
arg_caps_retain &= ~network_minus;
arg_caps_retain |= plus; arg_caps_retain |= plus;
}
arg_caps_retain &= ~minus; arg_caps_retain &= ~minus;

View File

@ -411,7 +411,8 @@ int bus_verify_polkit_async(
e = sd_bus_message_get_error(q->reply); e = sd_bus_message_get_error(q->reply);
/* Treat no PK available as access denied */ /* Treat no PK available as access denied */
if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER))
return -EACCES; return -EACCES;
/* Copy error from polkit reply */ /* Copy error from polkit reply */
@ -422,7 +423,6 @@ int bus_verify_polkit_async(
r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}"); r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
if (r >= 0) if (r >= 0)
r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge); r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -28,7 +28,8 @@
#include "tmpfile-util.h" #include "tmpfile-util.h"
#include "virt.h" #include "virt.h"
#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) /* __NR_socket may be invalid due to libseccomp */
#if !defined(__NR_socket) || __NR_socket <= 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__)
/* On these archs, socket() is implemented via the socketcall() syscall multiplexer, /* On these archs, socket() is implemented via the socketcall() syscall multiplexer,
* and we can't restrict it hence via seccomp. */ * and we can't restrict it hence via seccomp. */
# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1 # define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
@ -304,14 +305,14 @@ static void test_protect_sysctl(void) {
assert_se(pid >= 0); assert_se(pid >= 0);
if (pid == 0) { if (pid == 0) {
#if __NR__sysctl > 0 #if defined __NR__sysctl && __NR__sysctl > 0
assert_se(syscall(__NR__sysctl, NULL) < 0); assert_se(syscall(__NR__sysctl, NULL) < 0);
assert_se(errno == EFAULT); assert_se(errno == EFAULT);
#endif #endif
assert_se(seccomp_protect_sysctl() >= 0); assert_se(seccomp_protect_sysctl() >= 0);
#if __NR__sysctl > 0 #if defined __NR__sysctl && __NR__sysctl > 0
assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0); assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0);
assert_se(errno == EPERM); assert_se(errno == EPERM);
#endif #endif
@ -640,7 +641,7 @@ static void test_load_syscall_filter_set_raw(void) {
assert_se(poll(NULL, 0, 0) == 0); assert_se(poll(NULL, 0, 0) == 0);
assert_se(s = hashmap_new(NULL)); assert_se(s = hashmap_new(NULL));
#if SCMP_SYS(access) >= 0 #if defined __NR_access && __NR_access > 0
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0);
#else #else
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0);
@ -656,7 +657,7 @@ static void test_load_syscall_filter_set_raw(void) {
s = hashmap_free(s); s = hashmap_free(s);
assert_se(s = hashmap_new(NULL)); assert_se(s = hashmap_new(NULL));
#if SCMP_SYS(access) >= 0 #if defined __NR_access && __NR_access > 0
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(EILSEQ)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(EILSEQ)) >= 0);
#else #else
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0);
@ -672,7 +673,7 @@ static void test_load_syscall_filter_set_raw(void) {
s = hashmap_free(s); s = hashmap_free(s);
assert_se(s = hashmap_new(NULL)); assert_se(s = hashmap_new(NULL));
#if SCMP_SYS(poll) >= 0 #if defined __NR_poll && __NR_poll > 0
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(-1)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(-1)) >= 0);
#else #else
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0);
@ -689,7 +690,7 @@ static void test_load_syscall_filter_set_raw(void) {
s = hashmap_free(s); s = hashmap_free(s);
assert_se(s = hashmap_new(NULL)); assert_se(s = hashmap_new(NULL));
#if SCMP_SYS(poll) >= 0 #if defined __NR_poll && __NR_poll > 0
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(EILSEQ)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(EILSEQ)) >= 0);
#else #else
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0); assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0);
@ -767,8 +768,8 @@ static int real_open(const char *path, int flags, mode_t mode) {
* testing purposes that calls the real syscall, on architectures where SYS_open is defined. On * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On
* other architectures, let's just fall back to the glibc call. */ * other architectures, let's just fall back to the glibc call. */
#ifdef SYS_open #if defined __NR_open && __NR_open > 0
return (int) syscall(SYS_open, path, flags, mode); return (int) syscall(__NR_open, path, flags, mode);
#else #else
return open(path, flags, mode); return open(path, flags, mode);
#endif #endif