[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aDQJ+kt5c0trlfo5@gauss3.secunet.de>
Date: Mon, 26 May 2025 08:28:10 +0200
From: Steffen Klassert <steffen.klassert@...unet.com>
To: Sabrina Dubroca <sd@...asysnail.net>
CC: <netdev@...r.kernel.org>, Antony Antony <antony.antony@...unet.com>,
Tobias Brunner <tobias@...ongswan.org>, Florian Westphal <fw@...len.de>
Subject: Re: [PATCH ipsec 2/2] xfrm: state: use a consistent pcpu_id in
xfrm_state_find
On Fri, May 23, 2025 at 05:11:18PM +0200, Sabrina Dubroca wrote:
> If we get preempted during xfrm_state_find, we could run
> xfrm_state_look_at using a different pcpu_id than the one
> xfrm_state_find saw. This could lead to ignoring states that should
> have matched, and triggering acquires on a CPU that already has a pcpu
> state.
>
> xfrm_state_find starts on CPU1
> pcpu_id = 1
> lookup starts
> <preemption, we're now on CPU2>
> xfrm_state_look_at pcpu_id = 2
> finds a state
> found:
> best->pcpu_num != pcpu_id (2 != 1)
> if (!x && !error && !acquire_in_progress) {
> ...
> xfrm_state_alloc
> xfrm_init_tempstate
> ...
>
> This can be avoided by passing the original pcpu_id down to all
> xfrm_state_look_at() calls.
>
> Also switch to raw_smp_processor_id, disabling preempting just to
> re-enable it immediately doesn't really make sense.
>
> Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.")
> Signed-off-by: Sabrina Dubroca <sd@...asysnail.net>
> ---
> net/xfrm/xfrm_state.c | 19 ++++++-------------
> 1 file changed, 6 insertions(+), 13 deletions(-)
>
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index ff6813ecc6df..3dc78ef2bf7d 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -1307,14 +1307,8 @@ static void xfrm_hash_grow_check(struct net *net, int have_hash_collision)
> static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
> const struct flowi *fl, unsigned short family,
> struct xfrm_state **best, int *acq_in_progress,
> - int *error)
> + int *error, unsigned int pcpu_id)
> {
> - /* We need the cpu id just as a lookup key,
> - * we don't require it to be stable.
> - */
> - unsigned int pcpu_id = get_cpu();
> - put_cpu();
> -
> /* Resolution logic:
> * 1. There is a valid state with matching selector. Done.
> * 2. Valid state with inappropriate selector. Skip.
> @@ -1381,8 +1375,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
> /* We need the cpu id just as a lookup key,
> * we don't require it to be stable.
> */
> - pcpu_id = get_cpu();
> - put_cpu();
> + pcpu_id = raw_smp_processor_id();
This codepath can be taken from the forwarding path with preemtion
disabled. raw_smp_processor_id will trigger a warning in that case,
maybe better to use raw_cpu_ptr?
Thanks!
Powered by blists - more mailing lists