Commit 217040ae authored by Alexey Kuznetsov's avatar Alexey Kuznetsov Committed by David S. Miller

[IPSEC]: More pfkey2 semantic fixes.

- xfrm_state.c: never return mature SAs on getspi.
- af_key.c: do not forget to delete dummy super-larvals when they are resolved
- af_key.c: wow! specially for this case I added gfp argument
            to xfrm_alloc_policy() and forgot to use it really.
parent b423fed1
......@@ -371,7 +371,7 @@ struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel);
struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
void xfrm_policy_flush(void);
void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr);
struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create);
extern void xfrm_policy_flush(void);
extern void xfrm_policy_kill(struct xfrm_policy *);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
......
......@@ -386,7 +386,7 @@ xfrm_state_lookup(u32 daddr, u32 spi, u8 proto)
}
struct xfrm_state *
xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
{
struct xfrm_state *x, *x0;
unsigned h = ntohl(daddr);
......@@ -400,10 +400,11 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
mode == x->props.mode &&
proto == x->id.proto &&
saddr == x->props.saddr.xfrm4_addr &&
reqid == x->props.reqid) {
reqid == x->props.reqid &&
x->km.state == XFRM_STATE_ACQ) {
if (!x0)
x0 = x;
if (x->km.state != XFRM_STATE_ACQ)
if (x->id.spi)
continue;
x0 = x;
break;
......@@ -411,7 +412,7 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
}
if (x0) {
atomic_inc(&x0->refcnt);
} else if ((x0 = xfrm_state_alloc()) != NULL) {
} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
x0->sel.daddr.xfrm4_addr = daddr;
x0->sel.daddr.xfrm4_mask = ~0;
x0->sel.saddr.xfrm4_addr = saddr;
......
......@@ -528,8 +528,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **
switch (((struct sockaddr *)(addr + 1))->sa_family) {
case AF_INET:
x = xfrm_state_lookup(
((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
x = xfrm_state_lookup(((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
sa->sadb_sa_spi, proto);
break;
case AF_INET6:
......@@ -1043,7 +1042,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
daddr = (struct sockaddr_in*)(addr + 1);
x = xfrm_find_acq(mode, reqid, proto, daddr->sin_addr.s_addr,
saddr->sin_addr.s_addr);
saddr->sin_addr.s_addr, 1);
if (x == NULL)
return -ENOENT;
......@@ -1122,7 +1121,17 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
/* XXX there is race condition */
x1 = pfkey_xfrm_state_lookup(hdr, ext_hdrs);
if (x1 && hdr->sadb_msg_type == SADB_ADD) {
if (!x1) {
x1 = xfrm_find_acq(x->props.mode, x->props.reqid, x->id.proto,
x->id.daddr.xfrm4_addr,
x->props.saddr.xfrm4_addr, 0);
if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
xfrm_state_put(x1);
x1 = NULL;
}
}
if (x1 && x1->id.spi && hdr->sadb_msg_type == SADB_ADD) {
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
xfrm_state_put(x1);
......@@ -1131,7 +1140,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
xfrm_state_insert(x);
if (x1 && hdr->sadb_msg_type != SADB_ADD) {
if (x1) {
xfrm_state_delete(x1);
xfrm_state_put(x1);
}
......@@ -2156,7 +2165,7 @@ static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int
(!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND))
return NULL;
xp = xfrm_policy_alloc(GFP_KERNEL);
xp = xfrm_policy_alloc(GFP_ATOMIC);
if (xp == NULL) {
*dir = -ENOBUFS;
return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment