Merge "af_key: unconditionally clone on broadcast"
This commit is contained in:
commit
1ba0161c4d
1 changed files with 15 additions and 25 deletions
|
@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
|
static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation,
|
||||||
gfp_t allocation, struct sock *sk)
|
struct sock *sk)
|
||||||
{
|
{
|
||||||
int err = -ENOBUFS;
|
int err = -ENOBUFS;
|
||||||
|
|
||||||
sock_hold(sk);
|
if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
|
||||||
if (*skb2 == NULL) {
|
return err;
|
||||||
if (atomic_read(&skb->users) != 1) {
|
|
||||||
*skb2 = skb_clone(skb, allocation);
|
skb = skb_clone(skb, allocation);
|
||||||
} else {
|
|
||||||
*skb2 = skb;
|
if (skb) {
|
||||||
atomic_inc(&skb->users);
|
skb_set_owner_r(skb, sk);
|
||||||
}
|
skb_queue_tail(&sk->sk_receive_queue, skb);
|
||||||
|
sk->sk_data_ready(sk);
|
||||||
|
err = 0;
|
||||||
}
|
}
|
||||||
if (*skb2 != NULL) {
|
|
||||||
if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
|
|
||||||
skb_set_owner_r(*skb2, sk);
|
|
||||||
skb_queue_tail(&sk->sk_receive_queue, *skb2);
|
|
||||||
sk->sk_data_ready(sk);
|
|
||||||
*skb2 = NULL;
|
|
||||||
err = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sock_put(sk);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
|
||||||
{
|
{
|
||||||
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
struct sk_buff *skb2 = NULL;
|
|
||||||
int err = -ESRCH;
|
int err = -ESRCH;
|
||||||
|
|
||||||
/* XXX Do we need something like netlink_overrun? I think
|
/* XXX Do we need something like netlink_overrun? I think
|
||||||
|
@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
|
||||||
* socket.
|
* socket.
|
||||||
*/
|
*/
|
||||||
if (pfk->promisc)
|
if (pfk->promisc)
|
||||||
pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
|
pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
|
||||||
|
|
||||||
/* the exact target will be processed later */
|
/* the exact target will be processed later */
|
||||||
if (sk == one_sk)
|
if (sk == one_sk)
|
||||||
|
@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
|
err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
|
||||||
|
|
||||||
/* Error is cleared after successful sending to at least one
|
/* Error is cleared after successful sending to at least one
|
||||||
* registered KM */
|
* registered KM */
|
||||||
|
@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (one_sk != NULL)
|
if (one_sk != NULL)
|
||||||
err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
|
err = pfkey_broadcast_one(skb, allocation, one_sk);
|
||||||
|
|
||||||
kfree_skb(skb2);
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue