[PATCH v2 04/13] bpf: move tmp variable into ax register in interpreter

Juerg Haefliger juerg.haefliger at canonical.com
Fri Mar 8 08:26:16 UTC 2019


This v2 patch came in after v1 has already been applied. I took the liberty to
replace v1 with v2 and force push bionic/master-next.

...Juerg


> From: Daniel Borkmann <daniel at iogearbox.net>
> 
> This change moves the on-stack 64 bit tmp variable in ___bpf_prog_run()
> into the hidden ax register. The latter is currently only used in JITs
> for constant blinding as a temporary scratch register, meaning the BPF
> interpreter will never see the use of ax. Therefore it is safe to use
> it for the cases where tmp has been used earlier. This is needed to later
> on allow restricted hidden use of ax in both interpreter and JITs.
> 
> Signed-off-by: Daniel Borkmann <daniel at iogearbox.net>
> Acked-by: Alexei Starovoitov <ast at kernel.org>
> Signed-off-by: Alexei Starovoitov <ast at kernel.org>
> 
> CVE-2019-7308
> 
> (backported from commit 144cd91c4c2bced6eb8a7e25e590f6618a11e854)
> [tyhicks: Backport around context changes and missing commits
>  1ea47e01ad6e and e0cea7ce988c]
> Signed-off-by: Tyler Hicks <tyhicks at canonical.com>
> Acked-by: You-Sheng Yang <vicamo.yang at canonical.com>
> Acked-by: Stefan Bader <stefan.bader at canonical.com>
> Signed-off-by: Khalid Elmously <khalid.elmously at canonical.com>
> ---
> 
> * Changes since v1:
>   - There were three additional uses of the tmp variable in ___bpf_prog_run()
>     that needed to be converted to AX in order to fix a build failure seen with
>     our i386 kernel config.
> 
>  include/linux/filter.h |  3 ++-
>  kernel/bpf/core.c      | 38 +++++++++++++++++++-------------------
>  2 files changed, 21 insertions(+), 20 deletions(-)
> 
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index e85292a16467..ec944f15f1a4 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -53,7 +53,8 @@ struct bpf_prog_aux;
>   * constants. See JIT pre-step in bpf_jit_blind_constants().
>   */
>  #define BPF_REG_AX		MAX_BPF_REG
> -#define MAX_BPF_JIT_REG		(MAX_BPF_REG + 1)
> +#define MAX_BPF_EXT_REG		(MAX_BPF_REG + 1)
> +#define MAX_BPF_JIT_REG		MAX_BPF_EXT_REG
>  
>  /* unused opcode to mark special call to bpf_tail_call() helper */
>  #define BPF_TAIL_CALL	0xf0
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index 7949e8b8f94e..439574daf1f0 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -51,6 +51,7 @@
>  #define DST	regs[insn->dst_reg]
>  #define SRC	regs[insn->src_reg]
>  #define FP	regs[BPF_REG_FP]
> +#define AX	regs[BPF_REG_AX]
>  #define ARG1	regs[BPF_REG_ARG1]
>  #define CTX	regs[BPF_REG_CTX]
>  #define IMM	insn->imm
> @@ -778,7 +779,6 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
>  static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
>  				    u64 *stack)
>  {
> -	u64 tmp;
>  	static const void *jumptable[256] = {
>  		[0 ... 255] = &&default_label,
>  		/* Now overwrite non-defaults ... */
> @@ -952,22 +952,22 @@ static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
>  	ALU64_MOD_X:
>  		if (unlikely(SRC == 0))
>  			return 0;
> -		div64_u64_rem(DST, SRC, &tmp);
> -		DST = tmp;
> +		div64_u64_rem(DST, SRC, &AX);
> +		DST = AX;
>  		CONT;
>  	ALU_MOD_X:
>  		if (unlikely((u32)SRC == 0))
>  			return 0;
> -		tmp = (u32) DST;
> -		DST = do_div(tmp, (u32) SRC);
> +		AX = (u32) DST;
> +		DST = do_div(AX, (u32) SRC);
>  		CONT;
>  	ALU64_MOD_K:
> -		div64_u64_rem(DST, IMM, &tmp);
> -		DST = tmp;
> +		div64_u64_rem(DST, IMM, &AX);
> +		DST = AX;
>  		CONT;
>  	ALU_MOD_K:
> -		tmp = (u32) DST;
> -		DST = do_div(tmp, (u32) IMM);
> +		AX = (u32) DST;
> +		DST = do_div(AX, (u32) IMM);
>  		CONT;
>  	ALU64_DIV_X:
>  		if (unlikely(SRC == 0))
> @@ -977,17 +977,17 @@ static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
>  	ALU_DIV_X:
>  		if (unlikely((u32)SRC == 0))
>  			return 0;
> -		tmp = (u32) DST;
> -		do_div(tmp, (u32) SRC);
> -		DST = (u32) tmp;
> +		AX = (u32) DST;
> +		do_div(AX, (u32) SRC);
> +		DST = (u32) AX;
>  		CONT;
>  	ALU64_DIV_K:
>  		DST = div64_u64(DST, IMM);
>  		CONT;
>  	ALU_DIV_K:
> -		tmp = (u32) DST;
> -		do_div(tmp, (u32) IMM);
> -		DST = (u32) tmp;
> +		AX = (u32) DST;
> +		do_div(AX, (u32) IMM);
> +		DST = (u32) AX;
>  		CONT;
>  	ALU_END_TO_BE:
>  		switch (IMM) {
> @@ -1242,7 +1242,7 @@ static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
>  		 *   BPF_R0 - 8/16/32-bit skb data converted to cpu endianness
>  		 */
>  
> -		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 4, &tmp);
> +		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 4, &AX);
>  		if (likely(ptr != NULL)) {
>  			BPF_R0 = get_unaligned_be32(ptr);
>  			CONT;
> @@ -1252,7 +1252,7 @@ static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
>  	LD_ABS_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + imm32)) */
>  		off = IMM;
>  load_half:
> -		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 2, &tmp);
> +		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 2, &AX);
>  		if (likely(ptr != NULL)) {
>  			BPF_R0 = get_unaligned_be16(ptr);
>  			CONT;
> @@ -1262,7 +1262,7 @@ static unsigned int ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn,
>  	LD_ABS_B: /* BPF_R0 = *(u8 *) (skb->data + imm32) */
>  		off = IMM;
>  load_byte:
> -		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 1, &tmp);
> +		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 1, &AX);
>  		if (likely(ptr != NULL)) {
>  			BPF_R0 = *(u8 *)ptr;
>  			CONT;
> @@ -1291,7 +1291,7 @@ STACK_FRAME_NON_STANDARD(___bpf_prog_run); /* jump table */
>  static unsigned int PROG_NAME(stack_size)(const void *ctx, const struct bpf_insn *insn) \
>  { \
>  	u64 stack[stack_size / sizeof(u64)]; \
> -	u64 regs[MAX_BPF_REG]; \
> +	u64 regs[MAX_BPF_EXT_REG]; \
>  \
>  	FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \
>  	ARG1 = (u64) (unsigned long) ctx; \

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20190308/9bd8e07a/attachment-0001.sig>


More information about the kernel-team mailing list