All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
Cc: linux-security-module@vger.kernel.org
Subject: Re: [PATCH v4 2/7] landlock: Add UDP connect() access control
Date: Fri, 30 Oct 2026 04:53:46 +0000	[thread overview]
Message-ID: <sashiko-outbox-190350@kernel.org> (raw)
In-Reply-To: <20260502124306.3975990-3-matthieu@buffet.re>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] TOCTOU race condition allows bypassing the LANDLOCK_ACCESS_NET_BIND_UDP restriction for autobinding ephemeral ports.
- [High] Spurious access denial when calling connect(AF_UNSPEC) on an unbound UDP socket.
- [Medium] Unmarked data races when reading `inet_sk(sock->sk)->inet_num` and `sock->sk->__sk_common.skc_family`.
--

commit 80ae13b5d76df96979bf826e8fb592eacdf098bc
Author: Matthieu Buffet <matthieu@buffet.re>

landlock: Add UDP connect() access control

This commit adds support for a second fine-grained UDP access right
LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP. It controls the ability to set the
remote port of a UDP socket via connect(), and includes detection of
when autobind is about to be required.

> diff --git a/security/landlock/net.c b/security/landlock/net.c
> index f9ccb52e7d45..045881f81295 100644
> --- a/security/landlock/net.c
> +++ b/security/landlock/net.c

[ ... ]

