Skip to content

Commit

Permalink
bpf: try harder on clones when writing into skb
Browse files Browse the repository at this point in the history
[ Upstream commit 3697649ff29e0f647565eed04b27a7779c646a22 ]

When we're dealing with clones and the area is not writeable, try
harder and get a copy via pskb_expand_head(). Replace also other
occurences in tc actions with the new skb_try_make_writable().

Reported-by: Ashhad Sheikh <ashhadsheikh394@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Change-Id: I4dcd1acf037219a6d74263a0de07f64022101444
  • Loading branch information
borkmann authored and Lee Jones committed Dec 9, 2020
1 parent 8933239 commit 398615c
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 19 deletions.
7 changes: 7 additions & 0 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -2433,6 +2433,13 @@ static inline int skb_clone_writable(const struct sk_buff *skb, unsigned int len
skb_headroom(skb) + len <= skb->hdr_len;
}

static inline int skb_try_make_writable(struct sk_buff *skb,
unsigned int write_len)
{
return skb_cloned(skb) && !skb_clone_writable(skb, write_len) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
}

static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
int cloned)
{
Expand Down
8 changes: 2 additions & 6 deletions net/sched/act_csum.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@ static void *tcf_csum_skb_nextlayer(struct sk_buff *skb,
int hl = ihl + jhl;

if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) ||
(skb_cloned(skb) &&
!skb_clone_writable(skb, hl + ntkoff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
skb_try_make_writable(skb, hl + ntkoff))
return NULL;
else
return (void *)(skb_network_header(skb) + ihl);
Expand Down Expand Up @@ -376,9 +374,7 @@ static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
}

if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) {
if (skb_cloned(skb) &&
!skb_clone_writable(skb, sizeof(*iph) + ntkoff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
if (skb_try_make_writable(skb, sizeof(*iph) + ntkoff))
goto fail;

ip_send_check(ip_hdr(skb));
Expand Down
18 changes: 5 additions & 13 deletions net/sched/act_nat.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
addr = iph->daddr;

if (!((old_addr ^ addr) & mask)) {
if (skb_cloned(skb) &&
!skb_clone_writable(skb, sizeof(*iph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
if (skb_try_make_writable(skb, sizeof(*iph) + noff))
goto drop;

new_addr &= mask;
Expand Down Expand Up @@ -155,9 +153,7 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
struct tcphdr *tcph;

if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) ||
(skb_cloned(skb) &&
!skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
skb_try_make_writable(skb, ihl + sizeof(*tcph) + noff))
goto drop;

tcph = (void *)(skb_network_header(skb) + ihl);
Expand All @@ -169,9 +165,7 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
struct udphdr *udph;

if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) ||
(skb_cloned(skb) &&
!skb_clone_writable(skb, ihl + sizeof(*udph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
skb_try_make_writable(skb, ihl + sizeof(*udph) + noff))
goto drop;

udph = (void *)(skb_network_header(skb) + ihl);
Expand Down Expand Up @@ -211,10 +205,8 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
if ((old_addr ^ addr) & mask)
break;

if (skb_cloned(skb) &&
!skb_clone_writable(skb, ihl + sizeof(*icmph) +
sizeof(*iph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
if (skb_try_make_writable(skb, ihl + sizeof(*icmph) +
sizeof(*iph) + noff))
goto drop;

icmph = (void *)(skb_network_header(skb) + ihl);
Expand Down

0 comments on commit 398615c

Please sign in to comment.