All of lore.kernel.org
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: dhowells@redhat.com
Cc: netdev@vger.kernel.org, marc.dionne@auristor.com,
	kuba@kernel.org, davem@davemloft.net, edumazet@google.com,
	pabeni@redhat.com, horms@kernel.org,
	linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org,
	nicoyip.dev@gmail.com, stable@vger.kernel.org
Subject: Re: [PATCH net v9 13/14] rxrpc: fix use-after-free in rxrpc_poke_conn()
Date: Tue, 08 Sep 2026 20:49:50 +0000	[thread overview]
Message-ID: <178890059047.219967.10164675967516707934@kernel.org> (raw)
In-Reply-To: <20260907113743.1453210-14-dhowells@redhat.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:

Critical: 0 · High: 0 (1) · Medium: 0 · Low: 1

- [Low] Commit message mischaracterizes the applied fix: it claims to
  guard rxrpc_poke_conn() "with the same liveness/refcount check the…

Pre-existing issues:
- [High] Residual poke-reference leak after the rxrpc I/O thread exits:
  rxrpc_poke_conn() (net/rxrpc/conn_object.c:34-44) still takes a poke…

--

rxrpc: fix use-after-free in rxrpc_poke_conn()

This changes rxrpc_poke_conn() to take the poke reference with
rxrpc_get_connection_maybe() instead of rxrpc_get_connection(), returning
early if the refcount is already zero.  The intent is to stop a connection
being linked into local->conn_attend_q after it has started teardown.

No Link: tags in the commit header.

Two questions below, one about the changelog wording and one about a
pre-existing lifetime issue that this hunk touches.

> Guard rxrpc_poke_conn() with the same liveness/refcount check the sibling
> rxrpc_queue_conn() uses before taking the poke reference, so a connection
> past its last-active point is not poked/requeued after teardown began.

[Severity: Low]
Is this description of the applied change accurate?  rxrpc_queue_conn()
gates on the active count and takes no reference at all:

net/rxrpc/conn_object.c:rxrpc_queue_conn() {
	if (atomic_read(&conn->active) >= 0 &&
	    rxrpc_queue_work(&conn->processor))
		rxrpc_see_connection(conn, why);
}

and rxrpc_see_connection() only does refcount_read() plus a tracepoint.
The patch instead adds a refcount gate
(rxrpc_get_connection_maybe() is __refcount_inc_not_zero()), which is a
different liveness signal.

Also, does the code achieve "a connection past its last-active point is not
poked/requeued"?  rxrpc_service_connection_reaper() sets active to -1 while
the refcount is still non-zero:

net/rxrpc/conn_object.c:rxrpc_service_connection_reaper() {
	...
		active = 0;
		if (!atomic_try_cmpxchg(&conn->active, &active, -1))
			continue;
	...
		rxrpc_put_connection(conn, rxrpc_conn_put_service_reaped);
}

so such a connection still passes the new refcount test and is queued to
the I/O thread.  Would it be clearer to describe the change as a
refcount_inc_not_zero gate rather than the same check as
rxrpc_queue_conn()?

> diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
> index 0ece717db0f85..1be50e0c9cee5 100644
> --- a/net/rxrpc/conn_object.c
> +++ b/net/rxrpc/conn_object.c
> @@ -34,7 +34,10 @@ void rxrpc_poke_conn(struct rxrpc_connection *conn, enum rxrpc_conn_trace why)
>  	spin_lock_irq(&local->lock);
>  	busy = !list_empty(&conn->attend_link);
>  	if (!busy) {
> -		rxrpc_get_connection(conn, why);
> +		if (!rxrpc_get_connection_maybe(conn, why)) {
> +			spin_unlock_irq(&local->lock);
> +			return;
> +		}
>  		list_add_tail(&conn->attend_link, &local->conn_attend_q);
>  	}
>  	spin_unlock_irq(&local->lock);

[Severity: High]
This isn't a bug introduced by this patch, but can a poke reference still be
taken after the I/O thread has exited, and if so who drops it?

The only consumer of conn_attend_q is rxrpc_io_thread():

