Skip to content

Commit 5fc43ce

Browse files
committed
Merge tag 'ipsec-2023-08-15' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== 1) Fix a slab-out-of-bounds read in xfrm_address_filter. From Lin Ma. 2) Fix the pfkey sadb_x_filter validation. From Lin Ma. 3) Use the correct nla_policy structure for XFRMA_SEC_CTX. From Lin Ma. 4) Fix warnings triggerable by bad packets in the encap functions. From Herbert Xu. 5) Fix some slab-use-after-free in decode_session6. From Zhengchao Shao. 6) Fix a possible NULL piointer dereference in xfrm_update_ae_params. Lin Ma. 7) Add a forgotten nla_policy for XFRMA_MTIMER_THRESH. From Lin Ma. 8) Don't leak offloaded policies. From Leon Romanovsky. 9) Delete also the offloading part of an acquire state. From Leon Romanovsky. Please pull or let me know if there are problems.
2 parents 9944d20 + f3ec2b5 commit 5fc43ce

File tree

9 files changed

+34
-30
lines changed

9 files changed

+34
-30
lines changed

include/net/xfrm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,6 +1984,7 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
19841984
if (dev->xfrmdev_ops->xdo_dev_state_free)
19851985
dev->xfrmdev_ops->xdo_dev_state_free(x);
19861986
xso->dev = NULL;
1987+
xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
19871988
netdev_put(dev, &xso->dev_tracker);
19881989
}
19891990
}

net/ipv4/ip_vti.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,12 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
287287

288288
switch (skb->protocol) {
289289
case htons(ETH_P_IP):
290-
xfrm_decode_session(skb, &fl, AF_INET);
291290
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
291+
xfrm_decode_session(skb, &fl, AF_INET);
292292
break;
293293
case htons(ETH_P_IPV6):
294-
xfrm_decode_session(skb, &fl, AF_INET6);
295294
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
295+
xfrm_decode_session(skb, &fl, AF_INET6);
296296
break;
297297
default:
298298
goto tx_err;

net/ipv6/ip6_vti.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,12 +568,12 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
568568
vti6_addr_conflict(t, ipv6_hdr(skb)))
569569
goto tx_err;
570570

571-
xfrm_decode_session(skb, &fl, AF_INET6);
572571
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
572+
xfrm_decode_session(skb, &fl, AF_INET6);
573573
break;
574574
case htons(ETH_P_IP):
575-
xfrm_decode_session(skb, &fl, AF_INET);
576575
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
576+
xfrm_decode_session(skb, &fl, AF_INET);
577577
break;
578578
default:
579579
goto tx_err;

net/key/af_key.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,9 +1848,9 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
18481848
if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
18491849
struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
18501850

1851-
if ((xfilter->sadb_x_filter_splen >=
1851+
if ((xfilter->sadb_x_filter_splen >
18521852
(sizeof(xfrm_address_t) << 3)) ||
1853-
(xfilter->sadb_x_filter_dplen >=
1853+
(xfilter->sadb_x_filter_dplen >
18541854
(sizeof(xfrm_address_t) << 3))) {
18551855
mutex_unlock(&pfk->dump_lock);
18561856
return -EINVAL;

net/xfrm/xfrm_compat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
108108
[XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
109109
[XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) },
110110
[XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) },
111-
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) },
111+
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_user_sec_ctx) },
112112
[XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) },
113113
[XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) },
114114
[XFRMA_REPLAY_THRESH] = { .type = NLA_U32 },

net/xfrm/xfrm_input.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
180180
int optlen = 0;
181181
int err = -EINVAL;
182182

183+
skb->protocol = htons(ETH_P_IP);
184+
183185
if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
184186
struct ip_beet_phdr *ph;
185187
int phlen;
@@ -232,6 +234,8 @@ static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
232234
{
233235
int err = -EINVAL;
234236

237+
skb->protocol = htons(ETH_P_IP);
238+
235239
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
236240
goto out;
237241

@@ -267,6 +271,8 @@ static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
267271
{
268272
int err = -EINVAL;
269273

274+
skb->protocol = htons(ETH_P_IPV6);
275+
270276
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
271277
goto out;
272278

@@ -296,6 +302,8 @@ static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
296302
int size = sizeof(struct ipv6hdr);
297303
int err;
298304

305+
skb->protocol = htons(ETH_P_IPV6);
306+
299307
err = skb_cow_head(skb, size + skb->mac_len);
300308
if (err)
301309
goto out;
@@ -346,6 +354,7 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
346354
return xfrm6_remove_tunnel_encap(x, skb);
347355
break;
348356
}
357+
return -EINVAL;
349358
}
350359

