From: Simon Horman <horms@kernel.org>
To: "Ricardo Cañuelo Navarro" <rcn@igalia.com>
Cc: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
Xin Long <lucien.xin@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
kernel-dev@igalia.com, linux-sctp@vger.kernel.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: Re: [PATCH] sctp: check transport existence before processing a send primitive
Date: Wed, 2 Apr 2025 14:21:41 +0100 [thread overview]
Message-ID: <20250402132141.GO214849@horms.kernel.org> (raw)
In-Reply-To: <20250402-kasan_slab-use-after-free_read_in_sctp_outq_select_transport-v1-1-da6f5f00f286@igalia.com>
On Wed, Apr 02, 2025 at 12:25:36PM +0200, Ricardo Cañuelo Navarro wrote:
> sctp_sendmsg() re-uses associations and transports when possible by
> doing a lookup based on the socket endpoint and the message destination
> address, and then sctp_sendmsg_to_asoc() sets the selected transport in
> all the message chunks to be sent.
>
> There's a possible race condition if another thread triggers the removal
> of that selected transport, for instance, by explicitly unbinding an
> address with setsockopt(SCTP_SOCKOPT_BINDX_REM), after the chunks have
> been set up and before the message is sent. This causes the access to
> the transport data in sctp_outq_select_transport(), when the association
> outqueue is flushed, to do a use-after-free read.
>
> This patch addresses this scenario by checking if the transport still
> exists right after the chunks to be sent are set up to use it and before
> proceeding to sending them. If the transport was freed since it was
> found, the send is aborted. The reason to add the check here is that
> once the transport is assigned to the chunks, deleting that transport
> is safe, since it will also set chunk->transport to NULL in the affected
> chunks. This scenario is correctly handled already, see Fixes below.
>
> The bug was found by a private syzbot instance (see the error report [1]
> and the C reproducer that triggers it [2]).
>
> Link: https://people.igalia.com/rcn/kernel_logs/20250402__KASAN_slab-use-after-free_Read_in_sctp_outq_select_transport.txt [1]
> Link: https://people.igalia.com/rcn/kernel_logs/20250402__KASAN_slab-use-after-free_Read_in_sctp_outq_select_transport__repro.c [2]
> Cc: stable@vger.kernel.org
> Fixes: df132eff4638 ("sctp: clear the transport of some out_chunk_list chunks in sctp_assoc_rm_peer")
> Signed-off-by: Ricardo Cañuelo Navarro <rcn@igalia.com>
> ---
> net/sctp/socket.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 36ee34f483d703ffcfe5ca9e6cc554fba24c75ef..9c5ff44fa73cae6a6a04790800cc33dfa08a8da9 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -1787,17 +1787,24 @@ static int sctp_sendmsg_check_sflags(struct sctp_association *asoc,
> return 1;
> }
>
> +static union sctp_addr *sctp_sendmsg_get_daddr(struct sock *sk,
> + const struct msghdr *msg,
> + struct sctp_cmsgs *cmsgs);
> +
> static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
> struct msghdr *msg, size_t msg_len,
> struct sctp_transport *transport,
> struct sctp_sndrcvinfo *sinfo)
> {
> + struct sctp_transport *aux_transport = NULL;
> struct sock *sk = asoc->base.sk;
> + struct sctp_endpoint *ep = sctp_sk(sk)->ep;
> struct sctp_sock *sp = sctp_sk(sk);
> struct net *net = sock_net(sk);
> struct sctp_datamsg *datamsg;
> bool wait_connect = false;
> struct sctp_chunk *chunk;
> + union sctp_addr *daddr;
> long timeo;
> int err;
>
> @@ -1869,6 +1876,15 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
> sctp_set_owner_w(chunk);
> chunk->transport = transport;
> }
> + /* Fail if transport was deleted after lookup in sctp_sendmsg() */
> + daddr = sctp_sendmsg_get_daddr(sk, msg, NULL);
> + if (daddr) {
> + sctp_endpoint_lookup_assoc(ep, daddr, &aux_transport);
> + if (!aux_transport || aux_transport != transport) {
> + sctp_datamsg_free(datamsg);
> + goto err;
Hi Ricardo,
This is not a full review, and I would suggest waiting for one from others.
But this will result in the local variable err being used uninitialised.
Flagged by Smatch.
> + }
> + }
>
> err = sctp_primitive_SEND(net, asoc, datamsg);
> if (err) {
--
pw-bot: changes-requested
next prev parent reply other threads:[~2025-04-02 13:21 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-02 10:25 [PATCH] sctp: check transport existence before processing a send primitive Ricardo Cañuelo Navarro
2025-04-02 13:21 ` Simon Horman [this message]
2025-04-02 13:37 ` Ricardo Cañuelo Navarro
2025-04-02 14:03 ` Ricardo Cañuelo Navarro
2025-04-02 19:40 ` Xin Long
2025-04-03 9:58 ` Ricardo Cañuelo Navarro
2025-04-03 14:42 ` Xin Long
2025-04-03 18:44 ` Xin Long
2025-04-04 10:04 ` Ricardo Cañuelo Navarro
2025-04-04 14:22 ` Xin Long
2025-04-07 7:37 ` Ricardo Cañuelo Navarro
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=20250402132141.GO214849@horms.kernel.org \
--to=horms@kernel.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kernel-dev@igalia.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sctp@vger.kernel.org \
--cc=lucien.xin@gmail.com \
--cc=marcelo.leitner@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rcn@igalia.com \
--cc=stable@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).