aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2005-06-19 01:45:31 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-19 01:45:31 -0400
commit7d6dfe1f5bc4c56e0c31173014a099ec3fa35907 (patch)
treea6b04337c4f6d1ff7b050082dc7e69dc5617d3d0
parentf60f6b8f70c756fc786d68f02ec17a1e84db645f (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>
-rw-r--r--net/key/af_key.c4
-rw-r--r--net/xfrm/xfrm_user.c4
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);
1346out:
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);
307out:
307 xfrm_state_put(x); 308 xfrm_state_put(x);
308
309 return err; 309 return err;
310} 310}
311 311