Skip to content

Commit 463ec95

Browse files
committed
Merge tag 'ipsec-2025-01-27' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2025-01-27 1) Fix incrementing the upper 32 bit sequence numbers for GSO skbs. From Jianbo Liu. 2) Fix an out-of-bounds read on xfrm state lookup. From Florian Westphal. 3) Fix secpath handling on packet offload mode. From Alexandre Cassen. 4) Fix the usage of skb->sk in the xfrm layer. 5) Don't disable preemption while looking up cache state to fix PREEMPT_RT. From Sebastian Sewior. * tag 'ipsec-2025-01-27' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: Don't disable preemption while looking up cache state. xfrm: Fix the usage of skb->sk xfrm: delete intermediate secpath entry in packet offload mode xfrm: state: fix out-of-bounds read during lookup xfrm: replay: Fix the update of replay_esn->oseq_hi for GSO ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 0154b94 + 6c9b7db commit 463ec95

File tree

9 files changed

+100
-38
lines changed

9 files changed

+100
-38
lines changed

include/net/xfrm.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,9 +1268,19 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
12681268

12691269
if (xo) {
12701270
x = xfrm_input_state(skb);
1271-
if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET)
1272-
return (xo->flags & CRYPTO_DONE) &&
1273-
(xo->status & CRYPTO_SUCCESS);
1271+
if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) {
1272+
bool check = (xo->flags & CRYPTO_DONE) &&
1273+
(xo->status & CRYPTO_SUCCESS);
1274+
1275+
/* The packets here are plain ones and secpath was
1276+
* needed to indicate that hardware already handled
1277+
* them and there is no need to do nothing in addition.
1278+
*
1279+
* Consume secpath which was set by drivers.
1280+
*/
1281+
secpath_reset(skb);
1282+
return check;
1283+
}
12741284
}
12751285

12761286
return __xfrm_check_nopolicy(net, skb, dir) ||

net/ipv4/esp4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ static void esp_output_done(void *data, int err)
279279
x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
280280
esp_output_tail_tcp(x, skb);
281281
else
282-
xfrm_output_resume(skb->sk, skb, err);
282+
xfrm_output_resume(skb_to_full_sk(skb), skb, err);
283283
}
284284
}
285285

net/ipv6/esp6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ static void esp_output_done(void *data, int err)
315315
x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
316316
esp_output_tail_tcp(x, skb);
317317
else
318-
xfrm_output_resume(skb->sk, skb, err);
318+
xfrm_output_resume(skb_to_full_sk(skb), skb, err);
319319
}
320320
}
321321

net/ipv6/xfrm6_output.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
8282

8383
toobig = skb->len > mtu && !skb_is_gso(skb);
8484

