Commit 5a5df594 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[NETLINK]: Unshare SKB, as necessary, in netlink_trim()

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0e91e70f
......@@ -660,7 +660,7 @@ void netlink_detachskb(struct sock *sk, struct sk_buff *skb)
sock_put(sk);
}
static inline void netlink_trim(struct sk_buff *skb, int allocation)
static inline struct sk_buff *netlink_trim(struct sk_buff *skb, int allocation)
{
int delta;
......@@ -668,10 +668,20 @@ static inline void netlink_trim(struct sk_buff *skb, int allocation)
delta = skb->end - skb->tail;
if (delta * 2 < skb->truesize)
return;
if (pskb_expand_head(skb, 0, -delta, allocation))
return;
return skb;
if (skb_shared(skb)) {
struct sk_buff *nskb = skb_clone(skb, allocation);
if (!nskb)
return skb;
kfree_skb(skb);
skb = nskb;
}
if (!pskb_expand_head(skb, 0, -delta, allocation))
skb->truesize -= delta;
return skb;
}
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock)
......@@ -680,7 +690,7 @@ int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock
int err;
long timeo;
netlink_trim(skb, gfp_any());
skb = netlink_trim(skb, gfp_any());
timeo = sock_sndtimeo(ssk, nonblock);
retry:
......@@ -778,6 +788,8 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
struct hlist_node *node;
struct sock *sk;
skb = netlink_trim(skb, allocation);
info.exclude_sk = ssk;
info.pid = pid;
info.group = group;
......@@ -788,8 +800,6 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
info.skb = skb;
info.skb2 = NULL;
netlink_trim(skb, allocation);
/* While we sleep in clone, do not allow to change socket list */
netlink_lock_table();
......
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