diff options
author | Patrick McHardy <kaber@trash.net> | 2005-06-19 01:45:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-06-19 01:45:31 -0400 |
commit | 7d6dfe1f5bc4c56e0c31173014a099ec3fa35907 (patch) | |
tree | a6b04337c4f6d1ff7b050082dc7e69dc5617d3d0 /net | |
parent | f60f6b8f70c756fc786d68f02ec17a1e84db645f (diff) |
[IPSEC] Fix xfrm_state leaks in error path
Herbert Xu wrote:
> @@ -1254,6 +1326,7 @@ static int pfkey_add(struct sock *sk, st
> if (IS_ERR(x))
> return PTR_ERR(x);
>
> + xfrm_state_hold(x);
This introduces a leak when xfrm_state_add()/xfrm_state_update()
fail. We hold two references (one from xfrm_state_alloc(), one
from xfrm_state_hold()), but only drop one. We need to take the
reference because the reference from xfrm_state_alloc() can
be dropped by __xfrm_state_delete(), so the fix is to drop both
references on error. Same problem in xfrm_user.c.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/key/af_key.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 4 |
2 files changed, 4 insertions, 4 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index 577f0bb5bb31..98b72f2024ff 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -1333,7 +1333,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, | |||
1333 | if (err < 0) { | 1333 | if (err < 0) { |
1334 | x->km.state = XFRM_STATE_DEAD; | 1334 | x->km.state = XFRM_STATE_DEAD; |
1335 | xfrm_state_put(x); | 1335 | xfrm_state_put(x); |
1336 | return err; | 1336 | goto out; |
1337 | } | 1337 | } |
1338 | 1338 | ||
1339 | if (hdr->sadb_msg_type == SADB_ADD) | 1339 | if (hdr->sadb_msg_type == SADB_ADD) |
@@ -1343,8 +1343,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, | |||
1343 | c.seq = hdr->sadb_msg_seq; | 1343 | c.seq = hdr->sadb_msg_seq; |
1344 | c.pid = hdr->sadb_msg_pid; | 1344 | c.pid = hdr->sadb_msg_pid; |
1345 | km_state_notify(x, &c); | 1345 | km_state_notify(x, &c); |
1346 | out: | ||
1346 | xfrm_state_put(x); | 1347 | xfrm_state_put(x); |
1347 | |||
1348 | return err; | 1348 | return err; |
1349 | } | 1349 | } |
1350 | 1350 | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index bc4fd7456873..9d30f732a273 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -296,7 +296,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | |||
296 | if (err < 0) { | 296 | if (err < 0) { |
297 | x->km.state = XFRM_STATE_DEAD; | 297 | x->km.state = XFRM_STATE_DEAD; |
298 | xfrm_state_put(x); | 298 | xfrm_state_put(x); |
299 | return err; | 299 | goto out; |
300 | } | 300 | } |
301 | 301 | ||
302 | c.seq = nlh->nlmsg_seq; | 302 | c.seq = nlh->nlmsg_seq; |
@@ -304,8 +304,8 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | |||
304 | c.event = nlh->nlmsg_type; | 304 | c.event = nlh->nlmsg_type; |
305 | 305 | ||
306 | km_state_notify(x, &c); | 306 | km_state_notify(x, &c); |
307 | out: | ||
307 | xfrm_state_put(x); | 308 | xfrm_state_put(x); |
308 | |||
309 | return err; | 309 | return err; |
310 | } | 310 | } |
311 | 311 | ||