diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2008-11-25 20:16:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-25 20:16:11 -0500 |
commit | 9d4139c76905833afcb77fe8ccc17f302a0eb9ab (patch) | |
tree | 40cb6b05eeffd0478f6d767effaa5d346aa3df82 /net/xfrm | |
parent | 673c09be457bb23aa0eaaa79804cbb342210d195 (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>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_state.c | 14 |
1 files changed, 8 insertions, 6 deletions
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 | */ |
53 | static LIST_HEAD(xfrm_state_all); | ||
54 | static struct hlist_head *xfrm_state_bydst __read_mostly; | 53 | static struct hlist_head *xfrm_state_bydst __read_mostly; |
55 | static struct hlist_head *xfrm_state_bysrc __read_mostly; | 54 | static struct hlist_head *xfrm_state_bysrc __read_mostly; |
56 | static struct hlist_head *xfrm_state_byspi __read_mostly; | 55 | static 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 | ||
2101 | void xfrm_state_fini(struct net *net) | 2102 | void 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 |