Re: [PATCH 2/2] rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer()

From: Marc Dionne
Date: Fri Nov 26 2021 - 08:18:00 EST


On Wed, Nov 24, 2021 at 10:38 AM David Howells <dhowells@xxxxxxxxxx> wrote:
>
> From: Eiichi Tsukata <eiichi.tsukata@xxxxxxxxxxx>
>
> Need to call rxrpc_put_local() for peer candidate before kfree() as it
> holds a ref to rxrpc_local.
>
> [DH: v2: Changed to abstract the peer freeing code out into a function]
>
> Fixes: 9ebeddef58c4 ("rxrpc: rxrpc_peer needs to hold a ref on the rxrpc_local record")
> Signed-off-by: Eiichi Tsukata <eiichi.tsukata@xxxxxxxxxxx>
> Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
> cc: Marc Dionne <marc.dionne@xxxxxxxxxxxx>
> cc: linux-afs@xxxxxxxxxxxxxxxxxxx
> Link: https://lore.kernel.org/all/20211121041608.133740-2-eiichi.tsukata@xxxxxxxxxxx/ # v1
> ---
>
> net/rxrpc/peer_object.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c
> index 68396d052052..0298fe2ad6d3 100644
> --- a/net/rxrpc/peer_object.c
> +++ b/net/rxrpc/peer_object.c
> @@ -299,6 +299,12 @@ static struct rxrpc_peer *rxrpc_create_peer(struct rxrpc_sock *rx,
> return peer;
> }
>
> +static void rxrpc_free_peer(struct rxrpc_peer *peer)
> +{
> + rxrpc_put_local(peer->local);
> + kfree_rcu(peer, rcu);
> +}
> +
> /*
> * Set up a new incoming peer. There shouldn't be any other matching peers
> * since we've already done a search in the list from the non-reentrant context
> @@ -365,7 +371,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx,
> spin_unlock_bh(&rxnet->peer_hash_lock);
>
> if (peer)
> - kfree(candidate);
> + rxrpc_free_peer(candidate);
> else
> peer = candidate;
> }
> @@ -420,8 +426,7 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer)
> list_del_init(&peer->keepalive_link);
> spin_unlock_bh(&rxnet->peer_hash_lock);
>
> - rxrpc_put_local(peer->local);
> - kfree_rcu(peer, rcu);
> + rxrpc_free_peer(peer);
> }
>
> /*
> @@ -457,8 +462,7 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *peer)
> if (n == 0) {
> hash_del_rcu(&peer->hash_link);
> list_del_init(&peer->keepalive_link);
> - rxrpc_put_local(peer->local);
> - kfree_rcu(peer, rcu);
> + rxrpc_free_peer(peer);
> }
> }

Reviewed-by: Marc Dionne <marc.dionne@xxxxxxxxxxxx>

Marc