Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ef0910c authored by David Daney's avatar David Daney Committed by Ralf Baechle
Browse files

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: default avatarDavid Daney <david.daney@cavium.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Steven J. Hill <steven.hill@cavium.com>
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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 64b2dd3a
Loading
Loading
Loading
Loading
+12 −4
Original line number Original line Diff line number Diff line
@@ -532,6 +532,7 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
	u32 sflags, tmp_flags;
	u32 sflags, tmp_flags;


	/* Adjust the stack pointer */
	/* Adjust the stack pointer */
	if (offset)
		emit_stack_offset(-align_sp(offset), ctx);
		emit_stack_offset(-align_sp(offset), ctx);


	tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT;
	tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT;
@@ -584,6 +585,7 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx,
		emit_load_stack_reg(r_ra, r_sp, real_off, ctx);
		emit_load_stack_reg(r_ra, r_sp, real_off, ctx);


	/* Restore the sp and discard the scrach memory */
	/* Restore the sp and discard the scrach memory */
	if (offset)
		emit_stack_offset(align_sp(offset), ctx);
		emit_stack_offset(align_sp(offset), ctx);
}
}


@@ -631,8 +633,14 @@ static void build_prologue(struct jit_ctx *ctx)
	if (ctx->flags & SEEN_X)
	if (ctx->flags & SEEN_X)
		emit_jit_reg_move(r_X, r_zero, ctx);
		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);
		emit_jit_reg_move(r_A, r_zero, ctx);
}
}