From cb4b36928a3bae9abe614260f1bd1ef7ab7ff30d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 20 Nov 2025 09:39:32 +0900 Subject: [PATCH 1/2] socket-label: move prototype of socket_address_listen() and string table for SocketAddressBindIPv6Only The function socket_address_listen() is declared at shared/socket-label.c, however its prototype was in basic/socket-util.h. This moves the prototype to shared/socket-label.h. Also, enum SocketAddressBindIPv6Only is not used anymore in basic/*.[ch]. Let's move the definition and its string table to shared/socket-label.[ch]. Follow-up for b25a930f0e2ebe77bc8b0f0acfac8a3b27ef1f0a. --- src/basic/socket-util.c | 20 -------------------- src/basic/socket-util.h | 25 ------------------------- src/core/socket.h | 1 + src/shared/socket-label.c | 31 +++++++++++++++++++++++++++---- src/shared/socket-label.h | 29 +++++++++++++++++++++++++++++ src/shared/socket-netlink.c | 1 + src/test/test-tables.c | 1 + 7 files changed, 59 insertions(+), 49 deletions(-) create mode 100644 src/shared/socket-label.h diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 568072a492..c98cd35d54 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -669,26 +669,6 @@ static const char* const netlink_family_table[] = { DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX); -static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = { - [SOCKET_ADDRESS_DEFAULT] = "default", - [SOCKET_ADDRESS_BOTH] = "both", - [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only" -}; - -DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); - -SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) { - int r; - - r = parse_boolean(n); - if (r > 0) - return SOCKET_ADDRESS_IPV6_ONLY; - if (r == 0) - return SOCKET_ADDRESS_BOTH; - - return socket_address_bind_ipv6_only_from_string(n); -} - bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) { assert(a); assert(b); diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 6e937ffee9..b8cb834131 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -53,14 +53,6 @@ typedef struct SocketAddress { int protocol; } SocketAddress; -typedef enum SocketAddressBindIPv6Only { - SOCKET_ADDRESS_DEFAULT, - SOCKET_ADDRESS_BOTH, - SOCKET_ADDRESS_IPV6_ONLY, - _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX, - _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -EINVAL, -} SocketAddressBindIPv6Only; - #define socket_address_family(a) ((a)->sockaddr.sa.sa_family) const char* socket_address_type_to_string(int t) _const_; @@ -74,19 +66,6 @@ static inline int socket_address_unlink(const SocketAddress *a) { bool socket_address_can_accept(const SocketAddress *a) _pure_; -int socket_address_listen( - const SocketAddress *a, - int flags, - int backlog, - SocketAddressBindIPv6Only only, - const char *bind_to_device, - bool reuse_port, - bool free_bind, - bool transparent, - mode_t directory_mode, - mode_t socket_mode, - const char *label); - int socket_address_verify(const SocketAddress *a, bool strict) _pure_; int socket_address_print(const SocketAddress *a, char **p); bool socket_address_matches_fd(const SocketAddress *a, int fd); @@ -108,10 +87,6 @@ int getsockname_pretty(int fd, char **ret); int socknameinfo_pretty(const struct sockaddr *sa, socklen_t salen, char **_ret); -const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_; -SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_; -SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s); - int netlink_family_to_string_alloc(int b, char **s); int netlink_family_from_string(const char *s) _pure_; diff --git a/src/core/socket.h b/src/core/socket.h index cec10dece9..74356e2325 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -6,6 +6,7 @@ #include "execute.h" #include "list.h" #include "pidref.h" +#include "socket-label.h" #include "socket-util.h" #include "unit.h" diff --git a/src/shared/socket-label.c b/src/shared/socket-label.c index 0e41f2674e..ad64f4f63d 100644 --- a/src/shared/socket-label.c +++ b/src/shared/socket-label.c @@ -8,10 +8,33 @@ #include "fs-util.h" #include "log.h" #include "mkdir-label.h" +#include "parse-util.h" #include "selinux-util.h" +#include "socket-label.h" #include "socket-util.h" +#include "string-table.h" #include "umask-util.h" +static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = { + [SOCKET_ADDRESS_DEFAULT] = "default", + [SOCKET_ADDRESS_BOTH] = "both", + [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only" +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); + +SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) { + int r; + + r = parse_boolean(n); + if (r > 0) + return SOCKET_ADDRESS_IPV6_ONLY; + if (r == 0) + return SOCKET_ADDRESS_BOTH; + + return socket_address_bind_ipv6_only_from_string(n); +} + int socket_address_listen( const SocketAddress *a, int flags, @@ -23,7 +46,7 @@ int socket_address_listen( bool transparent, mode_t directory_mode, mode_t socket_mode, - const char *label) { + const char *selinux_label) { _cleanup_close_ int fd = -EBADF; const char *p; @@ -38,15 +61,15 @@ int socket_address_listen( if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported()) return -EAFNOSUPPORT; - if (label) { - r = mac_selinux_create_socket_prepare(label); + if (selinux_label) { + r = mac_selinux_create_socket_prepare(selinux_label); if (r < 0) return r; } fd = RET_NERRNO(socket(socket_address_family(a), a->type | flags, a->protocol)); - if (label) + if (selinux_label) mac_selinux_create_socket_clear(); if (fd < 0) diff --git a/src/shared/socket-label.h b/src/shared/socket-label.h new file mode 100644 index 0000000000..8d882cb4e2 --- /dev/null +++ b/src/shared/socket-label.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "shared-forward.h" + +typedef enum SocketAddressBindIPv6Only { + SOCKET_ADDRESS_DEFAULT, + SOCKET_ADDRESS_BOTH, + SOCKET_ADDRESS_IPV6_ONLY, + _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX, + _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -EINVAL, +} SocketAddressBindIPv6Only; + +const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_; +SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_; +SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s); + +int socket_address_listen( + const SocketAddress *a, + int flags, + int backlog, + SocketAddressBindIPv6Only only, + const char *bind_to_device, + bool reuse_port, + bool free_bind, + bool transparent, + mode_t directory_mode, + mode_t socket_mode, + const char *selinux_label); diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c index 771bf2f799..060388685f 100644 --- a/src/shared/socket-netlink.c +++ b/src/shared/socket-netlink.c @@ -15,6 +15,7 @@ #include "netlink-sock-diag.h" #include "netlink-util.h" #include "parse-util.h" +#include "socket-label.h" #include "socket-netlink.h" #include "socket-util.h" #include "string-util.h" diff --git a/src/test/test-tables.c b/src/test/test-tables.c index 41b6cd6136..95ceb0e5ae 100644 --- a/src/test/test-tables.c +++ b/src/test/test-tables.c @@ -29,6 +29,7 @@ #include "service.h" #include "show-status.h" #include "socket.h" +#include "socket-label.h" #include "socket-util.h" #include "swap.h" #include "test-tables.h" From 360f750b01eb713dcf40ac5c3d963b0a6b398e2f Mon Sep 17 00:00:00 2001 From: Marc-Antoine Riou Date: Thu, 6 Nov 2025 10:21:12 +0000 Subject: [PATCH 2/2] socket-label: apply SMACK label to socket and its file descriptor When a socket unit specifies SmackLabel=, the label was previously not applied to the underlying Unix socket file or its file descriptor. This change ensures that the SMACK label is applied both to the socket path on the filesystem and to the opened socket FD. --- src/core/socket.c | 5 +++-- src/shared/socket-label.c | 15 ++++++++++++++- src/shared/socket-label.h | 3 ++- src/shared/socket-netlink.c | 14 ++++++++++++-- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/core/socket.c b/src/core/socket.c index c8e737eaa7..3bb0149e62 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1504,7 +1504,7 @@ static int socket_determine_selinux_label(Socket *s, char **ret) { static int socket_address_listen_do( Socket *s, const SocketAddress *address, - const char *label) { + const char *selinux_label) { assert(s); assert(address); @@ -1520,7 +1520,8 @@ static int socket_address_listen_do( s->transparent, s->directory_mode, s->socket_mode, - label); + selinux_label, + s->smack); } #define log_address_error_errno(u, address, error, fmt) \ diff --git a/src/shared/socket-label.c b/src/shared/socket-label.c index ad64f4f63d..e16f9537a6 100644 --- a/src/shared/socket-label.c +++ b/src/shared/socket-label.c @@ -10,6 +10,7 @@ #include "mkdir-label.h" #include "parse-util.h" #include "selinux-util.h" +#include "smack-util.h" #include "socket-label.h" #include "socket-util.h" #include "string-table.h" @@ -46,7 +47,8 @@ int socket_address_listen( bool transparent, mode_t directory_mode, mode_t socket_mode, - const char *selinux_label) { + const char *selinux_label, + const char *smack_label) { _cleanup_close_ int fd = -EBADF; const char *p; @@ -75,6 +77,12 @@ int socket_address_listen( if (fd < 0) return fd; + if (smack_label) { + r = mac_smack_apply_fd(fd, SMACK_ATTR_ACCESS, smack_label); + if (r < 0) + log_warning_errno(r, "Failed to apply SMACK label for socket FD, ignoring: %m"); + } + if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) { r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, only == SOCKET_ADDRESS_IPV6_ONLY); if (r < 0) @@ -130,6 +138,11 @@ int socket_address_listen( if (r < 0) return r; } + if (smack_label) { + r = mac_smack_apply(p, SMACK_ATTR_ACCESS, smack_label); + if (r < 0) + log_warning_errno(r, "Failed to apply SMACK label for socket path, ignoring: %m"); + } } else { if (bind(fd, &a->sockaddr.sa, a->size) < 0) return -errno; diff --git a/src/shared/socket-label.h b/src/shared/socket-label.h index 8d882cb4e2..cfcb20f187 100644 --- a/src/shared/socket-label.h +++ b/src/shared/socket-label.h @@ -26,4 +26,5 @@ int socket_address_listen( bool transparent, mode_t directory_mode, mode_t socket_mode, - const char *selinux_label); + const char *selinux_label, + const char *smack_label); diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c index 060388685f..885606b6e0 100644 --- a/src/shared/socket-netlink.c +++ b/src/shared/socket-netlink.c @@ -184,8 +184,18 @@ int make_socket_fd(int log_level, const char* address, int type, int flags) { a.type = type; - fd = socket_address_listen(&a, type | flags, SOMAXCONN_DELUXE, SOCKET_ADDRESS_DEFAULT, - NULL, false, false, false, 0755, 0644, NULL); + fd = socket_address_listen( + &a, + type | flags, + SOMAXCONN_DELUXE, SOCKET_ADDRESS_DEFAULT, + /* bind_to_device= */ NULL, + /* reuse_port= */ false, + /* free_bind= */ false, + /* transparent= */ false, + 0755, + 0644, + /* selinux_label= */ NULL, + /* smack_label= */ NULL); if (fd < 0 || log_get_max_level() >= log_level) { _cleanup_free_ char *p = NULL;