summaryrefslogtreecommitdiffstats
path: root/net/key
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2008-10-01 05:17:54 -0700
committerDavid S. Miller <davem@davemloft.net>2008-10-01 05:17:54 -0700
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 d628df97e02..b7f5a1c353e 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)
return 0;
}
-static int pfkey_do_dump(struct pfkey_sock *pfk)
+static void pfkey_terminate_dump(struct pfkey_sock *pfk)
{
- int rc;
-
- rc = pfk->dump.dump(pfk);
- if (rc == -ENOBUFS)
- return 0;
-
- pfk->dump.done(pfk);
- pfk->dump.dump = NULL;
- pfk->dump.done = NULL;
- return rc;
+ if (pfk->dump.dump) {
+ pfk->dump.done(pfk);
+ pfk->dump.dump = NULL;
+ pfk->dump.done = NULL;
+ }
}
static void pfkey_sock_destruct(struct sock *sk)
{
+ pfkey_terminate_dump(pfkey_sk(sk));
skb_queue_purge(&sk->sk_receive_queue);
if (!sock_flag(sk, SOCK_DEAD)) {
@@ -310,6 +306,18 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
return err;
}
+static int pfkey_do_dump(struct pfkey_sock *pfk)
+{
+ int rc;
+
+ rc = pfk->dump.dump(pfk);
+ if (rc == -ENOBUFS)
+ return 0;
+
+ pfkey_terminate_dump(pfk);
+ return rc;
+}
+
static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig)
{
*new = *orig;