aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/xfrm.h
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-09-22 22:48:19 -0400
committerDavid S. Miller <davem@davemloft.net>2008-09-22 22:48:19 -0400
commit5c1824587f0797373c95719a196f6098f7c6d20c (patch)
treec3a5af01afc01d88e111c7e1821b03bf404566f6 /include/net/xfrm.h
parentfcaa40669cd798ca2ac0d15441e8a1d1145f2b16 (diff)
ipsec: Fix xfrm_state_walk race
As discovered by Timo Teräs, the currently xfrm_state_walk scheme is racy because if a second dump finishes before the first, we may free xfrm states that the first dump would walk over later. This patch fixes this by storing the dumps in a list in order to calculate the correct completion counter which cures this problem. I've expanded netlink_cb in order to accomodate the extra state related to this. It shouldn't be a big deal since netlink_cb is kmalloced for each dump and we're just increasing it by 4 or 8 bytes. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/xfrm.h')
-rw-r--r--include/net/xfrm.h10
1 files changed, 3 insertions, 7 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4bb94992b5fa..48630b266593 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1246,6 +1246,8 @@ struct xfrm6_tunnel {
1246}; 1246};
1247 1247
1248struct xfrm_state_walk { 1248struct xfrm_state_walk {
1249 struct list_head list;
1250 unsigned long genid;
1249 struct xfrm_state *state; 1251 struct xfrm_state *state;
1250 int count; 1252 int count;
1251 u8 proto; 1253 u8 proto;
@@ -1281,13 +1283,7 @@ static inline void xfrm6_fini(void)
1281extern int xfrm_proc_init(void); 1283extern int xfrm_proc_init(void);
1282#endif 1284#endif
1283 1285
1284static inline void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto) 1286extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
1285{
1286 walk->proto = proto;
1287 walk->state = NULL;
1288 walk->count = 0;
1289}
1290
1291extern int xfrm_state_walk(struct xfrm_state_walk *walk, 1287extern int xfrm_state_walk(struct xfrm_state_walk *walk,
1292 int (*func)(struct xfrm_state *, int, void*), void *); 1288 int (*func)(struct xfrm_state *, int, void*), void *);
1293extern void xfrm_state_walk_done(struct xfrm_state_walk *walk); 1289extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);