aboutsummaryrefslogtreecommitdiffstats
path: root/net/key
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2008-10-01 08:17:54 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-01 08:17:54 -0400
commit0523820482dcb42784572ffd2296c2f08c275a2b (patch)
tree19a31ae7b58a650fd58dab39a391aba3f7e3a23a /net/key
parent5dc121e9a7a8a3721cefeb07f3559f50fbedc67e (diff)
af_key: Free dumping state on socket close
Fix a xfrm_{state,policy}_walk leak if pfkey socket is closed while dumping is on-going. Signed-off-by: Timo Teras <timo.teras@iki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/key')
-rw-r--r--net/key/af_key.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index d628df97e02e..b7f5a1c353ee 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -73,22 +73,18 @@ static int pfkey_can_dump(struct sock *sk)
73 return 0; 73 return 0;
74} 74}
75 75
76static int pfkey_do_dump(struct pfkey_sock *pfk) 76static void pfkey_terminate_dump(struct pfkey_sock *pfk)
77{ 77{
78 int rc; 78 if (pfk->dump.dump) {
79 79 pfk->dump.done(pfk);
80 rc = pfk->dump.dump(pfk); 80 pfk->dump.dump = NULL;
81 if (rc == -ENOBUFS) 81 pfk->dump.done = NULL;
82 return 0; 82 }
83
84 pfk->dump.done(pfk);
85 pfk->dump.dump = NULL;
86 pfk->dump.done = NULL;
87 return rc;
88} 83}
89 84
90static void pfkey_sock_destruct(struct sock *sk) 85static void pfkey_sock_destruct(struct sock *sk)
91{ 86{
87 pfkey_terminate_dump(pfkey_sk(sk));
92 skb_queue_purge(&sk->sk_receive_queue); 88 skb_queue_purge(&sk->sk_receive_queue);
93 89
94 if (!sock_flag(sk, SOCK_DEAD)) { 90 if (!sock_flag(sk, SOCK_DEAD)) {
@@ -310,6 +306,18 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
310 return err; 306 return err;
311} 307}
312 308
309static int pfkey_do_dump(struct pfkey_sock *pfk)
310{
311 int rc;
312
313 rc = pfk->dump.dump(pfk);
314 if (rc == -ENOBUFS)
315 return 0;
316
317 pfkey_terminate_dump(pfk);
318 return rc;
319}
320
313static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) 321static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig)
314{ 322{
315 *new = *orig; 323 *new = *orig;