mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
landlock: Add UDP bind() access control
Add support for a first fine-grained UDP access right. LANDLOCK_ACCESS_NET_BIND_UDP controls the ability to set the local port of a UDP socket (via bind()). It will be useful for servers (to start receiving datagrams), and for some clients that need to use a specific source port (e.g. mDNS requires to use port 5353) For obvious performance concerns, access control is only enforced when configuring sockets, not when using them for common send/recv operations. Bump ABI to allow userspace to detect and use this new right. Signed-off-by: Matthieu Buffet <matthieu@buffet.re> Link: https://patch.msgid.link/20260611162107.49278-2-matthieu@buffet.re [mic: Fix comment formatting] Signed-off-by: Mickaël Salaün <mic@digikod.net>
This commit is contained in:
parent
0ce4243509
commit
9a8ed15ce2
|
|
@ -200,10 +200,10 @@ struct landlock_net_port_attr {
|
|||
* (also used for IPv6), and within that range, on a per-socket basis
|
||||
* with ``setsockopt(IP_LOCAL_PORT_RANGE)``.
|
||||
*
|
||||
* A Landlock rule with port 0 and the %LANDLOCK_ACCESS_NET_BIND_TCP
|
||||
* right means that requesting to bind on port 0 is allowed and it will
|
||||
* automatically translate to binding on a kernel-assigned ephemeral
|
||||
* port.
|
||||
* A Landlock rule with port 0 and the %LANDLOCK_ACCESS_NET_BIND_TCP or
|
||||
* %LANDLOCK_ACCESS_NET_BIND_UDP right means that requesting to bind on
|
||||
* port 0 is allowed and it will automatically translate to binding on a
|
||||
* kernel-assigned ephemeral port.
|
||||
*/
|
||||
__u64 port;
|
||||
};
|
||||
|
|
@ -373,10 +373,16 @@ struct landlock_net_port_attr {
|
|||
* port. Support added in Landlock ABI version 4.
|
||||
* - %LANDLOCK_ACCESS_NET_CONNECT_TCP: Connect TCP sockets to the given
|
||||
* remote port. Support added in Landlock ABI version 4.
|
||||
*
|
||||
* And similarly for UDP port numbers:
|
||||
*
|
||||
* - %LANDLOCK_ACCESS_NET_BIND_UDP: Bind UDP sockets to the given local
|
||||
* port. Support added in Landlock ABI version 10.
|
||||
*/
|
||||
/* clang-format off */
|
||||
#define LANDLOCK_ACCESS_NET_BIND_TCP (1ULL << 0)
|
||||
#define LANDLOCK_ACCESS_NET_CONNECT_TCP (1ULL << 1)
|
||||
#define LANDLOCK_ACCESS_NET_BIND_UDP (1ULL << 2)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ static_assert(ARRAY_SIZE(fs_access_strings) == LANDLOCK_NUM_ACCESS_FS);
|
|||
static const char *const net_access_strings[] = {
|
||||
[BIT_INDEX(LANDLOCK_ACCESS_NET_BIND_TCP)] = "net.bind_tcp",
|
||||
[BIT_INDEX(LANDLOCK_ACCESS_NET_CONNECT_TCP)] = "net.connect_tcp",
|
||||
[BIT_INDEX(LANDLOCK_ACCESS_NET_BIND_UDP)] = "net.bind_udp",
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(net_access_strings) == LANDLOCK_NUM_ACCESS_NET);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
|
||||
#define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS)
|
||||
|
||||
#define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_CONNECT_TCP
|
||||
#define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_BIND_UDP
|
||||
#define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1)
|
||||
#define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET)
|
||||
|
||||
|
|
|
|||
|
|
@ -88,15 +88,17 @@ static int current_check_access_socket(struct socket *const sock,
|
|||
* inconsistencies and return -EINVAL if needed.
|
||||
*/
|
||||
return 0;
|
||||
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) {
|
||||
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
|
||||
access_request == LANDLOCK_ACCESS_NET_BIND_UDP) {
|
||||
/*
|
||||
* Binding to an AF_UNSPEC address is treated
|
||||
* differently by IPv4 and IPv6 sockets. The socket's
|
||||
* family may change under our feet due to
|
||||
* setsockopt(IPV6_ADDRFORM), but that's ok: we either
|
||||
* reject entirely or require
|
||||
* %LANDLOCK_ACCESS_NET_BIND_TCP for the given port, so
|
||||
* it cannot be used to bypass the policy.
|
||||
* reject entirely for IPv6 or require
|
||||
* %LANDLOCK_ACCESS_NET_BIND_TCP or
|
||||
* %LANDLOCK_ACCESS_NET_BIND_UDP for IPv4, so it cannot
|
||||
* be used to bypass the policy.
|
||||
*
|
||||
* IPv4 sockets map AF_UNSPEC to AF_INET for
|
||||
* retrocompatibility for bind accesses, only if the
|
||||
|
|
@ -142,7 +144,8 @@ static int current_check_access_socket(struct socket *const sock,
|
|||
if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) {
|
||||
audit_net.dport = port;
|
||||
audit_net.v4info.daddr = addr4->sin_addr.s_addr;
|
||||
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) {
|
||||
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
|
||||
access_request == LANDLOCK_ACCESS_NET_BIND_UDP) {
|
||||
audit_net.sport = port;
|
||||
audit_net.v4info.saddr = addr4->sin_addr.s_addr;
|
||||
} else {
|
||||
|
|
@ -164,7 +167,8 @@ static int current_check_access_socket(struct socket *const sock,
|
|||
if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) {
|
||||
audit_net.dport = port;
|
||||
audit_net.v6info.daddr = addr6->sin6_addr;
|
||||
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) {
|
||||
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
|
||||
access_request == LANDLOCK_ACCESS_NET_BIND_UDP) {
|
||||
audit_net.sport = port;
|
||||
audit_net.v6info.saddr = addr6->sin6_addr;
|
||||
} else {
|
||||
|
|
@ -224,6 +228,8 @@ static int hook_socket_bind(struct socket *const sock,
|
|||
|
||||
if (sk_is_tcp(sock->sk))
|
||||
access_request = LANDLOCK_ACCESS_NET_BIND_TCP;
|
||||
else if (sk_is_udp(sock->sk))
|
||||
access_request = LANDLOCK_ACCESS_NET_BIND_UDP;
|
||||
else
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ static const struct file_operations ruleset_fops = {
|
|||
* If the change involves a fix that requires userspace awareness, also update
|
||||
* the errata documentation in Documentation/userspace-api/landlock.rst .
|
||||
*/
|
||||
const int landlock_abi_version = 9;
|
||||
const int landlock_abi_version = 10;
|
||||
|
||||
/**
|
||||
* sys_landlock_create_ruleset - Create a new ruleset
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ TEST(abi_version)
|
|||
const struct landlock_ruleset_attr ruleset_attr = {
|
||||
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
|
||||
};
|
||||
ASSERT_EQ(9, landlock_create_ruleset(NULL, 0,
|
||||
LANDLOCK_CREATE_RULESET_VERSION));
|
||||
ASSERT_EQ(10, landlock_create_ruleset(NULL, 0,
|
||||
LANDLOCK_CREATE_RULESET_VERSION));
|
||||
|
||||
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
|
||||
LANDLOCK_CREATE_RULESET_VERSION));
|
||||
|
|
|
|||
|
|
@ -1326,11 +1326,12 @@ FIXTURE_TEARDOWN(mini)
|
|||
|
||||
/* clang-format off */
|
||||
|
||||
#define ACCESS_LAST LANDLOCK_ACCESS_NET_CONNECT_TCP
|
||||
#define ACCESS_LAST LANDLOCK_ACCESS_NET_BIND_UDP
|
||||
|
||||
#define ACCESS_ALL ( \
|
||||
LANDLOCK_ACCESS_NET_BIND_TCP | \
|
||||
LANDLOCK_ACCESS_NET_CONNECT_TCP)
|
||||
LANDLOCK_ACCESS_NET_CONNECT_TCP | \
|
||||
LANDLOCK_ACCESS_NET_BIND_UDP)
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user