aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-11-25 20:16:11 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-25 20:16:11 -0500
commit9d4139c76905833afcb77fe8ccc17f302a0eb9ab (patch)
tree40cb6b05eeffd0478f6d767effaa5d346aa3df82
parent673c09be457bb23aa0eaaa79804cbb342210d195 (diff)
netns xfrm: per-netns xfrm_state_all list
This is done to get a) simple "something leaked" check b) cover possible DoSes when other netns puts many, many xfrm_states onto a list. c) not miss "alien xfrm_state" check in some of list iterators in future. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netns/xfrm.h3
-rw-r--r--net/xfrm/xfrm_state.c14
2 files changed, 11 insertions, 6 deletions
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 1cb0024a3b47..6ae234a16517 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -1,7 +1,10 @@
1#ifndef __NETNS_XFRM_H 1#ifndef __NETNS_XFRM_H
2#define __NETNS_XFRM_H 2#define __NETNS_XFRM_H
3 3
4#include <linux/list.h>
5
4struct netns_xfrm { 6struct netns_xfrm {
7 struct list_head state_all;
5}; 8};
6 9
7#endif 10#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 81bde76d049c..85bb85484b70 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,7 +50,6 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
50 * Main use is finding SA after policy selected tunnel or transport mode. 50 * Main use is finding SA after policy selected tunnel or transport mode.
51 * Also, it can be used by ah/esp icmp error handler to find offending SA. 51 * Also, it can be used by ah/esp icmp error handler to find offending SA.
52 */ 52 */
53static LIST_HEAD(xfrm_state_all);
54static struct hlist_head *xfrm_state_bydst __read_mostly; 53static struct hlist_head *xfrm_state_bydst __read_mostly;
55static struct hlist_head *xfrm_state_bysrc __read_mostly; 54static struct hlist_head *xfrm_state_bysrc __read_mostly;
56static struct hlist_head *xfrm_state_byspi __read_mostly; 55static struct hlist_head *xfrm_state_byspi __read_mostly;
@@ -855,7 +854,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
855 854
856 if (km_query(x, tmpl, pol) == 0) { 855 if (km_query(x, tmpl, pol) == 0) {
857 x->km.state = XFRM_STATE_ACQ; 856 x->km.state = XFRM_STATE_ACQ;
858 list_add(&x->km.all, &xfrm_state_all); 857 list_add(&x->km.all, &init_net.xfrm.state_all);
859 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 858 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
860 h = xfrm_src_hash(daddr, saddr, family); 859 h = xfrm_src_hash(daddr, saddr, family);
861 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 860 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -924,7 +923,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
924 923
925 x->genid = ++xfrm_state_genid; 924 x->genid = ++xfrm_state_genid;
926 925
927 list_add(&x->km.all, &xfrm_state_all); 926 list_add(&x->km.all, &init_net.xfrm.state_all);
928 927
929 h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, 928 h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
930 x->props.reqid, x->props.family); 929 x->props.reqid, x->props.family);
@@ -1053,7 +1052,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
1053 xfrm_state_hold(x); 1052 xfrm_state_hold(x);
1054 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; 1053 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
1055 add_timer(&x->timer); 1054 add_timer(&x->timer);
1056 list_add(&x->km.all, &xfrm_state_all); 1055 list_add(&x->km.all, &init_net.xfrm.state_all);
1057 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 1056 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
1058 h = xfrm_src_hash(daddr, saddr, family); 1057 h = xfrm_src_hash(daddr, saddr, family);
1059 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 1058 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -1559,10 +1558,10 @@ int xfrm_state_walk(struct xfrm_state_walk *walk,
1559 1558
1560 spin_lock_bh(&xfrm_state_lock); 1559 spin_lock_bh(&xfrm_state_lock);
1561 if (list_empty(&walk->all)) 1560 if (list_empty(&walk->all))
1562 x = list_first_entry(&xfrm_state_all, struct xfrm_state_walk, all); 1561 x = list_first_entry(&init_net.xfrm.state_all, struct xfrm_state_walk, all);
1563 else 1562 else
1564 x = list_entry(&walk->all, struct xfrm_state_walk, all); 1563 x = list_entry(&walk->all, struct xfrm_state_walk, all);
1565 list_for_each_entry_from(x, &xfrm_state_all, all) { 1564 list_for_each_entry_from(x, &init_net.xfrm.state_all, all) {
1566 if (x->state == XFRM_STATE_DEAD) 1565 if (x->state == XFRM_STATE_DEAD)
1567 continue; 1566 continue;
1568 state = container_of(x, struct xfrm_state, km); 1567 state = container_of(x, struct xfrm_state, km);
@@ -2085,6 +2084,8 @@ int __net_init xfrm_state_init(struct net *net)
2085{ 2084{
2086 unsigned int sz; 2085 unsigned int sz;
2087 2086
2087 INIT_LIST_HEAD(&net->xfrm.state_all);
2088
2088 sz = sizeof(struct hlist_head) * 8; 2089 sz = sizeof(struct hlist_head) * 8;
2089 2090
2090 xfrm_state_bydst = xfrm_hash_alloc(sz); 2091 xfrm_state_bydst = xfrm_hash_alloc(sz);
@@ -2100,6 +2101,7 @@ int __net_init xfrm_state_init(struct net *net)
2100 2101
2101void xfrm_state_fini(struct net *net) 2102void xfrm_state_fini(struct net *net)
2102{ 2103{
2104 WARN_ON(!list_empty(&net->xfrm.state_all));
2103} 2105}
2104 2106
2105#ifdef CONFIG_AUDITSYSCALL 2107#ifdef CONFIG_AUDITSYSCALL