85-
if (toobig && xfrm6_local_dontfrag(skb->sk)) {
85+
if (toobig && xfrm6_local_dontfrag(sk)) {
8686
xfrm6_local_rxpmtu(skb, mtu);
8787
kfree_skb(skb);
8888
return -EMSGSIZE;
8989
} else if (toobig && xfrm6_noneed_fragment(skb)) {
9090
skb->ignore_df = 1;
9191
goto skip_frag;
92-
} else if (!skb->ignore_df && toobig && skb->sk) {
92+
} else if (!skb->ignore_df && toobig && sk) {
9393
xfrm_local_error(skb, mtu);
9494
kfree_skb(skb);
9595
return -EMSGSIZE;

net/xfrm/xfrm_interface_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
506506
skb_dst_set(skb, dst);
507507
skb->dev = tdev;
508508

509-
err = dst_output(xi->net, skb->sk, skb);
509+
err = dst_output(xi->net, skb_to_full_sk(skb), skb);
510510
if (net_xmit_eval(err) == 0) {
511511
dev_sw_netstats_tx_add(dev, 1, length);
512512
} else {

net/xfrm/xfrm_output.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
802802
!skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) {
803803
skb->protocol = htons(ETH_P_IP);
804804

805-
if (skb->sk)
805+
if (skb->sk && sk_fullsock(skb->sk))
806806
xfrm_local_error(skb, mtu);
807807
else
808808
icmp_send(skb, ICMP_DEST_UNREACH,
@@ -838,6 +838,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
838838
{
839839
int mtu, ret = 0;
840840
struct dst_entry *dst = skb_dst(skb);
841+
struct sock *sk = skb_to_full_sk(skb);
841842

842843
if (skb->ignore_df)
843844
goto out;
@@ -852,9 +853,9 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
852853
skb->dev = dst->dev;
853854
skb->protocol = htons(ETH_P_IPV6);
854855

855-
if (xfrm6_local_dontfrag(skb->sk))
856+
if (xfrm6_local_dontfrag(sk))
856857
ipv6_stub->xfrm6_local_rxpmtu(skb, mtu);
857-
else if (skb->sk)
858+
else if (sk)
858859
xfrm_local_error(skb, mtu);
859860
else
860861
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);

net/xfrm/xfrm_policy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2964,7 +2964,7 @@ static void xfrm_policy_queue_process(struct timer_list *t)
29642964
skb_dst_drop(skb);
29652965
skb_dst_set(skb, dst);
29662966

2967-
dst_output(net, skb->sk, skb);
2967+
dst_output(net, skb_to_full_sk(skb), skb);
29682968
}
29692969

29702970
out:

net/xfrm/xfrm_replay.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -714,10 +714,12 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff
714714
oseq += skb_shinfo(skb)->gso_segs;
715715
}
716716

717-
if (unlikely(xo->seq.low < replay_esn->oseq)) {
718-
XFRM_SKB_CB(skb)->seq.output.hi = ++oseq_hi;
719-
xo->seq.hi = oseq_hi;
720-
replay_esn->oseq_hi = oseq_hi;
717+
if (unlikely(oseq < replay_esn->oseq)) {
718+
replay_esn->oseq_hi = ++oseq_hi;
719+
if (xo->seq.low < replay_esn->oseq) {
720+
XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
721+
xo->seq.hi = oseq_hi;
722+
}
721723
if (replay_esn->oseq_hi == 0) {
722724
replay_esn->oseq--;
723725
replay_esn->oseq_hi--;

net/xfrm/xfrm_state.c

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
#define xfrm_state_deref_prot(table, net) \
3636
rcu_dereference_protected((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock))
37+
#define xfrm_state_deref_check(table, net) \
38+
rcu_dereference_check((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock))
3739

3840
static void xfrm_state_gc_task(struct work_struct *work);
3941

@@ -62,6 +64,8 @@ static inline unsigned int xfrm_dst_hash(struct net *net,
6264
u32 reqid,
6365
unsigned short family)
6466
{
67+
lockdep_assert_held(&net->xfrm.xfrm_state_lock);
68+
6569
return __xfrm_dst_hash(daddr, saddr, reqid, family, net->xfrm.state_hmask);
6670
}
6771

@@ -70,18 +74,24 @@ static inline unsigned int xfrm_src_hash(struct net *net,
7074
const xfrm_address_t *saddr,
7175
unsigned short family)
7276
{
77+
lockdep_assert_held(&net->xfrm.xfrm_state_lock);
78+
7379
return __xfrm_src_hash(daddr, saddr, family, net->xfrm.state_hmask);
7480
}
7581

7682
static inline unsigned int
7783
xfrm_spi_hash(struct net *net, const xfrm_address_t *daddr,
7884
__be32 spi, u8 proto, unsigned short family)
7985
{
86+
lockdep_assert_held(&net->xfrm.xfrm_state_lock);
87+
8088
return __xfrm_spi_hash(daddr, spi, proto, family, net->xfrm.state_hmask);
8189
}
8290

8391
static unsigned int xfrm_seq_hash(struct net *net, u32 seq)
8492
{
93+
lockdep_assert_held(&net->xfrm.xfrm_state_lock);
94+
8595
return __xfrm_seq_hash(seq, net->xfrm.state_hmask);
8696
}
8797

@@ -1108,16 +1118,38 @@ xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl,
11081118
x->props.family = tmpl->encap_family;
11091119
}
11101120

1111-
static struct xfrm_state *__xfrm_state_lookup_all(struct net *net, u32 mark,
1121+
struct xfrm_hash_state_ptrs {
1122+
const struct hlist_head *bydst;
1123+
const struct hlist_head *bysrc;
1124+
const struct hlist_head *byspi;
1125+
unsigned int hmask;
1126+
};
1127+
1128+
static void xfrm_hash_ptrs_get(const struct net *net, struct xfrm_hash_state_ptrs *ptrs)
1129+
{
1130+
unsigned int sequence;
1131+
1132+
do {
1133+
sequence = read_seqcount_begin(&net->xfrm.xfrm_state_hash_generation);
1134+
1135+
ptrs->bydst = xfrm_state_deref_check(net->xfrm.state_bydst, net);
1136+
ptrs->bysrc = xfrm_state_deref_check(net->xfrm.state_bysrc, net);
1137+
ptrs->byspi = xfrm_state_deref_check(net->xfrm.state_byspi, net);
1138+
ptrs->hmask = net->xfrm.state_hmask;
1139+
} while (read_seqcount_retry(&net->xfrm.xfrm_state_hash_generation, sequence));
1140+
}
1141+
1142+
static struct xfrm_state *__xfrm_state_lookup_all(const struct xfrm_hash_state_ptrs *state_ptrs,
1143+
u32 mark,
11121144
const xfrm_address_t *daddr,
11131145
__be32 spi, u8 proto,
11141146
unsigned short family,
11151147
struct xfrm_dev_offload *xdo)
11161148
{
1117-
unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
1149+
unsigned int h = __xfrm_spi_hash(daddr, spi, proto, family, state_ptrs->hmask);
11181150
struct xfrm_state *x;
11191151

1120-
hlist_for_each_entry_rcu(x, net->xfrm.state_byspi + h, byspi) {
1152+
hlist_for_each_entry_rcu(x, state_ptrs->byspi + h, byspi) {
11211153
#ifdef CONFIG_XFRM_OFFLOAD
11221154
if (xdo->type == XFRM_DEV_OFFLOAD_PACKET) {
11231155
if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET)
@@ -1151,15 +1183,16 @@ static struct xfrm_state *__xfrm_state_lookup_all(struct net *net, u32 mark,
11511183
return NULL;
11521184
}
11531185

1154-
static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark,
1186+
static struct xfrm_state *__xfrm_state_lookup(const struct xfrm_hash_state_ptrs *state_ptrs,
1187+
u32 mark,
11551188
const xfrm_address_t *daddr,
11561189
__be32 spi, u8 proto,
11571190
unsigned short family)
11581191
{
1159-
unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
1192+
unsigned int h = __xfrm_spi_hash(daddr, spi, proto, family, state_ptrs->hmask);
11601193
struct xfrm_state *x;
11611194

1162-
hlist_for_each_entry_rcu(x, net->xfrm.state_byspi + h, byspi) {
1195+
hlist_for_each_entry_rcu(x, state_ptrs->byspi + h, byspi) {
11631196
if (x->props.family != family ||
11641197
x->id.spi != spi ||
11651198
x->id.proto != proto ||
@@ -1181,11 +1214,11 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
11811214
__be32 spi, u8 proto,
11821215
unsigned short family)
11831216
{
1217+
struct xfrm_hash_state_ptrs state_ptrs;
11841218
struct hlist_head *state_cache_input;
11851219
struct xfrm_state *x = NULL;
1186-
int cpu = get_cpu();
11871220

1188-
state_cache_input = per_cpu_ptr(net->xfrm.state_cache_input, cpu);
1221+
state_cache_input = raw_cpu_ptr(net->xfrm.state_cache_input);
11891222

11901223
rcu_read_lock();
11911224
hlist_for_each_entry_rcu(x, state_cache_input, state_cache_input) {
@@ -1202,7 +1235,9 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
12021235
goto out;
12031236
}
12041237

1205-
x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
1238+
xfrm_hash_ptrs_get(net, &state_ptrs);
1239+
1240+
x = __xfrm_state_lookup(&state_ptrs, mark, daddr, spi, proto, family);
12061241

12071242
if (x && x->km.state == XFRM_STATE_VALID) {
12081243
spin_lock_bh(&net->xfrm.xfrm_state_lock);
@@ -1217,20 +1252,20 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
12171252

12181253
out:
12191254
rcu_read_unlock();
1220-
put_cpu();
12211255
return x;
12221256
}
12231257
EXPORT_SYMBOL(xfrm_input_state_lookup);
12241258

1225-
static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1259+
static struct xfrm_state *__xfrm_state_lookup_byaddr(const struct xfrm_hash_state_ptrs *state_ptrs,
1260+
u32 mark,
12261261
const xfrm_address_t *daddr,
12271262
const xfrm_address_t *saddr,
12281263
u8 proto, unsigned short family)
12291264
{
1230-
unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
1265+
unsigned int h = __xfrm_src_hash(daddr, saddr, family, state_ptrs->hmask);
12311266
struct xfrm_state *x;
12321267

1233-
hlist_for_each_entry_rcu(x, net->xfrm.state_bysrc + h, bysrc) {
1268+
hlist_for_each_entry_rcu(x, state_ptrs->bysrc + h, bysrc) {
12341269
if (x->props.family != family ||
12351270
x->id.proto != proto ||
12361271
!xfrm_addr_equal(&x->id.daddr, daddr, family) ||
@@ -1250,14 +1285,17 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
12501285
static inline struct xfrm_state *
12511286
__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
12521287
{
1288+
struct xfrm_hash_state_ptrs state_ptrs;
12531289
struct net *net = xs_net(x);
12541290
u32 mark = x->mark.v & x->mark.m;
12551291

1292+
xfrm_hash_ptrs_get(net, &state_ptrs);
1293+
12561294
if (use_spi)
1257-
return __xfrm_state_lookup(net, mark, &x->id.daddr,
1295+
return __xfrm_state_lookup(&state_ptrs, mark, &x->id.daddr,
12581296
x->id.spi, x->id.proto, family);
12591297
else
1260-
return __xfrm_state_lookup_byaddr(net, mark,
1298+
return __xfrm_state_lookup_byaddr(&state_ptrs, mark,
12611299
&x->id.daddr,
12621300
&x->props.saddr,
12631301
x->id.proto, family);
@@ -1331,6 +1369,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13311369
unsigned short family, u32 if_id)
13321370
{
13331371
static xfrm_address_t saddr_wildcard = { };
1372+
struct xfrm_hash_state_ptrs state_ptrs;
13341373
struct net *net = xp_net(pol);
13351374
unsigned int h, h_wildcard;
13361375
struct xfrm_state *x, *x0, *to_put;
@@ -1395,8 +1434,10 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13951434
else if (acquire_in_progress) /* XXX: acquire_in_progress should not happen */
13961435
WARN_ON(1);
13971436

1398-
h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
1399-
hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h, bydst) {
1437+
xfrm_hash_ptrs_get(net, &state_ptrs);
1438+
1439+
h = __xfrm_dst_hash(daddr, saddr, tmpl->reqid, encap_family, state_ptrs.hmask);
1440+
hlist_for_each_entry_rcu(x, state_ptrs.bydst + h, bydst) {
14001441
#ifdef CONFIG_XFRM_OFFLOAD
14011442
if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) {
14021443
if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET)
@@ -1429,8 +1470,9 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
14291470
if (best || acquire_in_progress)
14301471
goto found;
14311472

1432-
h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family);
1433-
hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h_wildcard, bydst) {
1473+
h_wildcard = __xfrm_dst_hash(daddr, &saddr_wildcard, tmpl->reqid,
1474+
encap_family, state_ptrs.hmask);
1475+
hlist_for_each_entry_rcu(x, state_ptrs.bydst + h_wildcard, bydst) {
14341476
#ifdef CONFIG_XFRM_OFFLOAD
14351477
if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) {
14361478
if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET)
@@ -1468,7 +1510,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
14681510

14691511
if (!x && !error && !acquire_in_progress) {
14701512
if (tmpl->id.spi &&
1471-
(x0 = __xfrm_state_lookup_all(net, mark, daddr,
1513+
(x0 = __xfrm_state_lookup_all(&state_ptrs, mark, daddr,
14721514
tmpl->id.spi, tmpl->id.proto,
14731515
encap_family,
14741516
&pol->xdo)) != NULL) {
@@ -2253,10 +2295,13 @@ struct xfrm_state *
22532295
xfrm_state_lookup(struct net *net, u32 mark, const xfrm_address_t *daddr, __be32 spi,
22542296
u8 proto, unsigned short family)
22552297
{
2298+
struct xfrm_hash_state_ptrs state_ptrs;
22562299
struct xfrm_state *x;
22572300

22582301
rcu_read_lock();
2259-
x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
2302+
xfrm_hash_ptrs_get(net, &state_ptrs);
2303+
2304+
x = __xfrm_state_lookup(&state_ptrs, mark, daddr, spi, proto, family);
22602305
rcu_read_unlock();
22612306
return x;
22622307
}
@@ -2267,10 +2312,14 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark,
22672312
const xfrm_address_t *daddr, const xfrm_address_t *saddr,
22682313
u8 proto, unsigned short family)
22692314
{
2315+
struct xfrm_hash_state_ptrs state_ptrs;
22702316
struct xfrm_state *x;
22712317

22722318
spin_lock_bh(&net->xfrm.xfrm_state_lock);
2273-
x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
2319+
2320+
xfrm_hash_ptrs_get(net, &state_ptrs);
2321+
2322+
x = __xfrm_state_lookup_byaddr(&state_ptrs, mark, daddr, saddr, proto, family);
22742323
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
22752324
return x;
22762325
}

0 commit comments

Comments
 (0)