Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2015-03-16 1) Fix the network header offset in _decode_session6 when multiple IPv6 extension headers are present. From Hajime Tazaki. 2) Fix an interfamily tunnel crash. We set outer mode protocol too early and may dispatch to the wrong address family. Move the setting of the outer mode protocol behind the last accessing of the inner mode to fix the crash. 3) Most callers of xfrm_lookup() expect that dst_orig is released on error. But xfrm_lookup_route() may need dst_orig to handle certain error cases. So introduce a flag that tells what should be done in case of error. From Huaibin Wang. 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
ca00942a81
5 changed files with 10 additions and 8 deletions
|
@ -481,6 +481,7 @@ void dst_init(void);
|
|||
enum {
|
||||
XFRM_LOOKUP_ICMP = 1 << 0,
|
||||
XFRM_LOOKUP_QUEUE = 1 << 1,
|
||||
XFRM_LOOKUP_KEEP_DST_REF = 1 << 2,
|
||||
};
|
||||
|
||||
struct flowi;
|
||||
|
|
|
@ -63,6 +63,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
|||
return err;
|
||||
|
||||
IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
}
|
||||
|
@ -71,7 +72,6 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
|
|||
int xfrm4_output_finish(struct sk_buff *skb)
|
||||
{
|
||||
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
#ifdef CONFIG_NETFILTER
|
||||
IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
|
||||
|
|
|
@ -114,6 +114,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
|||
return err;
|
||||
|
||||
skb->ignore_df = 1;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
}
|
||||
|
@ -122,7 +123,6 @@ EXPORT_SYMBOL(xfrm6_prepare_output);
|
|||
int xfrm6_output_finish(struct sk_buff *skb)
|
||||
{
|
||||
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
|
||||
#ifdef CONFIG_NETFILTER
|
||||
IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
|
||||
|
|
|
@ -200,6 +200,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
|
|||
|
||||
#if IS_ENABLED(CONFIG_IPV6_MIP6)
|
||||
case IPPROTO_MH:
|
||||
offset += ipv6_optlen(exthdr);
|
||||
if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
|
||||
struct ip6_mh *mh;
|
||||
|
||||
|
|
|
@ -2269,11 +2269,9 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
|
|||
* have the xfrm_state's. We need to wait for KM to
|
||||
* negotiate new SA's or bail out with error.*/
|
||||
if (net->xfrm.sysctl_larval_drop) {
|
||||
dst_release(dst);
|
||||
xfrm_pols_put(pols, drop_pols);
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
|
||||
|
||||
return ERR_PTR(-EREMOTE);
|
||||
err = -EREMOTE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = -EAGAIN;
|
||||
|
@ -2324,7 +2322,8 @@ nopol:
|
|||
error:
|
||||
dst_release(dst);
|
||||
dropdst:
|
||||
dst_release(dst_orig);
|
||||
if (!(flags & XFRM_LOOKUP_KEEP_DST_REF))
|
||||
dst_release(dst_orig);
|
||||
xfrm_pols_put(pols, drop_pols);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
@ -2338,7 +2337,8 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
|
|||
struct sock *sk, int flags)
|
||||
{
|
||||
struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk,
|
||||
flags | XFRM_LOOKUP_QUEUE);
|
||||
flags | XFRM_LOOKUP_QUEUE |
|
||||
XFRM_LOOKUP_KEEP_DST_REF);
|
||||
|
||||
if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
|
||||
return make_blackhole(net, dst_orig->ops->family, dst_orig);
|
||||
|
|
Loading…
Reference in a new issue