Commit fde9cd69 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 2018-12-18

1) Fix error return code in xfrm_output_one()
   when no dst_entry is attached to the skb.
   From Wei Yongjun.

2) The xfrm state hash bucket count reported to
   userspace is off by one. Fix from Benjamin Poirier.

3) Fix NULL pointer dereference in xfrm_input when
   skb_dst_force clears the dst_entry.

4) Fix freeing of xfrm states on acquire. We use a
   dedicated slab cache for the xfrm states now,
   so free it properly with kmem_cache_free.
   From Mathias Krause.

Please pull or let me know if there are problems.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8d013b79 4a135e53
...@@ -1552,6 +1552,7 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, ...@@ -1552,6 +1552,7 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
int (*func)(struct xfrm_state *, int, void*), void *); int (*func)(struct xfrm_state *, int, void*), void *);
void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net); void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
struct xfrm_state *xfrm_state_alloc(struct net *net); struct xfrm_state *xfrm_state_alloc(struct net *net);
void xfrm_state_free(struct xfrm_state *x);
struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr, struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
const xfrm_address_t *saddr, const xfrm_address_t *saddr,
const struct flowi *fl, const struct flowi *fl,
......
...@@ -346,6 +346,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -346,6 +346,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
skb->sp->xvec[skb->sp->len++] = x; skb->sp->xvec[skb->sp->len++] = x;
skb_dst_force(skb);
if (!skb_dst(skb)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR);
goto drop;
}
lock: lock:
spin_lock(&x->lock); spin_lock(&x->lock);
...@@ -385,7 +391,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -385,7 +391,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
XFRM_SKB_CB(skb)->seq.input.low = seq; XFRM_SKB_CB(skb)->seq.input.low = seq;
XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
skb_dst_force(skb);
dev_hold(skb->dev); dev_hold(skb->dev);
if (crypto_done) if (crypto_done)
......
...@@ -102,6 +102,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) ...@@ -102,6 +102,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
skb_dst_force(skb); skb_dst_force(skb);
if (!skb_dst(skb)) { if (!skb_dst(skb)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
err = -EHOSTUNREACH;
goto error_nolock; goto error_nolock;
} }
......
...@@ -426,6 +426,12 @@ static void xfrm_put_mode(struct xfrm_mode *mode) ...@@ -426,6 +426,12 @@ static void xfrm_put_mode(struct xfrm_mode *mode)
module_put(mode->owner); module_put(mode->owner);
} }
void xfrm_state_free(struct xfrm_state *x)
{
kmem_cache_free(xfrm_state_cache, x);
}
EXPORT_SYMBOL(xfrm_state_free);
static void xfrm_state_gc_destroy(struct xfrm_state *x) static void xfrm_state_gc_destroy(struct xfrm_state *x)
{ {
tasklet_hrtimer_cancel(&x->mtimer); tasklet_hrtimer_cancel(&x->mtimer);
...@@ -452,7 +458,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) ...@@ -452,7 +458,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
} }
xfrm_dev_state_free(x); xfrm_dev_state_free(x);
security_xfrm_state_free(x); security_xfrm_state_free(x);
kmem_cache_free(xfrm_state_cache, x); xfrm_state_free(x);
} }
static void xfrm_state_gc_task(struct work_struct *work) static void xfrm_state_gc_task(struct work_struct *work)
...@@ -788,7 +794,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si) ...@@ -788,7 +794,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
{ {
spin_lock_bh(&net->xfrm.xfrm_state_lock); spin_lock_bh(&net->xfrm.xfrm_state_lock);
si->sadcnt = net->xfrm.state_num; si->sadcnt = net->xfrm.state_num;
si->sadhcnt = net->xfrm.state_hmask; si->sadhcnt = net->xfrm.state_hmask + 1;
si->sadhmcnt = xfrm_state_hashmax; si->sadhmcnt = xfrm_state_hashmax;
spin_unlock_bh(&net->xfrm.xfrm_state_lock); spin_unlock_bh(&net->xfrm.xfrm_state_lock);
} }
......
...@@ -2288,13 +2288,13 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2288,13 +2288,13 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
kfree(x); xfrm_state_free(x);
kfree(xp); kfree(xp);
return 0; return 0;
free_state: free_state:
kfree(x); xfrm_state_free(x);
nomem: nomem:
return err; return err;
} }
......
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