net/rxrpc/io_thread.c:rxrpc_io_thread() {
	...
		while ((conn = list_first_entry_or_null(&conn_attend_q,
						       struct rxrpc_connection,
						       attend_link))) {
			spin_lock_irq(&local->lock);
			list_del_init(&conn->attend_link);
			spin_unlock_irq(&local->lock);
			rxrpc_input_conn_event(conn, NULL);
			rxrpc_put_connection(conn, rxrpc_conn_put_poke);
		}
	...
		if (should_stop)
			break;
	...
	rxrpc_destroy_local(local);
}

After that break, nothing drains conn_attend_q again.  rxrpc_destroy_local()
purges rx_queue and the client conns but never unlinks attend_link or drops
poke refs:

net/rxrpc/local_object.c:rxrpc_destroy_local() {
	local->dead = true;

	mutex_lock(&rxnet->local_mutex);
	hlist_del_init_rcu(&local->link);
	mutex_unlock(&rxnet->local_mutex);

	rxrpc_clean_up_local_conns(local);
	...
	rxrpc_purge_queue(&local->rx_queue);
	rxrpc_purge_client_connections(local);
}

The final-ACK timer armed in rxrpc_disconnect_client_call() has no reference
held for it:

net/rxrpc/conn_client.c:rxrpc_disconnect_client_call() {
	...
		unsigned long final_ack_at = jiffies + 2;
	...
		rxrpc_reduce_conn_timer(conn, final_ack_at);
}

If that timer expires between the I/O thread's last conn_attend_q re-check
and rxrpc_clean_up_local_conns()'s
rxrpc_put_connection(conn, rxrpc_conn_put_local_dead), the idle/bundle refs
are still held, so rxrpc_get_connection_maybe() succeeds and the connection
is queued with a poke ref that nothing will ever drop.

Does conn->ref then never reach zero, leaving conn->proc_link on
rxnet->conn_proc_list, rxnet->nr_conns undecremented and the rxrpc_local
reference held?  At netns exit that would hit

net/rxrpc/conn_object.c:rxrpc_destroy_all_connections() {
	ASSERT(list_empty(&rxnet->conn_proc_list));
	...
	wait_var_event(&rxnet->nr_conns, !atomic_read(&rxnet->nr_conns));
}

either the ASSERT or an indefinite wait on the cleanup_net worker.

Would closing this need a reference held for the armed conn->timer with a
synchronous cancel before the last put, or explicit unlinking of
conn_attend_q entries when the I/O thread exits?  The refcount-only gate
added here does not appear to cover it.

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260907113743.1453210-1-dhowells%40redhat.com

  reply	other threads:[~2026-09-08 20:49 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-07 11:37 [PATCH net v9 00/14] rxrpc: Miscellaneous fixes David Howells
2026-09-07 11:37 ` [PATCH net v9 01/14] afs: Fix lack of loop around sendmsg() to rxrpc David Howells
2026-09-07 13:06   ` David Laight
2026-09-10 10:18     ` David Howells
2026-09-07 11:37 ` [PATCH net v9 02/14] afs: Fix afs to abort the rxrpc call on send error David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 03/14] rxrpc: Fix lack of loop around reply send in rxperf server David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 04/14] rxrpc: Fix sendmsg to not return an error if last packet queued David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 05/14] rxrpc: Fix sendmsg length David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 06/14] rxrpc: Fix packet encryption error handling David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 07/14] rxrpc: Fix update of call->tx_pending without holding lock David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 08/14] rxrpc: Fix double IRQ enablement David Howells
2026-09-07 11:37 ` [PATCH net v9 09/14] rxrpc: Fix generation of notifications after call completion David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 10/14] rxrpc: Fix RxGK key parser to check enctype is supported David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 11/14] afs: Fix creation of RxGK CM channel token to have right size David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 12/14] afs: Fix lack of setting call->server when doing FS.InlineBulkStatus David Howells
2026-09-08 20:49   ` netdev-bot+sashiko
2026-09-07 11:37 ` [PATCH net v9 13/14] rxrpc: fix use-after-free in rxrpc_poke_conn() David Howells
2026-09-08 20:49   ` netdev-bot+sashiko [this message]
2026-09-07 11:37 ` [PATCH net v9 14/14] rxrpc: Take write lock when publishing the initial RxGK key David Howells
2026-09-08 20:49   ` netdev-bot+sashiko

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=178890059047.219967.10164675967516707934@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-afs@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.dionne@auristor.com \
    --cc=netdev@vger.kernel.org \
    --cc=nicoyip.dev@gmail.com \
    --cc=pabeni@redhat.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 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.