351360
WARN_ON_ONCE(1);
@@ -366,19 +375,6 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
366375
return -EAFNOSUPPORT;
367376
}
368377

369-
switch (XFRM_MODE_SKB_CB(skb)->protocol) {
370-
case IPPROTO_IPIP:
371-
case IPPROTO_BEETPH:
372-
skb->protocol = htons(ETH_P_IP);
373-
break;
374-
case IPPROTO_IPV6:
375-
skb->protocol = htons(ETH_P_IPV6);
376-
break;
377-
default:
378-
WARN_ON_ONCE(1);
379-
break;
380-
}
381-
382378
return xfrm_inner_mode_encap_remove(x, skb);
383379
}
384380

net/xfrm/xfrm_interface_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
537537

538538
switch (skb->protocol) {
539539
case htons(ETH_P_IPV6):
540-
xfrm_decode_session(skb, &fl, AF_INET6);
541540
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
541+
xfrm_decode_session(skb, &fl, AF_INET6);
542542
if (!dst) {
543543
fl.u.ip6.flowi6_oif = dev->ifindex;
544544
fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
@@ -552,8 +552,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
552552
}
553553
break;
554554
case htons(ETH_P_IP):
555-
xfrm_decode_session(skb, &fl, AF_INET);
556555
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
556+
xfrm_decode_session(skb, &fl, AF_INET);
557557
if (!dst) {
558558
struct rtable *rt;
559559

net/xfrm/xfrm_state.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,12 +1324,8 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
13241324
struct xfrm_dev_offload *xso = &x->xso;
13251325

13261326
if (xso->type == XFRM_DEV_OFFLOAD_PACKET) {
1327-
xso->dev->xfrmdev_ops->xdo_dev_state_delete(x);
1328-
xso->dir = 0;
1329-
netdev_put(xso->dev, &xso->dev_tracker);
1330-
xso->dev = NULL;
1331-
xso->real_dev = NULL;
1332-
xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
1327+
xfrm_dev_state_delete(x);
1328+
xfrm_dev_state_free(x);
13331329
}
13341330
#endif
13351331
x->km.state = XFRM_STATE_DEAD;

net/xfrm/xfrm_user.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
628628
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
629629
struct nlattr *mt = attrs[XFRMA_MTIMER_THRESH];
630630

631-
if (re) {
631+
if (re && x->replay_esn && x->preplay_esn) {
632632
struct xfrm_replay_state_esn *replay_esn;
633633
replay_esn = nla_data(re);
634634
memcpy(x->replay_esn, replay_esn,
@@ -1267,6 +1267,15 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
12671267
sizeof(*filter), GFP_KERNEL);
12681268
if (filter == NULL)
12691269
return -ENOMEM;
1270+
1271+
/* see addr_match(), (prefix length >> 5) << 2
1272+
* will be used to compare xfrm_address_t
1273+
*/
1274+
if (filter->splen > (sizeof(xfrm_address_t) << 3) ||
1275+
filter->dplen > (sizeof(xfrm_address_t) << 3)) {
1276+
kfree(filter);
1277+
return -EINVAL;
1278+
}
12701279
}
12711280

12721281
if (attrs[XFRMA_PROTO])
@@ -2336,6 +2345,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
23362345
NETLINK_CB(skb).portid);
23372346
}
23382347
} else {
2348+
xfrm_dev_policy_delete(xp);
23392349
xfrm_audit_policy_delete(xp, err ? 0 : 1, true);
23402350

23412351
if (err != 0)
@@ -3015,7 +3025,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
30153025
[XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
30163026
[XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) },
30173027
[XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) },
3018-
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) },
3028+
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_user_sec_ctx) },
30193029
[XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) },
30203030
[XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) },
30213031
[XFRMA_REPLAY_THRESH] = { .type = NLA_U32 },
@@ -3035,6 +3045,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
30353045
[XFRMA_SET_MARK] = { .type = NLA_U32 },
30363046
[XFRMA_SET_MARK_MASK] = { .type = NLA_U32 },
30373047
[XFRMA_IF_ID] = { .type = NLA_U32 },
3048+
[XFRMA_MTIMER_THRESH] = { .type = NLA_U32 },
30383049
};
30393050
EXPORT_SYMBOL_GPL(xfrma_policy);
30403051

0 commit comments

Comments
 (0)