forked from luck/tmp_suning_uos_patched
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2017-06-23 1) Fix xfrm garbage collecting when unregistering a netdevice. From Hangbin Liu. 2) Fix NULL pointer derefernce when exiting a network namespace. From Hangbin Liu. 3) Fix some error codes in pfkey to prevent a NULL pointer derefernce. From Dan Carpenter. 4) Fix NULL pointer derefernce on allocation failure in pfkey. From Dan Carpenter. 5) Adjust IPv6 payload_len to include extension headers. Otherwise we corrupt the packets when doing ESP GRO on transport mode. From Yossi Kuperman. 6) Set nhoff to the proper offset of the IPv6 nexthdr when doing ESP GRO. From Yossi Kuperman. Please pull or let me know if there are problems. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
43b786c676
|
@ -1850,8 +1850,9 @@ static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XFRM_OFFLOAD
|
||||
void __net_init xfrm_dev_init(void);
|
||||
|
||||
#ifdef CONFIG_XFRM_OFFLOAD
|
||||
int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features);
|
||||
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
|
||||
struct xfrm_user_offload *xuo);
|
||||
|
@ -1877,10 +1878,6 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
|
|||
}
|
||||
}
|
||||
#else
|
||||
static inline void __net_init xfrm_dev_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -30,6 +30,25 @@
|
|||
#include <net/ipv6.h>
|
||||
#include <linux/icmpv6.h>
|
||||
|
||||
static __u16 esp6_nexthdr_esp_offset(struct ipv6hdr *ipv6_hdr, int nhlen)
|
||||
{
|
||||
int off = sizeof(struct ipv6hdr);
|
||||
struct ipv6_opt_hdr *exthdr;
|
||||
|
||||
if (likely(ipv6_hdr->nexthdr == NEXTHDR_ESP))
|
||||
return offsetof(struct ipv6hdr, nexthdr);
|
||||
|
||||
while (off < nhlen) {
|
||||
exthdr = (void *)ipv6_hdr + off;
|
||||
if (exthdr->nexthdr == NEXTHDR_ESP)
|
||||
return off;
|
||||
|
||||
off += ipv6_optlen(exthdr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
@ -38,6 +57,7 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
|
|||
struct xfrm_state *x;
|
||||
__be32 seq;
|
||||
__be32 spi;
|
||||
int nhoff;
|
||||
int err;
|
||||
|
||||
skb_pull(skb, offset);
|
||||
|
@ -72,6 +92,11 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
|
|||
|
||||
xo->flags |= XFRM_GRO;
|
||||
|
||||
nhoff = esp6_nexthdr_esp_offset(ipv6_hdr(skb), offset);
|
||||
if (!nhoff)
|
||||
goto out;
|
||||
|
||||
IP6CB(skb)->nhoff = nhoff;
|
||||
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
|
||||
XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
|
||||
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
|
||||
|
|
|
@ -43,8 +43,8 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
|
|||
return 1;
|
||||
#endif
|
||||
|
||||
ipv6_hdr(skb)->payload_len = htons(skb->len);
|
||||
__skb_push(skb, skb->data - skb_network_header(skb));
|
||||
ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
|
||||
|
||||
if (xo && (xo->flags & XFRM_GRO)) {
|
||||
skb_mac_header_rebuild(skb);
|
||||
|
|
|
@ -1157,6 +1157,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
goto out;
|
||||
}
|
||||
|
||||
err = -ENOBUFS;
|
||||
key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
|
||||
if (sa->sadb_sa_auth) {
|
||||
int keysize = 0;
|
||||
|
@ -1168,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
if (key)
|
||||
keysize = (key->sadb_key_bits + 7) / 8;
|
||||
x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
|
||||
if (!x->aalg)
|
||||
if (!x->aalg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strcpy(x->aalg->alg_name, a->name);
|
||||
x->aalg->alg_key_len = 0;
|
||||
if (key) {
|
||||
|
@ -1188,8 +1191,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
goto out;
|
||||
}
|
||||
x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
|
||||
if (!x->calg)
|
||||
if (!x->calg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strcpy(x->calg->alg_name, a->name);
|
||||
x->props.calgo = sa->sadb_sa_encrypt;
|
||||
} else {
|
||||
|
@ -1203,8 +1208,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
if (key)
|
||||
keysize = (key->sadb_key_bits + 7) / 8;
|
||||
x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
|
||||
if (!x->ealg)
|
||||
if (!x->ealg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strcpy(x->ealg->alg_name, a->name);
|
||||
x->ealg->alg_key_len = 0;
|
||||
if (key) {
|
||||
|
@ -1249,8 +1256,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
struct xfrm_encap_tmpl *natt;
|
||||
|
||||
x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
|
||||
if (!x->encap)
|
||||
if (!x->encap) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
natt = x->encap;
|
||||
n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
|
||||
|
@ -2755,6 +2764,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
|
|||
int err, err2;
|
||||
|
||||
err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
|
||||
if (!err)
|
||||
xfrm_garbage_collect(net);
|
||||
err2 = unicast_flush_resp(sk, hdr);
|
||||
if (err || err2) {
|
||||
if (err == -ESRCH) /* empty table - old silent behavior */
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
|
||||
xfrm_input.o xfrm_output.o \
|
||||
xfrm_sysctl.o xfrm_replay.o
|
||||
obj-$(CONFIG_XFRM_OFFLOAD) += xfrm_device.o
|
||||
xfrm_sysctl.o xfrm_replay.o xfrm_device.o
|
||||
obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
|
||||
obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
|
||||
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <net/xfrm.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#ifdef CONFIG_XFRM_OFFLOAD
|
||||
int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
|
||||
{
|
||||
int err;
|
||||
|
@ -137,6 +138,7 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
|||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok);
|
||||
#endif
|
||||
|
||||
int xfrm_dev_register(struct net_device *dev)
|
||||
{
|
||||
|
|
|
@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
|
|||
err = -ESRCH;
|
||||
out:
|
||||
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
||||
|
||||
if (cnt)
|
||||
xfrm_garbage_collect(net);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_policy_flush);
|
||||
|
|
|
@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
return 0;
|
||||
return err;
|
||||
}
|
||||
xfrm_garbage_collect(net);
|
||||
|
||||
c.data.type = type;
|
||||
c.event = nlh->nlmsg_type;
|
||||
|
|
Loading…
Reference in New Issue
Block a user