lkml.org 
[lkml]   [2012]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRe: [REGRESSION][PATCH] bpf_jit drops the ball on indirect negative mem references
    Date
    Hi Jan,

    On 30 Mar 2012, at 14:42, Jan Seiffert <kaffeemonster@googlemail.com> wrote:

    > Eric Dumazet schrieb:
    >> [snip]
    >> All these ".p2align 1" are noise for this patch.
    >>
    >> This should be done as separate patch, explaining the rationale.
    >>
    >> ...
    > Ok, i thought since you where concerned with the performance and
    > I'm touching this stuff anyway.
    > But you are right, can be done separately.
    > So gone.
    >
    >> [snip]
    >>
    >> Please add the code for imm8 offsets as well ?
    >>
    >> if (is_imm8(K))
    >> EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx),%esi */
    >> else
    >> EMIT2_off32(0x8d, 0xb3, K); /* lea imm32(%rbx),%esi */
    >
    > Right, there is this imm8 form. I left it out because i never saw gas emit it
    > and totally forgot about it.
    > Your wish is my command. But since there is no EMIT2_off32 and introducing
    > it would mean additional cleanup noise, i stayed with two emits.
    >
    > Do you know where i can ping the powerpc guys a little bit harder?

    No need (unless you mean a different guy), I have enough guilt as it is! :) (Sorry for no response, am moving house and am netless.) I skimmed your patches on my phone but hope to be in a state to review/test over the weekend or early next week. :)


    Cheers,

    Matt


    >
    > So here a v3 of the patch:
    >
    > Consider the following test program:
    >
    > #include <stdio.h>
    > #include <sys/types.h>
    > #include <sys/socket.h>
    > #include <netinet/in.h>
    > #include <pcap-bpf.h>
    >
    > #define die(x) do {perror(x); return 1;} while (0)
    > struct bpf_insn udp_filter[] = {
    > /* 0 */ BPF_STMT(BPF_LDX|BPF_W|BPF_IMM, -1048576+(0)), /* leax net[0] */
    > /* 1 */ BPF_STMT(BPF_LD|BPF_B|BPF_IND, 0), /* ldb [x+0] */
    > /* 2 */ BPF_STMT(BPF_RET|BPF_A, 0), /* ret a */
    > };
    >
    > int main(int argc, char *argv[])
    > {
    > char buf[512];
    > struct sockaddr_in addr;
    > struct bpf_program prg;
    > socklen_t addr_s;
    > ssize_t res;
    > int fd;
    >
    > addr.sin_family = AF_INET;
    > addr.sin_port = htons(5000);
    > addr.sin_addr.s_addr = 0;
    > addr_s = sizeof(addr);
    > prg.bf_len = sizeof(udp_filter)/sizeof(udp_filter[0]);
    > prg.bf_insns = udp_filter;
    > if(-1 == (fd = socket(AF_INET, SOCK_DGRAM, 0)))
    > die("socket");
    > if(-1 == bind(fd, (struct sockaddr *)&addr, sizeof(addr)))
    > die("bind");
    > if(-1 == setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &prg, sizeof(prg)))
    > die("setsockopt");
    > res = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addr_s);
    > if(res != -1)
    > printf("packet received: %zi bytes\n", res);
    > else
    > die("recvfrom");
    > return 0;
    > }
    >
    > when used with the bpf jit disabled works:
    > console 1 $ ./bpf
    > console 2 $ echo "hello" | nc -u localhost 5000
    > console 1: packet received: 6 bytes
    >
    > When the bpf jit gets enabled (echo 100 >
    > /proc/sys/net/core/bpf_jit_enable) the same program stops working:
    > console 1 $ ./bpf
    > console 2 $ echo "hello" | nc -u localhost 5000
    > console 1:
    >
    > The reason is that both jits (x86 and powerpc) do not handle negative
    > memory references like SKF_NET_OFF or SKF_LL_OFF, only the simple
    > ancillary data references are supported (by mapping to special
    > instructions).
    > In the case of an absolute reference, the jit aborts the translation
    > if a negative reference is seen, also a negative k on the indirect
    > load aborts the translation, but if X is negative to begin with, only
    > the error handler is reached at runtime which drops the whole packet.
    >
    > I propose the following patch to fix this situation.
    > Lightly tested on x86, but the powerpc asm part is prop. wrong.
    >
    > Signed-of-by: Jan Seiffert <kaffeemonster@googlemail.com>
    >
    > diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
    > index af1ab5e..e9b57b3 100644
    > --- a/arch/powerpc/net/bpf_jit.h
    > +++ b/arch/powerpc/net/bpf_jit.h
    > @@ -49,6 +49,10 @@
    > * Assembly helpers from arch/powerpc/net/bpf_jit.S:
    > */
    > extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
    > +extern u8 sk_load_word_positive_offset[], sk_load_half_positive_offset[];
    > +extern u8 sk_load_byte_positive_offset[], sk_load_byte_msh_positive_offset[];
    > +extern u8 sk_load_word_negative_offset[], sk_load_half_negative_offset[];
    > +extern u8 sk_load_byte_negative_offset[], sk_load_byte_msh_negative_offset[];
    >
    > #define FUNCTION_DESCR_SIZE 24
    >
    > diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S
    > index ff4506e..e590aa5 100644
    > --- a/arch/powerpc/net/bpf_jit_64.S
    > +++ b/arch/powerpc/net/bpf_jit_64.S
    > @@ -31,14 +31,13 @@
    > * then branch directly to slow_path_XXX if required. (In fact, could
    > * load a spare GPR with the address of slow_path_generic and pass size
    > * as an argument, making the call site a mtlr, li and bllr.)
    > - *
    > - * Technically, the "is addr < 0" check is unnecessary & slowing down
    > - * the ABS path, as it's statically checked on generation.
    > */
    > .globl sk_load_word
    > sk_load_word:
    > cmpdi r_addr, 0
    > - blt bpf_error
    > + blt bpf_slow_path_word_neg
    > + .globl sk_load_word_positive_offset
    > +sk_load_word_positive_offset:
    > /* Are we accessing past headlen? */
    > subi r_scratch1, r_HL, 4
    > cmpd r_scratch1, r_addr
    > @@ -51,7 +50,9 @@ sk_load_word:
    > .globl sk_load_half
    > sk_load_half:
    > cmpdi r_addr, 0
    > - blt bpf_error
    > + blt bpf_slow_path_half_neg
    > + .globl sk_load_half_positive_offset
    > +sk_load_half_positive_offset:
    > subi r_scratch1, r_HL, 2
    > cmpd r_scratch1, r_addr
    > blt bpf_slow_path_half
    > @@ -61,7 +62,9 @@ sk_load_half:
    > .globl sk_load_byte
    > sk_load_byte:
    > cmpdi r_addr, 0
    > - blt bpf_error
    > + blt bpf_slow_path_byte_neg
    > + .globl sk_load_byte_positive_offset
    > +sk_load_byte_positive_offset:
    > cmpd r_HL, r_addr
    > ble bpf_slow_path_byte
    > lbzx r_A, r_D, r_addr
    > @@ -69,22 +72,20 @@ sk_load_byte:
    >
    > /*
    > * BPF_S_LDX_B_MSH: ldxb 4*([offset]&0xf)
    > - * r_addr is the offset value, already known positive
    > + * r_addr is the offset value
    > */
    > .globl sk_load_byte_msh
    > sk_load_byte_msh:
    > + cmpdi r_addr, 0
    > + blt bpf_slow_path_byte_msh_neg
    > + .globl sk_load_byte_msh_positive_offset
    > +sk_load_byte_msh_positive_offset:
    > cmpd r_HL, r_addr
    > ble bpf_slow_path_byte_msh
    > lbzx r_X, r_D, r_addr
    > rlwinm r_X, r_X, 2, 32-4-2, 31-2
    > blr
    >
    > -bpf_error:
    > - /* Entered with cr0 = lt */
    > - li r3, 0
    > - /* Generated code will 'blt epilogue', returning 0. */
    > - blr
    > -
    > /* Call out to skb_copy_bits:
    > * We'll need to back up our volatile regs first; we have
    > * local variable space at r1+(BPF_PPC_STACK_BASIC).
    > @@ -136,3 +137,85 @@ bpf_slow_path_byte_msh:
    > lbz r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
    > rlwinm r_X, r_X, 2, 32-4-2, 31-2
    > blr
    > +
    > +/* Call out to bpf_internal_load_pointer_neg_helper:
    > + * We'll need to back up our volatile regs first; we have
    > + * local variable space at r1+(BPF_PPC_STACK_BASIC).
    > + * Allocate a new stack frame here to remain ABI-compliant in
    > + * stashing LR.
    > + */
    > +#define sk_negative_common(SIZE) \
    > + mflr r0; \
    > + std r0, 16(r1); \
    > + /* R3 goes in parameter space of caller's frame */ \
    > + std r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
    > + std r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
    > + std r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
    > + stdu r1, -BPF_PPC_SLOWPATH_FRAME(r1); \
    > + /* R3 = r_skb, as passed */ \
    > + mr r4, r_addr; \
    > + li r5, SIZE; \
    > + bl bpf_internal_load_pointer_neg_helper; \
    > + /* R3 != 0 on success */ \
    > + addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \
    > + ld r0, 16(r1); \
    > + ld r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
    > + ld r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
    > + mtlr r0; \
    > + cmpldi r3, 0; \
    > + beq bpf_error_slow; /* cr0 = EQ */ \
    > + mr r_addr, r3; \
    > + ld r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
    > + /* Great success! */
    > +
    > +bpf_slow_path_word_neg:
    > + lis r_scratch1,-32 /* SKF_LL_OFF */
    > + cmpd r_addr, r_scratch1 /* addr < SKF_* */
    > + blt bpf_error /* cr0 = LT */
    > + .globl sk_load_word_negative_offset
    > +sk_load_word_negative_offset:
    > + sk_negative_common(4)
    > + lwz r_A, 0(r_addr)
    > + blr
    > +
    > +bpf_slow_path_half_neg:
    > + lis r_scratch1,-32 /* SKF_LL_OFF */
    > + cmpd r_addr, r_scratch1 /* addr < SKF_* */
    > + blt bpf_error /* cr0 = LT */
    > + .globl sk_load_half_negative_offset
    > +sk_load_half_negative_offset:
    > + sk_negative_common(2)
    > + lhz r_A, 0(r_addr)
    > + blr
    > +
    > +bpf_slow_path_byte_neg:
    > + lis r_scratch1,-32 /* SKF_LL_OFF */
    > + cmpd r_addr, r_scratch1 /* addr < SKF_* */
    > + blt bpf_error /* cr0 = LT */
    > + .globl sk_load_byte_negative_offset
    > +sk_load_byte_negative_offset:
    > + sk_negative_common(1)
    > + lbz r_A, 0(r_addr)
    > + blr
    > +
    > +bpf_slow_path_byte_msh_neg:
    > + lis r_scratch1,-32 /* SKF_LL_OFF */
    > + cmpd r_addr, r_scratch1 /* addr < SKF_* */
    > + blt bpf_error /* cr0 = LT */
    > + .globl sk_load_byte_msh_negative_offset
    > +sk_load_byte_msh_negative_offset:
    > + sk_negative_common(1)
    > + lbz r_X, 0(r_addr)
    > + rlwinm r_X, r_X, 2, 32-4-2, 31-2
    > + blr
    > +
    > +bpf_error_slow:
    > + /* fabricate a cr0 = lt */
    > + li r_scratch1, -1
    > + cmpdi r_scratch1, 0
    > +bpf_error:
    > + /* Entered with cr0 = lt */
    > + li r3, 0
    > + /* Generated code will 'blt epilogue', returning 0. */
    > + blr
    > +
    > diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
    > index 73619d3..2dc8b14 100644
    > --- a/arch/powerpc/net/bpf_jit_comp.c
    > +++ b/arch/powerpc/net/bpf_jit_comp.c
    > @@ -127,6 +127,9 @@ static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
    > PPC_BLR();
    > }
    >
    > +#define CHOOSE_LOAD_FUNC(K, func) \
    > + ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
    > +
    > /* Assemble the body code between the prologue & epilogue. */
    > static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
    > struct codegen_context *ctx,
    > @@ -391,21 +394,16 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
    >
    > /*** Absolute loads from packet header/data ***/
    > case BPF_S_LD_W_ABS:
    > - func = sk_load_word;
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_word);
    > goto common_load;
    > case BPF_S_LD_H_ABS:
    > - func = sk_load_half;
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_half);
    > goto common_load;
    > case BPF_S_LD_B_ABS:
    > - func = sk_load_byte;
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_byte);
    > common_load:
    > - /*
    > - * Load from [K]. Reference with the (negative)
    > - * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported.
    > - */
    > + /* Load from [K]. */
    > ctx->seen |= SEEN_DATAREF;
    > - if ((int)K < 0)
    > - return -ENOTSUPP;
    > PPC_LI64(r_scratch1, func);
    > PPC_MTLR(r_scratch1);
    > PPC_LI32(r_addr, K);
    > @@ -429,7 +427,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
    > common_load_ind:
    > /*
    > * Load from [X + K]. Negative offsets are tested for
    > - * in the helper functions, and result in a 'ret 0'.
    > + * in the helper functions.
    > */
    > ctx->seen |= SEEN_DATAREF | SEEN_XREG;
    > PPC_LI64(r_scratch1, func);
    > @@ -443,13 +441,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
    > break;
    >
    > case BPF_S_LDX_B_MSH:
    > - /*
    > - * x86 version drops packet (RET 0) when K<0, whereas
    > - * interpreter does allow K<0 (__load_pointer, special
    > - * ancillary data). common_load returns ENOTSUPP if K<0,
    > - * so we fall back to interpreter & filter works.
    > - */
    > - func = sk_load_byte_msh;
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh);
    > goto common_load;
    > break;
    >
    > diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S
    > index 6687022..2897d7f 100644
    > --- a/arch/x86/net/bpf_jit.S
    > +++ b/arch/x86/net/bpf_jit.S
    > @@ -18,17 +18,17 @@
    > * r9d : hlen = skb->len - skb->data_len
    > */
    > #define SKBDATA %r8
    > -
    > -sk_load_word_ind:
    > - .globl sk_load_word_ind
    > -
    > - add %ebx,%esi /* offset += X */
    > -# test %esi,%esi /* if (offset < 0) goto bpf_error; */
    > - js bpf_error
    > +#define SKF_MAX_NEG_OFF $(-0x200000) /* SKF_LL_OFF from filter.h */
    >
    > sk_load_word:
    > .globl sk_load_word
    >
    > + test %esi,%esi
    > + js bpf_slow_path_word_neg
    > +
    > +sk_load_word_positive_offset:
    > + .globl sk_load_word_positive_offset
    > +
    > mov %r9d,%eax # hlen
    > sub %esi,%eax # hlen - offset
    > cmp $3,%eax
    > @@ -37,16 +37,15 @@ sk_load_word:
    > bswap %eax /* ntohl() */
    > ret
    >
    > -
    > -sk_load_half_ind:
    > - .globl sk_load_half_ind
    > -
    > - add %ebx,%esi /* offset += X */
    > - js bpf_error
    > -
    > sk_load_half:
    > .globl sk_load_half
    >
    > + test %esi,%esi
    > + js bpf_slow_path_half_neg
    > +
    > +sk_load_half_positive_offset:
    > + .globl sk_load_half_positive_offset
    > +
    > mov %r9d,%eax
    > sub %esi,%eax # hlen - offset
    > cmp $1,%eax
    > @@ -55,14 +54,15 @@ sk_load_half:
    > rol $8,%ax # ntohs()
    > ret
    >
    > -sk_load_byte_ind:
    > - .globl sk_load_byte_ind
    > - add %ebx,%esi /* offset += X */
    > - js bpf_error
    > -
    > sk_load_byte:
    > .globl sk_load_byte
    >
    > + test %esi,%esi
    > + js bpf_slow_path_byte_neg
    > +
    > +sk_load_byte_positive_offset:
    > + .globl sk_load_byte_positive_offset
    > +
    > cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */
    > jle bpf_slow_path_byte
    > movzbl (SKBDATA,%rsi),%eax
    > @@ -73,25 +73,21 @@ sk_load_byte:
    > *
    > * Implements BPF_S_LDX_B_MSH : ldxb 4*([offset]&0xf)
    > * Must preserve A accumulator (%eax)
    > - * Inputs : %esi is the offset value, already known positive
    > + * Inputs : %esi is the offset value
    > */
    > -ENTRY(sk_load_byte_msh)
    > - CFI_STARTPROC
    > +sk_load_byte_msh:
    > + .globl sk_load_byte_msh
    > + test %esi,%esi
    > + js bpf_slow_path_byte_msh_neg
    > +
    > +sk_load_byte_msh_positive_offset:
    > + .globl sk_load_byte_msh_positive_offset
    > cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte_msh */
    > jle bpf_slow_path_byte_msh
    > movzbl (SKBDATA,%rsi),%ebx
    > and $15,%bl
    > shl $2,%bl
    > ret
    > - CFI_ENDPROC
    > -ENDPROC(sk_load_byte_msh)
    > -
    > -bpf_error:
    > -# force a return 0 from jit handler
    > - xor %eax,%eax
    > - mov -8(%rbp),%rbx
    > - leaveq
    > - ret
    >
    > /* rsi contains offset and can be scratched */
    > #define bpf_slow_path_common(LEN) \
    > @@ -138,3 +134,68 @@ bpf_slow_path_byte_msh:
    > shl $2,%al
    > xchg %eax,%ebx
    > ret
    > +
    > +#define sk_negative_common(SIZE) \
    > + push %rdi; /* save skb */ \
    > + push %r9; \
    > + push SKBDATA; \
    > +/* rsi already has offset */ \
    > + mov $SIZE,%ecx; /* size */ \
    > + call bpf_internal_load_pointer_neg_helper; \
    > + test %rax,%rax; \
    > + pop SKBDATA; \
    > + pop %r9; \
    > + pop %rdi; \
    > + jz bpf_error
    > +
    > +
    > +bpf_slow_path_word_neg:
    > + cmp SKF_MAX_NEG_OFF, %esi /* test range */
    > + jl bpf_error /* offset lower -> error */
    > +sk_load_word_negative_offset:
    > + .globl sk_load_word_negative_offset
    > + sk_negative_common(4)
    > + mov (%rax), %eax
    > + bswap %eax
    > + ret
    > +
    > +bpf_slow_path_half_neg:
    > + cmp SKF_MAX_NEG_OFF, %esi
    > + jl bpf_error
    > +sk_load_half_negative_offset:
    > + .globl sk_load_half_negative_offset
    > + sk_negative_common(2)
    > + mov (%rax),%ax
    > + rol $8,%ax
    > + movzwl %ax,%eax
    > + ret
    > +
    > +bpf_slow_path_byte_neg:
    > + cmp SKF_MAX_NEG_OFF, %esi
    > + jl bpf_error
    > +sk_load_byte_negative_offset:
    > + .globl sk_load_byte_negative_offset
    > + sk_negative_common(1)
    > + movzbl (%rax), %eax
    > + ret
    > +
    > +bpf_slow_path_byte_msh_neg:
    > + cmp SKF_MAX_NEG_OFF, %esi
    > + jl bpf_error
    > +sk_load_byte_msh_negative_offset:
    > + .globl sk_load_byte_msh_negative_offset
    > + xchg %eax,%ebx /* dont lose A , X is about to be scratched */
    > + sk_negative_common(1)
    > + movzbl (%rax),%eax
    > + and $15,%al
    > + shl $2,%al
    > + xchg %eax,%ebx
    > + ret
    > +
    > +bpf_error:
    > +# force a return 0 from jit handler
    > + xor %eax,%eax
    > + mov -8(%rbp),%rbx
    > + leaveq
    > + ret
    > +
    > diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
    > index 5671752..39a2e2c 100644
    > --- a/arch/x86/net/bpf_jit_comp.c
    > +++ b/arch/x86/net/bpf_jit_comp.c
    > @@ -30,7 +30,10 @@ int bpf_jit_enable __read_mostly;
    > * assembly code in arch/x86/net/bpf_jit.S
    > */
    > extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
    > -extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[];
    > +extern u8 sk_load_word_positive_offset[], sk_load_half_positive_offset[];
    > +extern u8 sk_load_byte_positive_offset[], sk_load_byte_msh_positive_offset[];
    > +extern u8 sk_load_word_negative_offset[], sk_load_half_negative_offset[];
    > +extern u8 sk_load_byte_negative_offset[], sk_load_byte_msh_negative_offset[];
    >
    > static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
    > {
    > @@ -117,6 +120,8 @@ static inline void bpf_flush_icache(void *start, void *end)
    > set_fs(old_fs);
    > }
    >
    > +#define CHOOSE_LOAD_FUNC(K, func) \
    > + ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
    >
    > void bpf_jit_compile(struct sk_filter *fp)
    > {
    > @@ -473,44 +478,46 @@ void bpf_jit_compile(struct sk_filter *fp)
    > #endif
    > break;
    > case BPF_S_LD_W_ABS:
    > - func = sk_load_word;
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_word);
    > common_load: seen |= SEEN_DATAREF;
    > - if ((int)K < 0) {
    > - /* Abort the JIT because __load_pointer() is needed. */
    > - goto out;
    > - }
    > t_offset = func - (image + addrs[i]);
    > EMIT1_off32(0xbe, K); /* mov imm32,%esi */
    > EMIT1_off32(0xe8, t_offset); /* call */
    > break;
    > case BPF_S_LD_H_ABS:
    > - func = sk_load_half;
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_half);
    > goto common_load;
    > case BPF_S_LD_B_ABS:
    > - func = sk_load_byte;
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_byte);
    > goto common_load;
    > case BPF_S_LDX_B_MSH:
    > - if ((int)K < 0) {
    > - /* Abort the JIT because __load_pointer() is needed. */
    > - goto out;
    > - }
    > + func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh);
    > seen |= SEEN_DATAREF | SEEN_XREG;
    > - t_offset = sk_load_byte_msh - (image + addrs[i]);
    > + t_offset = func - (image + addrs[i]);
    > EMIT1_off32(0xbe, K); /* mov imm32,%esi */
    > EMIT1_off32(0xe8, t_offset); /* call sk_load_byte_msh */
    > break;
    > case BPF_S_LD_W_IND:
    > - func = sk_load_word_ind;
    > + func = sk_load_word;
    > common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG;
    > t_offset = func - (image + addrs[i]);
    > - EMIT1_off32(0xbe, K); /* mov imm32,%esi */
    > + if (K) {
    > + if (is_imm8(K)) {
    > + EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx), %esi */
    > + } else {
    > + EMIT2(0x8d, 0xb3); /* lea imm32(%rbx),%esi */
    > + EMIT(K, 4);
    > + }
    > + } else {
    > + EMIT2(0x89,0xde); /* mov %ebx,%esi */
    > + }
    > EMIT1_off32(0xe8, t_offset); /* call sk_load_xxx_ind */
    > break;
    > case BPF_S_LD_H_IND:
    > - func = sk_load_half_ind;
    > + func = sk_load_half;
    > goto common_load_ind;
    > case BPF_S_LD_B_IND:
    > - func = sk_load_byte_ind;
    > + func = sk_load_byte;
    > goto common_load_ind;
    > case BPF_S_JMP_JA:
    > t_offset = addrs[i + K] - addrs[i];
    > diff --git a/net/core/filter.c b/net/core/filter.c
    > index 5dea452..04ca613 100644
    > --- a/net/core/filter.c
    > +++ b/net/core/filter.c
    > @@ -41,7 +41,7 @@
    > #include <linux/ratelimit.h>
    >
    > /* No hurry in this branch */
    > -static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size)
    > +void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, unsigned int size)
    > {
    > u8 *ptr = NULL;
    >
    > @@ -54,13 +54,14 @@ static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size)
    > return ptr;
    > return NULL;
    > }
    > +EXPORT_SYMBOL(bpf_internal_load_pointer_neg_helper);
    >
    > static inline void *load_pointer(const struct sk_buff *skb, int k,
    > unsigned int size, void *buffer)
    > {
    > if (k >= 0)
    > return skb_header_pointer(skb, k, size, buffer);
    > - return __load_pointer(skb, k, size);
    > + return bpf_internal_load_pointer_neg_helper(skb, k, size);
    > }
    >
    > /**
    >


    \
     
     \ /
      Last update: 2012-03-30 17:23    [W:0.074 / U:1.336 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site