summaryrefslogtreecommitdiffstats
path: root/arch/mips/net
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2014-06-25 09:37:21 +0100
committerRalf Baechle <ralf@linux-mips.org>2014-06-26 10:48:22 +0100
commit95782bf434437b3292f5cb9ce21b53bdbc1beda1 (patch)
treedf217b9e4d2a4ec7ded37d7d3aea6c34d547e8e9 /arch/mips/net
parente5bb48b0553d75918094c5a6f7b60a4359887218 (diff)
downloadlinux-95782bf434437b3292f5cb9ce21b53bdbc1beda1.tar.gz
linux-95782bf434437b3292f5cb9ce21b53bdbc1beda1.tar.bz2
linux-95782bf434437b3292f5cb9ce21b53bdbc1beda1.zip
MIPS: BPF: Prevent kernel fall over for >=32bit shifts
Remove BUG_ON() if the shift immediate is >=32 to avoid kernel crashes due to malicious user input. If the shift immediate is >= 32, we simply load the destination register with 0 since only 32-bit instructions are used by JIT so this will do the correct thing even on MIPS64. Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> Cc: David S. Miller <davem@davemloft.net> Cc: Daniel Borkmann <dborkman@redhat.com> Cc: Alexei Starovoitov <ast@plumgrid.com> Cc: netdev@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/7179/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/net')
-rw-r--r--arch/mips/net/bpf_jit.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 1bcd599d9971..9476e7f061a1 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -151,6 +151,8 @@ static inline int optimize_div(u32 *k)
return 0;
}
+static inline void emit_jit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx);
+
/* Simply emit the instruction if the JIT memory space has been allocated */
#define emit_instr(ctx, func, ...) \
do { \
@@ -309,8 +311,11 @@ static inline void emit_sll(unsigned int dst, unsigned int src,
unsigned int sa, struct jit_ctx *ctx)
{
/* sa is 5-bits long */
- BUG_ON(sa >= BIT(5));
- emit_instr(ctx, sll, dst, src, sa);
+ if (sa >= BIT(5))
+ /* Shifting >= 32 results in zero */
+ emit_jit_reg_move(dst, r_zero, ctx);
+ else
+ emit_instr(ctx, sll, dst, src, sa);
}
static inline void emit_srlv(unsigned int dst, unsigned int src,
@@ -323,8 +328,11 @@ static inline void emit_srl(unsigned int dst, unsigned int src,
unsigned int sa, struct jit_ctx *ctx)
{
/* sa is 5-bits long */
- BUG_ON(sa >= BIT(5));
- emit_instr(ctx, srl, dst, src, sa);
+ if (sa >= BIT(5))
+ /* Shifting >= 32 results in zero */
+ emit_jit_reg_move(dst, r_zero, ctx);
+ else
+ emit_instr(ctx, srl, dst, src, sa);
}
static inline void emit_slt(unsigned int dst, unsigned int src1,