From 4ad701532a758202a422a8588f4d09c058c9a5dc Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:41 -0700 Subject: MIPS: BPF: Add JIT support for SKF_AD_HATYPE. This let's us pass some additional "modprobe test-bpf" tests with JIT enabled. Reuse the code for SKF_AD_IFINDEX, but substitute the offset and size of the "type" field. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15744/ Signed-off-by: Ralf Baechle --- arch/mips/net/bpf_jit.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'arch/mips/net/bpf_jit.c') diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index 49a2e2226fee..880e329310ee 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -365,6 +365,12 @@ static inline void emit_half_load(unsigned int reg, unsigned int base, emit_instr(ctx, lh, reg, offset, base); } +static inline void emit_half_load_unsigned(unsigned int reg, unsigned int base, + unsigned int offset, struct jit_ctx *ctx) +{ + emit_instr(ctx, lhu, reg, offset, base); +} + static inline void emit_mul(unsigned int dst, unsigned int src1, unsigned int src2, struct jit_ctx *ctx) { @@ -1112,6 +1118,8 @@ jmp_cmp: break; case BPF_ANC | SKF_AD_IFINDEX: /* A = skb->dev->ifindex */ + case BPF_ANC | SKF_AD_HATYPE: + /* A = skb->dev->type */ ctx->flags |= SEEN_SKB | SEEN_A; off = offsetof(struct sk_buff, dev); /* Load *dev pointer */ @@ -1120,10 +1128,15 @@ jmp_cmp: emit_bcond(MIPS_COND_EQ, r_s0, r_zero, b_imm(prog->len, ctx), ctx); emit_reg_move(r_ret, r_zero, ctx); - BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, - ifindex) != 4); - off = offsetof(struct net_device, ifindex); - emit_load(r_A, r_s0, off, ctx); + if (code == (BPF_ANC | SKF_AD_IFINDEX)) { + BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4); + off = offsetof(struct net_device, ifindex); + emit_load(r_A, r_s0, off, ctx); + } else { /* (code == (BPF_ANC | SKF_AD_HATYPE) */ + BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2); + off = offsetof(struct net_device, type); + emit_half_load_unsigned(r_A, r_s0, off, ctx); + } break; case BPF_ANC | SKF_AD_MARK: ctx->flags |= SEEN_SKB | SEEN_A; -- cgit v1.2.3 From 64b2dd3a8be3ec4e08fd5a3dab0620d9c6c398fe Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:42 -0700 Subject: MIPS: BPF: Use unsigned access for unsigned SKB fields. The SKB vlan_tci and queue_mapping fields are unsigned, don't sign extend these in the BPF JIT. In the vlan_tci case, the value gets masked so the change is not needed for correctness, but do it anyway for agreement with the types defined in struct sk_buff. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15746/ Signed-off-by: Ralf Baechle --- arch/mips/net/bpf_jit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/net/bpf_jit.c') diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index 880e329310ee..a68cd36a892f 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -1156,7 +1156,7 @@ jmp_cmp: BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2); off = offsetof(struct sk_buff, vlan_tci); - emit_half_load(r_s0, r_skb, off, ctx); + emit_half_load_unsigned(r_s0, r_skb, off, ctx); if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) { emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx); } else { @@ -1183,7 +1183,7 @@ jmp_cmp: BUILD_BUG_ON(offsetof(struct sk_buff, queue_mapping) > 0xff); off = offsetof(struct sk_buff, queue_mapping); - emit_half_load(r_A, r_skb, off, ctx); + emit_half_load_unsigned(r_A, r_skb, off, ctx); break; default: pr_debug("%s: Unhandled opcode: 0x%02x\n", __FILE__, -- cgit v1.2.3 From 1ef0910cfd681f0bd0b81f8809935b2006e9cfb9 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:43 -0700 Subject: MIPS: BPF: Quit clobbering callee saved registers in JIT code. If bpf_needs_clear_a() returns true, only actually clear it if it is ever used. If it is not used, we don't save and restore it, so the clearing has the nasty side effect of clobbering caller state. Also, don't emit stack pointer adjustment instructions if the adjustment amount is zero. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15745/ Signed-off-by: Ralf Baechle --- arch/mips/net/bpf_jit.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'arch/mips/net/bpf_jit.c') diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index a68cd36a892f..44b925005dd3 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -532,7 +532,8 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset) u32 sflags, tmp_flags; /* Adjust the stack pointer */ - emit_stack_offset(-align_sp(offset), ctx); + if (offset) + emit_stack_offset(-align_sp(offset), ctx); tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT; /* sflags is essentially a bitmap */ @@ -584,7 +585,8 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx, emit_load_stack_reg(r_ra, r_sp, real_off, ctx); /* Restore the sp and discard the scrach memory */ - emit_stack_offset(align_sp(offset), ctx); + if (offset) + emit_stack_offset(align_sp(offset), ctx); } static unsigned int get_stack_depth(struct jit_ctx *ctx) @@ -631,8 +633,14 @@ static void build_prologue(struct jit_ctx *ctx) if (ctx->flags & SEEN_X) emit_jit_reg_move(r_X, r_zero, ctx); - /* Do not leak kernel data to userspace */ - if (bpf_needs_clear_a(&ctx->skf->insns[0])) + /* + * Do not leak kernel data to userspace, we only need to clear + * r_A if it is ever used. In fact if it is never used, we + * will not save/restore it, so clearing it in this case would + * corrupt the state of the caller. + */ + if (bpf_needs_clear_a(&ctx->skf->insns[0]) && + (ctx->flags & SEEN_A)) emit_jit_reg_move(r_A, r_zero, ctx); } -- cgit v1.2.3