diff options
Diffstat (limited to 'arch/powerpc/net/bpf_jit.h')
| -rw-r--r-- | arch/powerpc/net/bpf_jit.h | 33 | 
1 files changed, 21 insertions, 12 deletions
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 99fad093f43e..7e9b978b768e 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h @@ -24,16 +24,30 @@  #define EMIT(instr)		PLANT_INSTR(image, ctx->idx, instr)  /* Long jump; (unconditional 'branch') */ -#define PPC_JMP(dest)		EMIT(PPC_INST_BRANCH |			      \ -				     (((dest) - (ctx->idx * 4)) & 0x03fffffc)) +#define PPC_JMP(dest)							      \ +	do {								      \ +		long offset = (long)(dest) - (ctx->idx * 4);		      \ +		if (!is_offset_in_branch_range(offset)) {		      \ +			pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx);			\ +			return -ERANGE;					      \ +		}							      \ +		EMIT(PPC_INST_BRANCH | (offset & 0x03fffffc));		      \ +	} while (0) +  /* blr; (unconditional 'branch' with link) to absolute address */  #define PPC_BL_ABS(dest)	EMIT(PPC_INST_BL |			      \  				     (((dest) - (unsigned long)(image + ctx->idx)) & 0x03fffffc))  /* "cond" here covers BO:BI fields. */ -#define PPC_BCC_SHORT(cond, dest)	EMIT(PPC_INST_BRANCH_COND |	      \ -					     (((cond) & 0x3ff) << 16) |	      \ -					     (((dest) - (ctx->idx * 4)) &     \ -					      0xfffc)) +#define PPC_BCC_SHORT(cond, dest)					      \ +	do {								      \ +		long offset = (long)(dest) - (ctx->idx * 4);		      \ +		if (!is_offset_in_cond_branch_range(offset)) {		      \ +			pr_err_ratelimited("Conditional branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx);		\ +			return -ERANGE;					      \ +		}							      \ +		EMIT(PPC_INST_BRANCH_COND | (((cond) & 0x3ff) << 16) | (offset & 0xfffc));					\ +	} while (0) +  /* Sign-extended 32-bit immediate load */  #define PPC_LI32(d, i)		do {					      \  		if ((int)(uintptr_t)(i) >= -32768 &&			      \ @@ -78,11 +92,6 @@  #define PPC_FUNC_ADDR(d,i) do { PPC_LI32(d, i); } while(0)  #endif -static inline bool is_nearbranch(int offset) -{ -	return (offset < 32768) && (offset >= -32768); -} -  /*   * The fly in the ointment of code size changing from pass to pass is   * avoided by padding the short branch case with a NOP.	 If code size differs @@ -91,7 +100,7 @@ static inline bool is_nearbranch(int offset)   * state.   */  #define PPC_BCC(cond, dest)	do {					      \ -		if (is_nearbranch((dest) - (ctx->idx * 4))) {		      \ +		if (is_offset_in_cond_branch_range((long)(dest) - (ctx->idx * 4))) {	\  			PPC_BCC_SHORT(cond, dest);			      \  			EMIT(PPC_RAW_NOP());				      \  		} else {						      \  | 
