diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 8079b4b210..bb38ea2467 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -1508,40 +1508,29 @@
RestrictAddressFamilies=
- Restricts the set of socket address families
- accessible to the processes of this unit. Takes a
- space-separated list of address family names to whitelist,
- such as
- AF_UNIX,
- AF_INET or
- AF_INET6. When
- prefixed with ~ the listed address
- families will be applied as blacklist, otherwise as whitelist.
- Note that this restricts access to the
- socket2
- system call only. Sockets passed into the process by other
- means (for example, by using socket activation with socket
- units, see
- systemd.socket5)
- are unaffected. Also, sockets created with
- socketpair() (which creates connected
- AF_UNIX sockets only) are unaffected. Note that this option
- has no effect on 32-bit x86 and is ignored (but works
- correctly on x86-64). If running in user mode, or in system
- mode, but without the CAP_SYS_ADMIN
- capability (e.g. setting User=nobody),
- NoNewPrivileges=yes is implied. By
- default, no restriction applies, all address families are
- accessible to processes. If assigned the empty string, any
- previous list changes are undone.
+ Restricts the set of socket address families accessible to the processes of this unit. Takes a
+ space-separated list of address family names to whitelist, such as AF_UNIX,
+ AF_INET or AF_INET6. When prefixed with ~ the
+ listed address families will be applied as blacklist, otherwise as whitelist. Note that this restricts access
+ to the socket2 system call
+ only. Sockets passed into the process by other means (for example, by using socket activation with socket
+ units, see systemd.socket5)
+ are unaffected. Also, sockets created with socketpair() (which creates connected AF_UNIX
+ sockets only) are unaffected. Note that this option has no effect on 32-bit x86, s390, s390x, mips, mips-le,
+ ppc, ppc-le, pcc64, ppc64-le and is ignored (but works correctly on other architectures, including x86-64). If
+ running in user mode, or in system mode, but without the CAP_SYS_ADMIN capability
+ (e.g. setting User=nobody), NoNewPrivileges=yes is implied. By default,
+ no restrictions apply, all address families are accessible to processes. If assigned the empty string, any
+ previous address familiy restriction changes are undone. This setting does not affect commands prefixed with
+ +.
- Use this option to limit exposure of processes to remote
- systems, in particular via exotic network protocols. Note that
- in most cases, the local AF_UNIX address
- family should be included in the configured whitelist as it is
- frequently used for local communication, including for
+ Use this option to limit exposure of processes to remote access, in particular via exotic and sensitive
+ network protocols, such as AF_PACKET. Note that in most cases, the local
+ AF_UNIX address family should be included in the configured whitelist as it is frequently
+ used for local communication, including for
syslog2
- logging. This does not affect commands prefixed with +.
+ logging.
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index bd9c0aac60..609e0619af 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -873,6 +873,8 @@ int seccomp_protect_sysctl(void) {
}
int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
+
+#if !SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
uint32_t arch;
int r;
@@ -1001,6 +1003,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
if (r < 0)
log_debug_errno(r, "Failed to install socket family rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
}
+#endif
return 0;
}
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index 4438e87fa6..2563fcd38a 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -76,6 +76,14 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist);
int seccomp_restrict_realtime(void);
int seccomp_memory_deny_write_execute(void);
+#if defined(__i386__) || defined(__s390x__) || defined(__s390__) || defined(__powerpc64__) || defined(__powerpc__) || defined (__mips__)
+/* On these archs, socket() is implemented via the socketcall() syscall multiplexer, and we can't restrict it hence via
+ * seccomp */
+#define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
+#else
+#define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
+#endif
+
extern const uint32_t seccomp_local_archs[];
#define SECCOMP_FOREACH_LOCAL_ARCH(arch) \
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
index 6f15879c45..54e7947c2f 100644
--- a/src/test/test-seccomp.c
+++ b/src/test/test-seccomp.c
@@ -283,8 +283,14 @@ static void test_restrict_address_families(void) {
assert_se(fd >= 0);
safe_close(fd);
+#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ assert_se(fd >= 0);
+ safe_close(fd);
+#else
assert_se(socket(AF_UNIX, SOCK_DGRAM, 0) < 0);
assert_se(errno == EAFNOSUPPORT);
+#endif
fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
assert_se(fd >= 0);
@@ -300,11 +306,21 @@ static void test_restrict_address_families(void) {
assert_se(fd >= 0);
safe_close(fd);
+#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ assert_se(fd >= 0);
+ safe_close(fd);
+
+ fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
+ assert_se(fd >= 0);
+ safe_close(fd);
+#else
assert_se(socket(AF_UNIX, SOCK_DGRAM, 0) < 0);
assert_se(errno == EAFNOSUPPORT);
assert_se(socket(AF_NETLINK, SOCK_DGRAM, 0) < 0);
assert_se(errno == EAFNOSUPPORT);
+#endif
_exit(EXIT_SUCCESS);
}