Skip to content

Commit

Permalink
Merge tag 'ipsec-2023-08-15' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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.
  • Loading branch information
davem330 committed Aug 16, 2023
2 parents 9944d20 + f3ec2b5 commit 5fc43ce
Show file tree
Hide file tree
Showing 9 changed files with 34 additions and 30 deletions.
1 change: 1 addition & 0 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1984,6 +1984,7 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
if (dev->xfrmdev_ops->xdo_dev_state_free)
dev->xfrmdev_ops->xdo_dev_state_free(x);
xso->dev = NULL;
xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
netdev_put(dev, &xso->dev_tracker);
}
}
Expand Down
4 changes: 2 additions & 2 deletions net/ipv4/ip_vti.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,12 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)

switch (skb->protocol) {
case htons(ETH_P_IP):
xfrm_decode_session(skb, &fl, AF_INET);
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
xfrm_decode_session(skb, &fl, AF_INET);
break;
case htons(ETH_P_IPV6):
xfrm_decode_session(skb, &fl, AF_INET6);
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
xfrm_decode_session(skb, &fl, AF_INET6);
break;
default:
goto tx_err;
Expand Down
4 changes: 2 additions & 2 deletions net/ipv6/ip6_vti.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,12 +568,12 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
vti6_addr_conflict(t, ipv6_hdr(skb)))
goto tx_err;

xfrm_decode_session(skb, &fl, AF_INET6);
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
xfrm_decode_session(skb, &fl, AF_INET6);
break;
case htons(ETH_P_IP):
xfrm_decode_session(skb, &fl, AF_INET);
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
xfrm_decode_session(skb, &fl, AF_INET);
break;
default:
goto tx_err;
Expand Down
4 changes: 2 additions & 2 deletions net/key/af_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -1848,9 +1848,9 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];

if ((xfilter->sadb_x_filter_splen >=
if ((xfilter->sadb_x_filter_splen >
(sizeof(xfrm_address_t) << 3)) ||
(xfilter->sadb_x_filter_dplen >=
(xfilter->sadb_x_filter_dplen >
(sizeof(xfrm_address_t) << 3))) {
mutex_unlock(&pfk->dump_lock);
return -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion net/xfrm/xfrm_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
[XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
[XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) },
[XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) },
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) },
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_user_sec_ctx) },
[XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) },
[XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) },
[XFRMA_REPLAY_THRESH] = { .type = NLA_U32 },
Expand Down
22 changes: 9 additions & 13 deletions net/xfrm/xfrm_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
int optlen = 0;
int err = -EINVAL;

skb->protocol = htons(ETH_P_IP);

if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
struct ip_beet_phdr *ph;
int phlen;
Expand Down Expand Up @@ -232,6 +234,8 @@ static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
{
int err = -EINVAL;

skb->protocol = htons(ETH_P_IP);

if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto out;

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

skb->protocol = htons(ETH_P_IPV6);

if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
goto out;

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

skb->protocol = htons(ETH_P_IPV6);

err = skb_cow_head(skb, size + skb->mac_len);
if (err)
goto out;
Expand Down Expand Up @@ -346,6 +354,7 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
return xfrm6_remove_tunnel_encap(x, skb);
break;
}
return -EINVAL;
}

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

switch (XFRM_MODE_SKB_CB(skb)->protocol) {
case IPPROTO_IPIP:
case IPPROTO_BEETPH:
skb->protocol = htons(ETH_P_IP);
break;
case IPPROTO_IPV6:
skb->protocol = htons(ETH_P_IPV6);
break;
default:
WARN_ON_ONCE(1);
break;
}

return xfrm_inner_mode_encap_remove(x, skb);
}

Expand Down
4 changes: 2 additions & 2 deletions net/xfrm/xfrm_interface_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,8 +537,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)

switch (skb->protocol) {
case htons(ETH_P_IPV6):
xfrm_decode_session(skb, &fl, AF_INET6);
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
xfrm_decode_session(skb, &fl, AF_INET6);
if (!dst) {
fl.u.ip6.flowi6_oif = dev->ifindex;
fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
Expand All @@ -552,8 +552,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
}
break;
case htons(ETH_P_IP):
xfrm_decode_session(skb, &fl, AF_INET);
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
xfrm_decode_session(skb, &fl, AF_INET);
if (!dst) {
struct rtable *rt;

Expand Down
8 changes: 2 additions & 6 deletions net/xfrm/xfrm_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1324,12 +1324,8 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
struct xfrm_dev_offload *xso = &x->xso;

if (xso->type == XFRM_DEV_OFFLOAD_PACKET) {
xso->dev->xfrmdev_ops->xdo_dev_state_delete(x);
xso->dir = 0;
netdev_put(xso->dev, &xso->dev_tracker);
xso->dev = NULL;
xso->real_dev = NULL;
xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
xfrm_dev_state_delete(x);
xfrm_dev_state_free(x);
}
#endif
x->km.state = XFRM_STATE_DEAD;
Expand Down
15 changes: 13 additions & 2 deletions net/xfrm/xfrm_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
struct nlattr *mt = attrs[XFRMA_MTIMER_THRESH];

if (re) {
if (re && x->replay_esn && x->preplay_esn) {
struct xfrm_replay_state_esn *replay_esn;
replay_esn = nla_data(re);
memcpy(x->replay_esn, replay_esn,
Expand Down Expand Up @@ -1267,6 +1267,15 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
sizeof(*filter), GFP_KERNEL);
if (filter == NULL)
return -ENOMEM;

/* see addr_match(), (prefix length >> 5) << 2
* will be used to compare xfrm_address_t
*/
if (filter->splen > (sizeof(xfrm_address_t) << 3) ||
filter->dplen > (sizeof(xfrm_address_t) << 3)) {
kfree(filter);
return -EINVAL;
}
}

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

if (err != 0)
Expand Down Expand Up @@ -3015,7 +3025,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
[XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) },
[XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) },
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) },
[XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_user_sec_ctx) },
[XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) },
[XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) },
[XFRMA_REPLAY_THRESH] = { .type = NLA_U32 },
Expand All @@ -3035,6 +3045,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_SET_MARK] = { .type = NLA_U32 },
[XFRMA_SET_MARK_MASK] = { .type = NLA_U32 },
[XFRMA_IF_ID] = { .type = NLA_U32 },
[XFRMA_MTIMER_THRESH] = { .type = NLA_U32 },
};
EXPORT_SYMBOL_GPL(xfrma_policy);

Expand Down

0 comments on commit 5fc43ce

Please sign in to comment.