Skip to content

Commit 085f24f

Browse files
qsngregkh
authored andcommitted
xfrm: state: use a consistent pcpu_id in xfrm_state_find
[ Upstream commit 7eb11c0 ] 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: 1ddf991 ("xfrm: Add support for per cpu xfrm state handling.") Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> Reviewed-by: Florian Westphal <fw@strlen.de> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 6bf2daa commit 085f24f

File tree

1 file changed

+6
-13
lines changed

1 file changed

+6
-13
lines changed

net/xfrm/xfrm_state.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,14 +1242,8 @@ static void xfrm_hash_grow_check(struct net *net, int have_hash_collision)
12421242
static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
12431243
const struct flowi *fl, unsigned short family,
12441244
struct xfrm_state **best, int *acq_in_progress,
1245-
int *error)
1245+
int *error, unsigned int pcpu_id)
12461246
{
1247-
/* We need the cpu id just as a lookup key,
1248-
* we don't require it to be stable.
1249-
*/
1250-
unsigned int pcpu_id = get_cpu();
1251-
put_cpu();
1252-
12531247
/* Resolution logic:
12541248
* 1. There is a valid state with matching selector. Done.
12551249
* 2. Valid state with inappropriate selector. Skip.
@@ -1316,8 +1310,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13161310
/* We need the cpu id just as a lookup key,
13171311
* we don't require it to be stable.
13181312
*/
1319-
pcpu_id = get_cpu();
1320-
put_cpu();
1313+
pcpu_id = raw_smp_processor_id();
13211314

13221315
to_put = NULL;
13231316

@@ -1337,7 +1330,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13371330
tmpl->id.proto == x->id.proto &&
13381331
(tmpl->id.spi == x->id.spi || !tmpl->id.spi))
13391332
xfrm_state_look_at(pol, x, fl, encap_family,
1340-
&best, &acquire_in_progress, &error);
1333+
&best, &acquire_in_progress, &error, pcpu_id);
13411334
}
13421335

13431336
if (best)
@@ -1354,7 +1347,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13541347
tmpl->id.proto == x->id.proto &&
13551348
(tmpl->id.spi == x->id.spi || !tmpl->id.spi))
13561349
xfrm_state_look_at(pol, x, fl, family,
1357-
&best, &acquire_in_progress, &error);
1350+
&best, &acquire_in_progress, &error, pcpu_id);
13581351
}
13591352

13601353
cached:
@@ -1395,7 +1388,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13951388
tmpl->id.proto == x->id.proto &&
13961389
(tmpl->id.spi == x->id.spi || !tmpl->id.spi))
13971390
xfrm_state_look_at(pol, x, fl, family,
1398-
&best, &acquire_in_progress, &error);
1391+
&best, &acquire_in_progress, &error, pcpu_id);
13991392
}
14001393
if (best || acquire_in_progress)
14011394
goto found;
@@ -1430,7 +1423,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
14301423
tmpl->id.proto == x->id.proto &&
14311424
(tmpl->id.spi == x->id.spi || !tmpl->id.spi))
14321425
xfrm_state_look_at(pol, x, fl, family,
1433-
&best, &acquire_in_progress, &error);
1426+
&best, &acquire_in_progress, &error, pcpu_id);
14341427
}
14351428

14361429
found:

0 commit comments

Comments
 (0)