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); ...@@ -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); struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
void xfrm_policy_flush(void); void xfrm_policy_flush(void);
void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); 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_flush(void);
extern void xfrm_policy_kill(struct xfrm_policy *); extern void xfrm_policy_kill(struct xfrm_policy *);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); 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) ...@@ -386,7 +386,7 @@ xfrm_state_lookup(u32 daddr, u32 spi, u8 proto)
} }
struct xfrm_state * 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; struct xfrm_state *x, *x0;
unsigned h = ntohl(daddr); unsigned h = ntohl(daddr);
...@@ -400,10 +400,11 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr) ...@@ -400,10 +400,11 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
mode == x->props.mode && mode == x->props.mode &&
proto == x->id.proto && proto == x->id.proto &&
saddr == x->props.saddr.xfrm4_addr && saddr == x->props.saddr.xfrm4_addr &&
reqid == x->props.reqid) { reqid == x->props.reqid &&
x->km.state == XFRM_STATE_ACQ) {
if (!x0) if (!x0)
x0 = x; x0 = x;
if (x->km.state != XFRM_STATE_ACQ) if (x->id.spi)
continue; continue;
x0 = x; x0 = x;
break; break;
...@@ -411,7 +412,7 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr) ...@@ -411,7 +412,7 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
} }
if (x0) { if (x0) {
atomic_inc(&x0->refcnt); 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_addr = daddr;
x0->sel.daddr.xfrm4_mask = ~0; x0->sel.daddr.xfrm4_mask = ~0;
x0->sel.saddr.xfrm4_addr = saddr; x0->sel.saddr.xfrm4_addr = saddr;
......
...@@ -528,8 +528,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void ** ...@@ -528,8 +528,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **
switch (((struct sockaddr *)(addr + 1))->sa_family) { switch (((struct sockaddr *)(addr + 1))->sa_family) {
case AF_INET: case AF_INET:
x = xfrm_state_lookup( x = xfrm_state_lookup(((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
sa->sadb_sa_spi, proto); sa->sadb_sa_spi, proto);
break; break;
case AF_INET6: case AF_INET6:
...@@ -1043,7 +1042,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h ...@@ -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); daddr = (struct sockaddr_in*)(addr + 1);
x = xfrm_find_acq(mode, reqid, proto, daddr->sin_addr.s_addr, 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) if (x == NULL)
return -ENOENT; return -ENOENT;
...@@ -1122,7 +1121,17 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, ...@@ -1122,7 +1121,17 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
/* XXX there is race condition */ /* XXX there is race condition */
x1 = pfkey_xfrm_state_lookup(hdr, ext_hdrs); 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; x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x); xfrm_state_put(x);
xfrm_state_put(x1); xfrm_state_put(x1);
...@@ -1131,7 +1140,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, ...@@ -1131,7 +1140,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
xfrm_state_insert(x); xfrm_state_insert(x);
if (x1 && hdr->sadb_msg_type != SADB_ADD) { if (x1) {
xfrm_state_delete(x1); xfrm_state_delete(x1);
xfrm_state_put(x1); xfrm_state_put(x1);
} }
...@@ -2156,7 +2165,7 @@ static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int ...@@ -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)) (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND))
return NULL; return NULL;
xp = xfrm_policy_alloc(GFP_KERNEL); xp = xfrm_policy_alloc(GFP_ATOMIC);
if (xp == NULL) { if (xp == NULL) {
*dir = -ENOBUFS; *dir = -ENOBUFS;
return NULL; 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