Commit 7c2becf7 authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2021-06-23

1) Don't return a mtu smaller than 1280 on IPv6 pmtu discovery.
   From Sabrina Dubroca

2) Fix seqcount rcu-read side in xfrm_policy_lookup_bytype
   for the PREEMPT_RT case. From Varad Gautam.

3) Remove a repeated declaration of xfrm_parse_spi.
   From Shaokun Zhang.

4) IPv4 beet mode can't handle fragments, but IPv6 does.
   commit 68dc022d ("xfrm: BEET mode doesn't support
   fragments for inner packets") handled IPv4 and IPv6
   the same way. Relax the check for IPv6 because fragments
   are possible here. From Xin Long.

5) Memory allocation failures are not reported for
   XFRMA_ENCAP and XFRMA_COADDR in xfrm_state_construct.
   Fix this by moving both cases in front of the function.

6) Fix a missing initialization in the xfrm offload fallback
   fail case for bonding devices. From Ayush Sawal.

Please pull or let me know if there are problems.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f4b29d2e dd72fadf
...@@ -1546,6 +1546,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); ...@@ -1546,6 +1546,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
int xfrm_init_replay(struct xfrm_state *x); int xfrm_init_replay(struct xfrm_state *x);
u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu);
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu); u32 xfrm_state_mtu(struct xfrm_state *x, int mtu);
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload); int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload);
int xfrm_init_state(struct xfrm_state *x); int xfrm_init_state(struct xfrm_state *x);
...@@ -1570,7 +1571,6 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, ...@@ -1570,7 +1571,6 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
int encap_type); int encap_type);
int xfrm4_transport_finish(struct sk_buff *skb, int async); int xfrm4_transport_finish(struct sk_buff *skb, int async);
int xfrm4_rcv(struct sk_buff *skb); int xfrm4_rcv(struct sk_buff *skb);
int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
{ {
......
...@@ -673,7 +673,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -673,7 +673,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
u32 padto; u32 padto;
padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached));
if (skb->len < padto) if (skb->len < padto)
esp.tfclen = padto - skb->len; esp.tfclen = padto - skb->len;
} }
......
...@@ -708,7 +708,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -708,7 +708,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
u32 padto; u32 padto;
padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached));
if (skb->len < padto) if (skb->len < padto)
esp.tfclen = padto - skb->len; esp.tfclen = padto - skb->len;
} }
......
...@@ -268,6 +268,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, ...@@ -268,6 +268,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
xso->num_exthdrs = 0; xso->num_exthdrs = 0;
xso->flags = 0; xso->flags = 0;
xso->dev = NULL; xso->dev = NULL;
xso->real_dev = NULL;
dev_put(dev); dev_put(dev);
if (err != -EOPNOTSUPP) if (err != -EOPNOTSUPP)
......
...@@ -711,15 +711,8 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) ...@@ -711,15 +711,8 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
static int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb) static int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
unsigned int ptr = 0;
int err; int err;
if (x->outer_mode.encap == XFRM_MODE_BEET &&
ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL, NULL) >= 0) {
net_warn_ratelimited("BEET mode doesn't support inner IPv6 fragments\n");
return -EAFNOSUPPORT;
}
err = xfrm6_tunnel_check_size(skb); err = xfrm6_tunnel_check_size(skb);
if (err) if (err)
return err; return err;
......
...@@ -2092,12 +2092,15 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, ...@@ -2092,12 +2092,15 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
if (unlikely(!daddr || !saddr)) if (unlikely(!daddr || !saddr))
return NULL; return NULL;
rcu_read_lock();
retry: retry:
do {
sequence = read_seqcount_begin(&xfrm_policy_hash_generation); sequence = read_seqcount_begin(&xfrm_policy_hash_generation);
rcu_read_lock();
chain = policy_hash_direct(net, daddr, saddr, family, dir); chain = policy_hash_direct(net, daddr, saddr, family, dir);
} while (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)); if (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)) {
rcu_read_unlock();
goto retry;
}
ret = NULL; ret = NULL;
hlist_for_each_entry_rcu(pol, chain, bydst) { hlist_for_each_entry_rcu(pol, chain, bydst) {
...@@ -2128,11 +2131,15 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, ...@@ -2128,11 +2131,15 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
} }
skip_inexact: skip_inexact:
if (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)) if (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)) {
rcu_read_unlock();
goto retry; goto retry;
}
if (ret && !xfrm_pol_hold_rcu(ret)) if (ret && !xfrm_pol_hold_rcu(ret)) {
rcu_read_unlock();
goto retry; goto retry;
}
fail: fail:
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -2518,7 +2518,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x) ...@@ -2518,7 +2518,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
} }
EXPORT_SYMBOL(xfrm_state_delete_tunnel); EXPORT_SYMBOL(xfrm_state_delete_tunnel);
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu)
{ {
const struct xfrm_type *type = READ_ONCE(x->type); const struct xfrm_type *type = READ_ONCE(x->type);
struct crypto_aead *aead; struct crypto_aead *aead;
...@@ -2549,7 +2549,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) ...@@ -2549,7 +2549,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
return ((mtu - x->props.header_len - crypto_aead_authsize(aead) - return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
net_adj) & ~(blksize - 1)) + net_adj - 2; net_adj) & ~(blksize - 1)) + net_adj - 2;
} }
EXPORT_SYMBOL_GPL(xfrm_state_mtu); EXPORT_SYMBOL_GPL(__xfrm_state_mtu);
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
{
mtu = __xfrm_state_mtu(x, mtu);
if (x->props.family == AF_INET6 && mtu < IPV6_MIN_MTU)
return IPV6_MIN_MTU;
return mtu;
}
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
{ {
......
...@@ -580,6 +580,20 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, ...@@ -580,6 +580,20 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
copy_from_user_state(x, p); copy_from_user_state(x, p);
if (attrs[XFRMA_ENCAP]) {
x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]),
sizeof(*x->encap), GFP_KERNEL);
if (x->encap == NULL)
goto error;
}
if (attrs[XFRMA_COADDR]) {
x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]),
sizeof(*x->coaddr), GFP_KERNEL);
if (x->coaddr == NULL)
goto error;
}
if (attrs[XFRMA_SA_EXTRA_FLAGS]) if (attrs[XFRMA_SA_EXTRA_FLAGS])
x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]); x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);
...@@ -600,23 +614,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, ...@@ -600,23 +614,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
attrs[XFRMA_ALG_COMP]))) attrs[XFRMA_ALG_COMP])))
goto error; goto error;
if (attrs[XFRMA_ENCAP]) {
x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]),
sizeof(*x->encap), GFP_KERNEL);
if (x->encap == NULL)
goto error;
}
if (attrs[XFRMA_TFCPAD]) if (attrs[XFRMA_TFCPAD])
x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]); x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]);
if (attrs[XFRMA_COADDR]) {
x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]),
sizeof(*x->coaddr), GFP_KERNEL);
if (x->coaddr == NULL)
goto error;
}
xfrm_mark_get(attrs, &x->mark); xfrm_mark_get(attrs, &x->mark);
xfrm_smark_init(attrs, &x->props.smark); xfrm_smark_init(attrs, &x->props.smark);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment