aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-12-18 14:43:26 -0500
committerDavid S. Miller <davem@davemloft.net>2018-12-18 14:43:26 -0500
commitfde9cd69a59f7ee405c87fff84bc08fa2a550e47 (patch)
tree886cc9496c272128a0b27b1b23cf6f14c292e209 /net/xfrm
parent8d013b7910599a06405fb37d6def4dde7cab7984 (diff)
parent4a135e538962cb00a9667c82e7d2b9e4d7cd7177 (diff)
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: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_input.c7
-rw-r--r--net/xfrm/xfrm_output.c1
-rw-r--r--net/xfrm/xfrm_state.c10
-rw-r--r--net/xfrm/xfrm_user.c4
4 files changed, 17 insertions, 5 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 684c0bc01e2c..d5635908587f 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -346,6 +346,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
346 346
347 skb->sp->xvec[skb->sp->len++] = x; 347 skb->sp->xvec[skb->sp->len++] = x;
348 348
349 skb_dst_force(skb);
350 if (!skb_dst(skb)) {
351 XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR);
352 goto drop;
353 }
354
349lock: 355lock:
350 spin_lock(&x->lock); 356 spin_lock(&x->lock);
351 357
@@ -385,7 +391,6 @@ lock:
385 XFRM_SKB_CB(skb)->seq.input.low = seq; 391 XFRM_SKB_CB(skb)->seq.input.low = seq;
386 XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; 392 XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
387 393
388 skb_dst_force(skb);
389 dev_hold(skb->dev); 394 dev_hold(skb->dev);
390 395
391 if (crypto_done) 396 if (crypto_done)
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 4ae87c5ce2e3..fef6b2da3c5d 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -102,6 +102,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
102 skb_dst_force(skb); 102 skb_dst_force(skb);
103 if (!skb_dst(skb)) { 103 if (!skb_dst(skb)) {
104 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); 104 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
105 err = -EHOSTUNREACH;
105 goto error_nolock; 106 goto error_nolock;
106 } 107 }
107 108
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index dc4a9f1fb941..23c92891758a 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -426,6 +426,12 @@ static void xfrm_put_mode(struct xfrm_mode *mode)
426 module_put(mode->owner); 426 module_put(mode->owner);
427} 427}
428 428
429void xfrm_state_free(struct xfrm_state *x)
430{
431 kmem_cache_free(xfrm_state_cache, x);
432}
433EXPORT_SYMBOL(xfrm_state_free);
434
429static void xfrm_state_gc_destroy(struct xfrm_state *x) 435static void xfrm_state_gc_destroy(struct xfrm_state *x)
430{ 436{
431 tasklet_hrtimer_cancel(&x->mtimer); 437 tasklet_hrtimer_cancel(&x->mtimer);
@@ -452,7 +458,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
452 } 458 }
453 xfrm_dev_state_free(x); 459 xfrm_dev_state_free(x);
454 security_xfrm_state_free(x); 460 security_xfrm_state_free(x);
455 kmem_cache_free(xfrm_state_cache, x); 461 xfrm_state_free(x);
456} 462}
457 463
458static void xfrm_state_gc_task(struct work_struct *work) 464static 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{ 794{
789 spin_lock_bh(&net->xfrm.xfrm_state_lock); 795 spin_lock_bh(&net->xfrm.xfrm_state_lock);
790 si->sadcnt = net->xfrm.state_num; 796 si->sadcnt = net->xfrm.state_num;
791 si->sadhcnt = net->xfrm.state_hmask; 797 si->sadhcnt = net->xfrm.state_hmask + 1;
792 si->sadhmcnt = xfrm_state_hashmax; 798 si->sadhmcnt = xfrm_state_hashmax;
793 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 799 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
794} 800}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c9a84e22f5d5..277c1c46fe94 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2288,13 +2288,13 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
2288 2288
2289 } 2289 }
2290 2290
2291 kfree(x); 2291 xfrm_state_free(x);
2292 kfree(xp); 2292 kfree(xp);
2293 2293
2294 return 0; 2294 return 0;
2295 2295
2296free_state: 2296free_state:
2297 kfree(x); 2297 xfrm_state_free(x);
2298nomem: 2298nomem:
2299 return err; 2299 return err;
2300} 2300}