Commit 21cafc1d authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller

bpf: remove artificial bpf_skb_{load, store}_bytes buffer limitation

We currently limit bpf_skb_store_bytes() and bpf_skb_load_bytes()
helpers to only store or load a maximum buffer of 16 bytes. Thus,
loading, rewriting and storing headers require several bpf_skb_load_bytes()
and bpf_skb_store_bytes() calls.

Also here we can use a per-cpu scratch buffer instead in order to not
pressure stack space any further. I do suspect that this limit was mainly
set in place for this particular reason. So, ease program development
by removing this limitation and make the scratchpad generic, so it can
be reused.
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d672345
...@@ -1333,15 +1333,22 @@ int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk) ...@@ -1333,15 +1333,22 @@ int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)
return 0; return 0;
} }
#define BPF_LDST_LEN 16U struct bpf_scratchpad {
union {
__be32 diff[MAX_BPF_STACK / sizeof(__be32)];
u8 buff[MAX_BPF_STACK];
};
};
static DEFINE_PER_CPU(struct bpf_scratchpad, bpf_sp);
static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags)
{ {
struct bpf_scratchpad *sp = this_cpu_ptr(&bpf_sp);
struct sk_buff *skb = (struct sk_buff *) (long) r1; struct sk_buff *skb = (struct sk_buff *) (long) r1;
int offset = (int) r2; int offset = (int) r2;
void *from = (void *) (long) r3; void *from = (void *) (long) r3;
unsigned int len = (unsigned int) r4; unsigned int len = (unsigned int) r4;
char buf[BPF_LDST_LEN];
void *ptr; void *ptr;
if (unlikely(flags & ~(BPF_F_RECOMPUTE_CSUM))) if (unlikely(flags & ~(BPF_F_RECOMPUTE_CSUM)))
...@@ -1355,14 +1362,14 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) ...@@ -1355,14 +1362,14 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags)
* *
* so check for invalid 'offset' and too large 'len' * so check for invalid 'offset' and too large 'len'
*/ */
if (unlikely((u32) offset > 0xffff || len > sizeof(buf))) if (unlikely((u32) offset > 0xffff || len > sizeof(sp->buff)))
return -EFAULT; return -EFAULT;
if (unlikely(skb_cloned(skb) && if (unlikely(skb_cloned(skb) &&
!skb_clone_writable(skb, offset + len))) !skb_clone_writable(skb, offset + len)))
return -EFAULT; return -EFAULT;
ptr = skb_header_pointer(skb, offset, len, buf); ptr = skb_header_pointer(skb, offset, len, sp->buff);
if (unlikely(!ptr)) if (unlikely(!ptr))
return -EFAULT; return -EFAULT;
...@@ -1371,7 +1378,7 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) ...@@ -1371,7 +1378,7 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags)
memcpy(ptr, from, len); memcpy(ptr, from, len);
if (ptr == buf) if (ptr == sp->buff)
/* skb_store_bits cannot return -EFAULT here */ /* skb_store_bits cannot return -EFAULT here */
skb_store_bits(skb, offset, ptr, len); skb_store_bits(skb, offset, ptr, len);
...@@ -1400,7 +1407,7 @@ static u64 bpf_skb_load_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) ...@@ -1400,7 +1407,7 @@ static u64 bpf_skb_load_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
unsigned int len = (unsigned int) r4; unsigned int len = (unsigned int) r4;
void *ptr; void *ptr;
if (unlikely((u32) offset > 0xffff || len > BPF_LDST_LEN)) if (unlikely((u32) offset > 0xffff || len > MAX_BPF_STACK))
return -EFAULT; return -EFAULT;
ptr = skb_header_pointer(skb, offset, len, to); ptr = skb_header_pointer(skb, offset, len, to);
...@@ -1525,15 +1532,9 @@ const struct bpf_func_proto bpf_l4_csum_replace_proto = { ...@@ -1525,15 +1532,9 @@ const struct bpf_func_proto bpf_l4_csum_replace_proto = {
.arg5_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING,
}; };
struct bpf_csum_scratchpad {
__be32 diff[128];
};
static DEFINE_PER_CPU(struct bpf_csum_scratchpad, bpf_csum_sp);
static u64 bpf_csum_diff(u64 r1, u64 from_size, u64 r3, u64 to_size, u64 seed) static u64 bpf_csum_diff(u64 r1, u64 from_size, u64 r3, u64 to_size, u64 seed)
{ {
struct bpf_csum_scratchpad *sp = this_cpu_ptr(&bpf_csum_sp); struct bpf_scratchpad *sp = this_cpu_ptr(&bpf_sp);
u64 diff_size = from_size + to_size; u64 diff_size = from_size + to_size;
__be32 *from = (__be32 *) (long) r1; __be32 *from = (__be32 *) (long) r1;
__be32 *to = (__be32 *) (long) r3; __be32 *to = (__be32 *) (long) r3;
......
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