> @@ -213,6 +216,50 @@ static int current_check_access_socket(struct socket *const sock,
>  	return -EACCES;
>  }
>  
> +static int current_check_autobind_udp_socket(struct socket *const sock)
> +{
> +	struct sockaddr_storage port0 = { 0 };
> +
> +	/*
> +	 * On UDP sockets, if a local port has not already been bound,
> +	 * calling connect() or sending a first datagram has the side
> +	 * effect of autobinding an ephemeral port: we also have to check
> +	 * that the process would have had the right to bind(0) explicitly.
> +	 * Note: socket is not locked, so another thread could do an
> +	 * explicit bind(!=0) on this socket, changing inet_num to non-zero
> +	 * after we read it, but this would only have us enforce an
> +	 * additional bind(0) access check and would not bypass policy.
> +	 */
> +	if (inet_sk(sock->sk)->inet_num != 0)
> +		return 0;

Are unmarked lockless reads of inet_num safe here?

Since the socket is not locked, inet_num can be modified concurrently by
another thread calling bind(), as noted in the comment. Should this read
use READ_ONCE() or data_race() to avoid KCSAN warnings about data races
under the Linux Kernel Memory Model?

This also applies to the lockless read of skc_family below, which can be
concurrently modified by setsockopt(IPV6_ADDRFORM).

Can a TOCTOU race bypass the autobind check?

If a process has an already autobound UDP socket (which lacks
SOCK_BINDPORT_LOCK), what happens if Thread A and Thread B race:

Thread A calls connect(remote_addr). The hook
current_check_autobind_udp_socket() checks inet_num != 0 locklessly,
assumes it is already bound, and skips the BIND_UDP check.

Thread B calls connect(AF_UNSPEC). The Landlock hook explicitly allows this.
The network stack executes udp_disconnect(), which unhashes the socket and
zeroes inet_num.

Thread A proceeds into the network stack (inet_dgram_connect), acquires the
socket lock, observes inet_num == 0, and calls inet_autobind().

Does this allow the socket to successfully bind to a new ephemeral port without
the required BIND_UDP Landlock access check?

> +
> +	/*
> +	 * Construct a struct sockaddr* with port 0 to pretend the
> +	 * process tried to bind() on that address.
> +	 */
> +	port0.ss_family = sock->sk->__sk_common.skc_family;

[ ... ]

> @@ -234,14 +281,22 @@ static int hook_socket_connect(struct socket *const sock,
>  			       const int addrlen)
>  {
>  	access_mask_t access_request;
> +	int ret = 0;
>  
>  	if (sk_is_tcp(sock->sk))
>  		access_request = LANDLOCK_ACCESS_NET_CONNECT_TCP;
> +	else if (sk_is_udp(sock->sk))
> +		access_request = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP;
>  	else
>  		return 0;
>  
> -	return current_check_access_socket(sock, address, addrlen,
> -					   access_request);
> +	ret = current_check_access_socket(sock, address, addrlen,
> +					  access_request);
> +
> +	if (ret == 0 && sk_is_udp(sock->sk))
> +		ret = current_check_autobind_udp_socket(sock);

Can this unconditionally enforce the bind check for connect(AF_UNSPEC) on
unbound sockets?

If connect(AF_UNSPEC) is called on an unbound UDP socket,
current_check_access_socket() explicitly permits it and returns 0.

However, the hook then unconditionally calls current_check_autobind_udp_socket().
Because the socket is unbound (inet_num == 0), it enforces the BIND_UDP
policy for port 0.

If the process does not have BIND_UDP access, the disconnect operation is denied
with -EACCES. But in the network stack, connect(AF_UNSPEC) merely dissolves
the remote association (udp_disconnect) and never triggers inet_autobind().

Will enforcing a bind check here break legitimate application cleanup behavior?

> +
> +	return ret;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260502124306.3975990-1-matthieu@buffet.re?part=2

  parent reply	other threads:[~2026-10-30  4:53 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-02 12:42 [PATCH v4 0/7] landlock: Add UDP access control support Matthieu Buffet
2026-05-02 12:43 ` [PATCH v4 1/7] landlock: Add UDP bind() access control Matthieu Buffet
2026-10-30  4:53   ` sashiko-bot
2026-05-02 12:43 ` [PATCH v4 2/7] landlock: Add UDP connect() " Matthieu Buffet
2026-05-22 21:10   ` Mickaël Salaün
2026-06-06 17:11     ` Matthieu Buffet
2026-06-09 21:15       ` [PATCH 1/2] landlock: Fix unmarked concurrent access to socket family Matthieu Buffet
2026-06-09 21:15         ` [PATCH 2/2] landlock: replace __sk_common struct sock field accesses Matthieu Buffet
2026-06-10 13:41           ` Mickaël Salaün
2026-06-10 13:48             ` Mickaël Salaün
2026-05-22 21:18   ` [PATCH v4 2/7] landlock: Add UDP connect() access control Mickaël Salaün
2026-06-06 17:04     ` Matthieu Buffet
2026-10-30  4:53   ` sashiko-bot [this message]
2026-05-02 12:43 ` [PATCH v4 3/7] landlock: Add UDP send " Matthieu Buffet
2026-05-22 21:10   ` Mickaël Salaün
2026-10-30  4:53   ` sashiko-bot
2026-05-02 12:43 ` [PATCH v4 4/7] selftests/landlock: Add UDP bind/connect tests Matthieu Buffet
2026-10-30  4:53   ` sashiko-bot
2026-05-02 12:43 ` [PATCH v4 5/7] selftests/landlock: Add tests for sendmsg() Matthieu Buffet
2026-10-30  4:53   ` sashiko-bot
2026-05-02 12:43 ` [PATCH v4 6/7] samples/landlock: Add sandboxer UDP access control Matthieu Buffet
2026-05-02 12:43 ` [PATCH v4 7/7] landlock: Add documentation for UDP support Matthieu Buffet
2026-05-22 21:11   ` Mickaël Salaün
2026-05-06 15:33 ` [PATCH v4 0/7] landlock: Add UDP access control support Günther Noack
2026-05-07 22:11   ` Matthieu Buffet
2026-05-22 21:08 ` Mickaël Salaün
2026-06-06 17:01   ` Matthieu Buffet
2026-06-10 13:44     ` Mickaël Salaün
2026-05-25 20:28 ` Mickaël Salaün
2026-06-11  0:27   ` Matthieu Buffet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-190350@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.