diff options
79 files changed, 714 insertions, 811 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 4550d247e308..c011e2296cb1 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c | |||
| @@ -74,32 +74,52 @@ struct jit_ctx { | |||
| 74 | 74 | ||
| 75 | int bpf_jit_enable __read_mostly; | 75 | int bpf_jit_enable __read_mostly; |
| 76 | 76 | ||
| 77 | static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset) | 77 | static inline int call_neg_helper(struct sk_buff *skb, int offset, void *ret, |
| 78 | unsigned int size) | ||
| 79 | { | ||
| 80 | void *ptr = bpf_internal_load_pointer_neg_helper(skb, offset, size); | ||
| 81 | |||
| 82 | if (!ptr) | ||
| 83 | return -EFAULT; | ||
| 84 | memcpy(ret, ptr, size); | ||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static u64 jit_get_skb_b(struct sk_buff *skb, int offset) | ||
| 78 | { | 89 | { |
| 79 | u8 ret; | 90 | u8 ret; |
| 80 | int err; | 91 | int err; |
| 81 | 92 | ||
| 82 | err = skb_copy_bits(skb, offset, &ret, 1); | 93 | if (offset < 0) |
| 94 | err = call_neg_helper(skb, offset, &ret, 1); | ||
| 95 | else | ||
| 96 | err = skb_copy_bits(skb, offset, &ret, 1); | ||
| 83 | 97 | ||
| 84 | return (u64)err << 32 | ret; | 98 | return (u64)err << 32 | ret; |
| 85 | } | 99 | } |
| 86 | 100 | ||
| 87 | static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset) | 101 | static u64 jit_get_skb_h(struct sk_buff *skb, int offset) |
| 88 | { | 102 | { |
| 89 | u16 ret; | 103 | u16 ret; |
| 90 | int err; | 104 | int err; |
| 91 | 105 | ||
| 92 | err = skb_copy_bits(skb, offset, &ret, 2); | 106 | if (offset < 0) |
| 107 | err = call_neg_helper(skb, offset, &ret, 2); | ||
| 108 | else | ||
| 109 | err = skb_copy_bits(skb, offset, &ret, 2); | ||
| 93 | 110 | ||
| 94 | return (u64)err << 32 | ntohs(ret); | 111 | return (u64)err << 32 | ntohs(ret); |
| 95 | } | 112 | } |
| 96 | 113 | ||
| 97 | static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset) | 114 | static u64 jit_get_skb_w(struct sk_buff *skb, int offset) |
| 98 | { | 115 | { |
| 99 | u32 ret; | 116 | u32 ret; |
| 100 | int err; | 117 | int err; |
| 101 | 118 | ||
| 102 | err = skb_copy_bits(skb, offset, &ret, 4); | 119 | if (offset < 0) |
| 120 | err = call_neg_helper(skb, offset, &ret, 4); | ||
| 121 | else | ||
| 122 | err = skb_copy_bits(skb, offset, &ret, 4); | ||
| 103 | 123 | ||
| 104 | return (u64)err << 32 | ntohl(ret); | 124 | return (u64)err << 32 | ntohl(ret); |
| 105 | } | 125 | } |
| @@ -536,9 +556,6 @@ static int build_body(struct jit_ctx *ctx) | |||
| 536 | case BPF_LD | BPF_B | BPF_ABS: | 556 | case BPF_LD | BPF_B | BPF_ABS: |
| 537 | load_order = 0; | 557 | load_order = 0; |
| 538 | load: | 558 | load: |
| 539 | /* the interpreter will deal with the negative K */ | ||
| 540 | if ((int)k < 0) | ||
| 541 | return -ENOTSUPP; | ||
| 542 | emit_mov_i(r_off, k, ctx); | 559 | emit_mov_i(r_off, k, ctx); |
| 543 | load_common: | 560 | load_common: |
| 544 | ctx->seen |= SEEN_DATA | SEEN_CALL; | 561 | ctx->seen |= SEEN_DATA | SEEN_CALL; |
| @@ -547,12 +564,24 @@ load_common: | |||
| 547 | emit(ARM_SUB_I(r_scratch, r_skb_hl, | 564 | emit(ARM_SUB_I(r_scratch, r_skb_hl, |
| 548 | 1 << load_order), ctx); | 565 | 1 << load_order), ctx); |
| 549 | emit(ARM_CMP_R(r_scratch, r_off), ctx); | 566 | emit(ARM_CMP_R(r_scratch, r_off), ctx); |
| 550 | condt = ARM_COND_HS; | 567 | condt = ARM_COND_GE; |
| 551 | } else { | ||
