diff options
Diffstat (limited to 'net/netlink/af_netlink.c')
| -rw-r--r-- | net/netlink/af_netlink.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 733bf52cef3e..e41ce458c2a9 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -735,11 +735,15 @@ static inline int do_one_broadcast(struct sock *sk, | |||
| 735 | 735 | ||
| 736 | sock_hold(sk); | 736 | sock_hold(sk); |
| 737 | if (p->skb2 == NULL) { | 737 | if (p->skb2 == NULL) { |
| 738 | if (atomic_read(&p->skb->users) != 1) { | 738 | if (skb_shared(p->skb)) { |
| 739 | p->skb2 = skb_clone(p->skb, p->allocation); | 739 | p->skb2 = skb_clone(p->skb, p->allocation); |
| 740 | } else { | 740 | } else { |
| 741 | p->skb2 = p->skb; | 741 | p->skb2 = skb_get(p->skb); |
| 742 | atomic_inc(&p->skb->users); | 742 | /* |
| 743 | * skb ownership may have been set when | ||
| 744 | * delivered to a previous socket. | ||
| 745 | */ | ||
| 746 | skb_orphan(p->skb2); | ||
| 743 | } | 747 | } |
| 744 | } | 748 | } |
| 745 | if (p->skb2 == NULL) { | 749 | if (p->skb2 == NULL) { |
| @@ -785,11 +789,12 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
| 785 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) | 789 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) |
| 786 | do_one_broadcast(sk, &info); | 790 | do_one_broadcast(sk, &info); |
| 787 | 791 | ||
| 792 | kfree_skb(skb); | ||
| 793 | |||
| 788 | netlink_unlock_table(); | 794 | netlink_unlock_table(); |
| 789 | 795 | ||
| 790 | if (info.skb2) | 796 | if (info.skb2) |
| 791 | kfree_skb(info.skb2); | 797 | kfree_skb(info.skb2); |
| 792 | kfree_skb(skb); | ||
| 793 | 798 | ||
| 794 | if (info.delivered) { | 799 | if (info.delivered) { |
| 795 | if (info.congested && (allocation & __GFP_WAIT)) | 800 | if (info.congested && (allocation & __GFP_WAIT)) |
