Re: [PATCH bpf-next 1/2] bpf: Fix a sdiv overflow issue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Yonghong,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Yonghong-Song/selftests-bpf-Add-a-couple-of-tests-for-potential-sdiv-overflow/20240911-124236
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link:    https://lore.kernel.org/r/20240911044017.2261738-1-yonghong.song%40linux.dev
patch subject: [PATCH bpf-next 1/2] bpf: Fix a sdiv overflow issue
config: x86_64-randconfig-121-20240912 (https://download.01.org/0day-ci/archive/20240912/202409121439.L01ZquSs-lkp@xxxxxxxxx/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240912/202409121439.L01ZquSs-lkp@xxxxxxxxx/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@xxxxxxxxx>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409121439.L01ZquSs-lkp@xxxxxxxxx/

sparse warnings: (new ones prefixed by >>)
   kernel/bpf/verifier.c:21184:38: sparse: sparse: subtraction of functions? Share your drugs
   kernel/bpf/verifier.c: note: in included file (through include/linux/bpf.h, include/linux/bpf-cgroup.h):
   include/linux/bpfptr.h:65:40: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:65:40: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:65:40: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:65:40: sparse: sparse: cast from non-scalar
   include/linux/bpfptr.h:65:40: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:65:40: sparse: sparse: cast from non-scalar
>> kernel/bpf/verifier.c:20538:33: sparse: sparse: cast truncates bits from constant value (8000000000000000 becomes 0)
   include/linux/bpfptr.h:65:40: sparse: sparse: cast to non-scalar
   include/linux/bpfptr.h:65:40: sparse: sparse: cast from non-scalar

vim +20538 kernel/bpf/verifier.c

 20445	
 20446	/* Do various post-verification rewrites in a single program pass.
 20447	 * These rewrites simplify JIT and interpreter implementations.
 20448	 */
 20449	static int do_misc_fixups(struct bpf_verifier_env *env)
 20450	{
 20451		struct bpf_prog *prog = env->prog;
 20452		enum bpf_attach_type eatype = prog->expected_attach_type;
 20453		enum bpf_prog_type prog_type = resolve_prog_type(prog);
 20454		struct bpf_insn *insn = prog->insnsi;
 20455		const struct bpf_func_proto *fn;
 20456		const int insn_cnt = prog->len;
 20457		const struct bpf_map_ops *ops;
 20458		struct bpf_insn_aux_data *aux;
 20459		struct bpf_insn *insn_buf = env->insn_buf;
 20460		struct bpf_prog *new_prog;
 20461		struct bpf_map *map_ptr;
 20462		int i, ret, cnt, delta = 0, cur_subprog = 0;
 20463		struct bpf_subprog_info *subprogs = env->subprog_info;
 20464		u16 stack_depth = subprogs[cur_subprog].stack_depth;
 20465		u16 stack_depth_extra = 0;
 20466	
 20467		if (env->seen_exception && !env->exception_callback_subprog) {
 20468			struct bpf_insn patch[] = {
 20469				env->prog->insnsi[insn_cnt - 1],
 20470				BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
 20471				BPF_EXIT_INSN(),
 20472			};
 20473	
 20474			ret = add_hidden_subprog(env, patch, ARRAY_SIZE(patch));
 20475			if (ret < 0)
 20476				return ret;
 20477			prog = env->prog;
 20478			insn = prog->insnsi;
 20479	
 20480			env->exception_callback_subprog = env->subprog_cnt - 1;
 20481			/* Don't update insn_cnt, as add_hidden_subprog always appends insns */
 20482			mark_subprog_exc_cb(env, env->exception_callback_subprog);
 20483		}
 20484	
 20485		for (i = 0; i < insn_cnt;) {
 20486			if (insn->code == (BPF_ALU64 | BPF_MOV | BPF_X) && insn->imm) {
 20487				if ((insn->off == BPF_ADDR_SPACE_CAST && insn->imm == 1) ||
 20488				    (((struct bpf_map *)env->prog->aux->arena)->map_flags & BPF_F_NO_USER_CONV)) {
 20489					/* convert to 32-bit mov that clears upper 32-bit */
 20490					insn->code = BPF_ALU | BPF_MOV | BPF_X;
 20491					/* clear off and imm, so it's a normal 'wX = wY' from JIT pov */
 20492					insn->off = 0;
 20493					insn->imm = 0;
 20494				} /* cast from as(0) to as(1) should be handled by JIT */
 20495				goto next_insn;
 20496			}
 20497	
 20498			if (env->insn_aux_data[i + delta].needs_zext)
 20499				/* Convert BPF_CLASS(insn->code) == BPF_ALU64 to 32-bit ALU */
 20500				insn->code = BPF_ALU | BPF_OP(insn->code) | BPF_SRC(insn->code);
 20501	
 20502			/* Make divide-by-zero exceptions impossible. */
 20503			if (insn->code == (BPF_ALU64 | BPF_MOD | BPF_X) ||
 20504			    insn->code == (BPF_ALU64 | BPF_DIV | BPF_X) ||
 20505			    insn->code == (BPF_ALU | BPF_MOD | BPF_X) ||
 20506			    insn->code == (BPF_ALU | BPF_DIV | BPF_X)) {
 20507				bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
 20508				bool isdiv = BPF_OP(insn->code) == BPF_DIV;
 20509				bool is_sdiv64 = is64 && isdiv && insn->off == 1;
 20510				struct bpf_insn *patchlet;
 20511				struct bpf_insn chk_and_div[] = {
 20512					/* [R,W]x div 0 -> 0 */
 20513					BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
 20514						     BPF_JNE | BPF_K, insn->src_reg,
 20515						     0, 2, 0),
 20516					BPF_ALU32_REG(BPF_XOR, insn->dst_reg, insn->dst_reg),
 20517					BPF_JMP_IMM(BPF_JA, 0, 0, 1),
 20518					*insn,
 20519				};
 20520				struct bpf_insn chk_and_mod[] = {
 20521					/* [R,W]x mod 0 -> [R,W]x */
 20522					BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
 20523						     BPF_JEQ | BPF_K, insn->src_reg,
 20524						     0, 1 + (is64 ? 0 : 1), 0),
 20525					*insn,
 20526					BPF_JMP_IMM(BPF_JA, 0, 0, 1),
 20527					BPF_MOV32_REG(insn->dst_reg, insn->dst_reg),
 20528				};
 20529				struct bpf_insn chk_and_sdiv64[] = {
 20530					/* Rx sdiv 0 -> 0 */
 20531					BPF_RAW_INSN(BPF_JMP | BPF_JNE | BPF_K, insn->src_reg,
 20532						     0, 2, 0),
 20533					BPF_ALU32_REG(BPF_XOR, insn->dst_reg, insn->dst_reg),
 20534					BPF_JMP_IMM(BPF_JA, 0, 0, 8),
 20535					/* LLONG_MIN sdiv -1 -> LLONG_MIN */
 20536					BPF_RAW_INSN(BPF_JMP | BPF_JNE | BPF_K, insn->src_reg,
 20537						     0, 6, -1),
 20538					BPF_LD_IMM64(insn->src_reg, LLONG_MIN),
 20539					BPF_RAW_INSN(BPF_JMP | BPF_JNE | BPF_X, insn->dst_reg,
 20540						     insn->src_reg, 2, 0),
 20541					BPF_MOV64_IMM(insn->src_reg, -1),
 20542					BPF_JMP_IMM(BPF_JA, 0, 0, 2),
 20543					BPF_MOV64_IMM(insn->src_reg, -1),
 20544					*insn,
 20545				};
 20546	
 20547				if (is_sdiv64) {
 20548					patchlet = chk_and_sdiv64;
 20549					cnt = ARRAY_SIZE(chk_and_sdiv64);
 20550				} else {
 20551					patchlet = isdiv ? chk_and_div : chk_and_mod;
 20552					cnt = isdiv ? ARRAY_SIZE(chk_and_div) :
 20553						      ARRAY_SIZE(chk_and_mod) - (is64 ? 2 : 0);
 20554				}
 20555	
 20556				new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt);
 20557				if (!new_prog)
 20558					return -ENOMEM;
 20559	
 20560				delta    += cnt - 1;
 20561				env->prog = prog = new_prog;
 20562				insn      = new_prog->insnsi + i + delta;
 20563				goto next_insn;
 20564			}
 20565	
 20566			/* Make it impossible to de-reference a userspace address */
 20567			if (BPF_CLASS(insn->code) == BPF_LDX &&
 20568			    (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
 20569			     BPF_MODE(insn->code) == BPF_PROBE_MEMSX)) {
 20570				struct bpf_insn *patch = &insn_buf[0];
 20571				u64 uaddress_limit = bpf_arch_uaddress_limit();
 20572	
 20573				if (!uaddress_limit)
 20574					goto next_insn;
 20575	
 20576				*patch++ = BPF_MOV64_REG(BPF_REG_AX, insn->src_reg);
 20577				if (insn->off)
 20578					*patch++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_AX, insn->off);
 20579				*patch++ = BPF_ALU64_IMM(BPF_RSH, BPF_REG_AX, 32);
 20580				*patch++ = BPF_JMP_IMM(BPF_JLE, BPF_REG_AX, uaddress_limit >> 32, 2);
 20581				*patch++ = *insn;
 20582				*patch++ = BPF_JMP_IMM(BPF_JA, 0, 0, 1);
 20583				*patch++ = BPF_MOV64_IMM(insn->dst_reg, 0);
 20584	
 20585				cnt = patch - insn_buf;
 20586				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20587				if (!new_prog)
 20588					return -ENOMEM;
 20589	
 20590				delta    += cnt - 1;
 20591				env->prog = prog = new_prog;
 20592				insn      = new_prog->insnsi + i + delta;
 20593				goto next_insn;
 20594			}
 20595	
 20596			/* Implement LD_ABS and LD_IND with a rewrite, if supported by the program type. */
 20597			if (BPF_CLASS(insn->code) == BPF_LD &&
 20598			    (BPF_MODE(insn->code) == BPF_ABS ||
 20599			     BPF_MODE(insn->code) == BPF_IND)) {
 20600				cnt = env->ops->gen_ld_abs(insn, insn_buf);
 20601				if (cnt == 0 || cnt >= INSN_BUF_SIZE) {
 20602					verbose(env, "bpf verifier is misconfigured\n");
 20603					return -EINVAL;
 20604				}
 20605	
 20606				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20607				if (!new_prog)
 20608					return -ENOMEM;
 20609	
 20610				delta    += cnt - 1;
 20611				env->prog = prog = new_prog;
 20612				insn      = new_prog->insnsi + i + delta;
 20613				goto next_insn;
 20614			}
 20615	
 20616			/* Rewrite pointer arithmetic to mitigate speculation attacks. */
 20617			if (insn->code == (BPF_ALU64 | BPF_ADD | BPF_X) ||
 20618			    insn->code == (BPF_ALU64 | BPF_SUB | BPF_X)) {
 20619				const u8 code_add = BPF_ALU64 | BPF_ADD | BPF_X;
 20620				const u8 code_sub = BPF_ALU64 | BPF_SUB | BPF_X;
 20621				struct bpf_insn *patch = &insn_buf[0];
 20622				bool issrc, isneg, isimm;
 20623				u32 off_reg;
 20624	
 20625				aux = &env->insn_aux_data[i + delta];
 20626				if (!aux->alu_state ||
 20627				    aux->alu_state == BPF_ALU_NON_POINTER)
 20628					goto next_insn;
 20629	
 20630				isneg = aux->alu_state & BPF_ALU_NEG_VALUE;
 20631				issrc = (aux->alu_state & BPF_ALU_SANITIZE) ==
 20632					BPF_ALU_SANITIZE_SRC;
 20633				isimm = aux->alu_state & BPF_ALU_IMMEDIATE;
 20634	
 20635				off_reg = issrc ? insn->src_reg : insn->dst_reg;
 20636				if (isimm) {
 20637					*patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit);
 20638				} else {
 20639					if (isneg)
 20640						*patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
 20641					*patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit);
 20642					*patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg);
 20643					*patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg);
 20644					*patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0);
 20645					*patch++ = BPF_ALU64_IMM(BPF_ARSH, BPF_REG_AX, 63);
 20646					*patch++ = BPF_ALU64_REG(BPF_AND, BPF_REG_AX, off_reg);
 20647				}
 20648				if (!issrc)
 20649					*patch++ = BPF_MOV64_REG(insn->dst_reg, insn->src_reg);
 20650				insn->src_reg = BPF_REG_AX;
 20651				if (isneg)
 20652					insn->code = insn->code == code_add ?
 20653						     code_sub : code_add;
 20654				*patch++ = *insn;
 20655				if (issrc && isneg && !isimm)
 20656					*patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
 20657				cnt = patch - insn_buf;
 20658	
 20659				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20660				if (!new_prog)
 20661					return -ENOMEM;
 20662	
 20663				delta    += cnt - 1;
 20664				env->prog = prog = new_prog;
 20665				insn      = new_prog->insnsi + i + delta;
 20666				goto next_insn;
 20667			}
 20668	
 20669			if (is_may_goto_insn(insn)) {
 20670				int stack_off = -stack_depth - 8;
 20671	
 20672				stack_depth_extra = 8;
 20673				insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_AX, BPF_REG_10, stack_off);
 20674				if (insn->off >= 0)
 20675					insn_buf[1] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 0, insn->off + 2);
 20676				else
 20677					insn_buf[1] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 0, insn->off - 1);
 20678				insn_buf[2] = BPF_ALU64_IMM(BPF_SUB, BPF_REG_AX, 1);
 20679				insn_buf[3] = BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_AX, stack_off);
 20680				cnt = 4;
 20681	
 20682				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20683				if (!new_prog)
 20684					return -ENOMEM;
 20685	
 20686				delta += cnt - 1;
 20687				env->prog = prog = new_prog;
 20688				insn = new_prog->insnsi + i + delta;
 20689				goto next_insn;
 20690			}
 20691	
 20692			if (insn->code != (BPF_JMP | BPF_CALL))
 20693				goto next_insn;
 20694			if (insn->src_reg == BPF_PSEUDO_CALL)
 20695				goto next_insn;
 20696			if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
 20697				ret = fixup_kfunc_call(env, insn, insn_buf, i + delta, &cnt);
 20698				if (ret)
 20699					return ret;
 20700				if (cnt == 0)
 20701					goto next_insn;
 20702	
 20703				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20704				if (!new_prog)
 20705					return -ENOMEM;
 20706	
 20707				delta	 += cnt - 1;
 20708				env->prog = prog = new_prog;
 20709				insn	  = new_prog->insnsi + i + delta;
 20710				goto next_insn;
 20711			}
 20712	
 20713			/* Skip inlining the helper call if the JIT does it. */
 20714			if (bpf_jit_inlines_helper_call(insn->imm))
 20715				goto next_insn;
 20716	
 20717			if (insn->imm == BPF_FUNC_get_route_realm)
 20718				prog->dst_needed = 1;
 20719			if (insn->imm == BPF_FUNC_get_prandom_u32)
 20720				bpf_user_rnd_init_once();
 20721			if (insn->imm == BPF_FUNC_override_return)
 20722				prog->kprobe_override = 1;
 20723			if (insn->imm == BPF_FUNC_tail_call) {
 20724				/* If we tail call into other programs, we
 20725				 * cannot make any assumptions since they can
 20726				 * be replaced dynamically during runtime in
 20727				 * the program array.
 20728				 */
 20729				prog->cb_access = 1;
 20730				if (!allow_tail_call_in_subprogs(env))
 20731					prog->aux->stack_depth = MAX_BPF_STACK;
 20732				prog->aux->max_pkt_offset = MAX_PACKET_OFF;
 20733	
 20734				/* mark bpf_tail_call as different opcode to avoid
 20735				 * conditional branch in the interpreter for every normal
 20736				 * call and to prevent accidental JITing by JIT compiler
 20737				 * that doesn't support bpf_tail_call yet
 20738				 */
 20739				insn->imm = 0;
 20740				insn->code = BPF_JMP | BPF_TAIL_CALL;
 20741	
 20742				aux = &env->insn_aux_data[i + delta];
 20743				if (env->bpf_capable && !prog->blinding_requested &&
 20744				    prog->jit_requested &&
 20745				    !bpf_map_key_poisoned(aux) &&
 20746				    !bpf_map_ptr_poisoned(aux) &&
 20747				    !bpf_map_ptr_unpriv(aux)) {
 20748					struct bpf_jit_poke_descriptor desc = {
 20749						.reason = BPF_POKE_REASON_TAIL_CALL,
 20750						.tail_call.map = aux->map_ptr_state.map_ptr,
 20751						.tail_call.key = bpf_map_key_immediate(aux),
 20752						.insn_idx = i + delta,
 20753					};
 20754	
 20755					ret = bpf_jit_add_poke_descriptor(prog, &desc);
 20756					if (ret < 0) {
 20757						verbose(env, "adding tail call poke descriptor failed\n");
 20758						return ret;
 20759					}
 20760	
 20761					insn->imm = ret + 1;
 20762					goto next_insn;
 20763				}
 20764	
 20765				if (!bpf_map_ptr_unpriv(aux))
 20766					goto next_insn;
 20767	
 20768				/* instead of changing every JIT dealing with tail_call
 20769				 * emit two extra insns:
 20770				 * if (index >= max_entries) goto out;
 20771				 * index &= array->index_mask;
 20772				 * to avoid out-of-bounds cpu speculation
 20773				 */
 20774				if (bpf_map_ptr_poisoned(aux)) {
 20775					verbose(env, "tail_call abusing map_ptr\n");
 20776					return -EINVAL;
 20777				}
 20778	
 20779				map_ptr = aux->map_ptr_state.map_ptr;
 20780				insn_buf[0] = BPF_JMP_IMM(BPF_JGE, BPF_REG_3,
 20781							  map_ptr->max_entries, 2);
 20782				insn_buf[1] = BPF_ALU32_IMM(BPF_AND, BPF_REG_3,
 20783							    container_of(map_ptr,
 20784									 struct bpf_array,
 20785									 map)->index_mask);
 20786				insn_buf[2] = *insn;
 20787				cnt = 3;
 20788				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20789				if (!new_prog)
 20790					return -ENOMEM;
 20791	
 20792				delta    += cnt - 1;
 20793				env->prog = prog = new_prog;
 20794				insn      = new_prog->insnsi + i + delta;
 20795				goto next_insn;
 20796			}
 20797	
 20798			if (insn->imm == BPF_FUNC_timer_set_callback) {
 20799				/* The verifier will process callback_fn as many times as necessary
 20800				 * with different maps and the register states prepared by
 20801				 * set_timer_callback_state will be accurate.
 20802				 *
 20803				 * The following use case is valid:
 20804				 *   map1 is shared by prog1, prog2, prog3.
 20805				 *   prog1 calls bpf_timer_init for some map1 elements
 20806				 *   prog2 calls bpf_timer_set_callback for some map1 elements.
 20807				 *     Those that were not bpf_timer_init-ed will return -EINVAL.
 20808				 *   prog3 calls bpf_timer_start for some map1 elements.
 20809				 *     Those that were not both bpf_timer_init-ed and
 20810				 *     bpf_timer_set_callback-ed will return -EINVAL.
 20811				 */
 20812				struct bpf_insn ld_addrs[2] = {
 20813					BPF_LD_IMM64(BPF_REG_3, (long)prog->aux),
 20814				};
 20815	
 20816				insn_buf[0] = ld_addrs[0];
 20817				insn_buf[1] = ld_addrs[1];
 20818				insn_buf[2] = *insn;
 20819				cnt = 3;
 20820	
 20821				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20822				if (!new_prog)
 20823					return -ENOMEM;
 20824	
 20825				delta    += cnt - 1;
 20826				env->prog = prog = new_prog;
 20827				insn      = new_prog->insnsi + i + delta;
 20828				goto patch_call_imm;
 20829			}
 20830	
 20831			if (is_storage_get_function(insn->imm)) {
 20832				if (!in_sleepable(env) ||
 20833				    env->insn_aux_data[i + delta].storage_get_func_atomic)
 20834					insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_ATOMIC);
 20835				else
 20836					insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_KERNEL);
 20837				insn_buf[1] = *insn;
 20838				cnt = 2;
 20839	
 20840				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20841				if (!new_prog)
 20842					return -ENOMEM;
 20843	
 20844				delta += cnt - 1;
 20845				env->prog = prog = new_prog;
 20846				insn = new_prog->insnsi + i + delta;
 20847				goto patch_call_imm;
 20848			}
 20849	
 20850			/* bpf_per_cpu_ptr() and bpf_this_cpu_ptr() */
 20851			if (env->insn_aux_data[i + delta].call_with_percpu_alloc_ptr) {
 20852				/* patch with 'r1 = *(u64 *)(r1 + 0)' since for percpu data,
 20853				 * bpf_mem_alloc() returns a ptr to the percpu data ptr.
 20854				 */
 20855				insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, 0);
 20856				insn_buf[1] = *insn;
 20857				cnt = 2;
 20858	
 20859				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
 20860				if (!new_prog)
 20861					return -ENOMEM;
 20862	
 20863				delta += cnt - 1;
 20864				env->prog = prog = new_prog;
 20865				insn = new_prog->insnsi + i + delta;
 20866				goto patch_call_imm;
 20867			}
 20868	
 20869			/* BPF_EMIT_CALL() assumptions in some of the map_gen_lookup
 20870			 * and other inlining handlers are currently limited to 64 bit
 20871			 * only.
 20872			 */
 20873			if (prog->jit_requested && BITS_PER_LONG == 64 &&
 20874			    (insn->imm == BPF_FUNC_map_lookup_elem ||
 20875			     insn->imm == BPF_FUNC_map_update_elem ||
 20876			     insn->imm == BPF_FUNC_map_delete_elem ||
 20877			     insn->imm == BPF_FUNC_map_push_elem   ||
 20878			     insn->imm == BPF_FUNC_map_pop_elem    ||
 20879			     insn->imm == BPF_FUNC_map_peek_elem   ||
 20880			     insn->imm == BPF_FUNC_redirect_map    ||
 20881			     insn->imm == BPF_FUNC_for_each_map_elem ||
 20882			     insn->imm == BPF_FUNC_map_lookup_percpu_elem)) {
 20883				aux = &env->insn_aux_data[i + delta];
 20884				if (bpf_map_ptr_poisoned(aux))
 20885					goto patch_call_imm;
 20886	
 20887				map_ptr = aux->map_ptr_state.map_ptr;
 20888				ops = map_ptr->ops;
 20889				if (insn->imm == BPF_FUNC_map_lookup_elem &&
 20890				    ops->map_gen_lookup) {
 20891					cnt = ops->map_gen_lookup(map_ptr, insn_buf);
 20892					if (cnt == -EOPNOTSUPP)
 20893						goto patch_map_ops_generic;
 20894					if (cnt <= 0 || cnt >= INSN_BUF_SIZE) {
 20895						verbose(env, "bpf verifier is misconfigured\n");
 20896						return -EINVAL;
 20897					}
 20898	
 20899					new_prog = bpf_patch_insn_data(env, i + delta,
 20900								       insn_buf, cnt);
 20901					if (!new_prog)
 20902						return -ENOMEM;
 20903	
 20904					delta    += cnt - 1;
 20905					env->prog = prog = new_prog;
 20906					insn      = new_prog->insnsi + i + delta;
 20907					goto next_insn;
 20908				}
 20909	
 20910				BUILD_BUG_ON(!__same_type(ops->map_lookup_elem,
 20911					     (void *(*)(struct bpf_map *map, void *key))NULL));
 20912				BUILD_BUG_ON(!__same_type(ops->map_delete_elem,
 20913					     (long (*)(struct bpf_map *map, void *key))NULL));
 20914				BUILD_BUG_ON(!__same_type(ops->map_update_elem,
 20915					     (long (*)(struct bpf_map *map, void *key, void *value,
 20916						      u64 flags))NULL));
 20917				BUILD_BUG_ON(!__same_type(ops->map_push_elem,
 20918					     (long (*)(struct bpf_map *map, void *value,
 20919						      u64 flags))NULL));
 20920				BUILD_BUG_ON(!__same_type(ops->map_pop_elem,
 20921					     (long (*)(struct bpf_map *map, void *value))NULL));
 20922				BUILD_BUG_ON(!__same_type(ops->map_peek_elem,
 20923					     (long (*)(struct bpf_map *map, void *value))NULL));
 20924				BUILD_BUG_ON(!__same_type(ops->map_redirect,
 20925					     (long (*)(struct bpf_map *map, u64 index, u64 flags))NULL));
 20926				BUILD_BUG_ON(!__same_type(ops->map_for_each_callback,
 20927					     (long (*)(struct bpf_map *map,
 20928						      bpf_callback_t callback_fn,
 20929						      void *callback_ctx,
 20930						      u64 flags))NULL));
 20931				BUILD_BUG_ON(!__same_type(ops->map_lookup_percpu_elem,
 20932					     (void *(*)(struct bpf_map *map, void *key, u32 cpu))NULL));
 20933	
 20934	patch_map_ops_generic:
 20935				switch (insn->imm) {
 20936				case BPF_FUNC_map_lookup_elem:
 20937					insn->imm = BPF_CALL_IMM(ops->map_lookup_elem);
 20938					goto next_insn;
 20939				case BPF_FUNC_map_update_elem:
 20940					insn->imm = BPF_CALL_IMM(ops->map_update_elem);
 20941					goto next_insn;
 20942				case BPF_FUNC_map_delete_elem:
 20943					insn->imm = BPF_CALL_IMM(ops->map_delete_elem);
 20944					goto next_insn;
 20945				case BPF_FUNC_map_push_elem:
 20946					insn->imm = BPF_CALL_IMM(ops->map_push_elem);
 20947					goto next_insn;
 20948				case BPF_FUNC_map_pop_elem:
 20949					insn->imm = BPF_CALL_IMM(ops->map_pop_elem);
 20950					goto next_insn;
 20951				case BPF_FUNC_map_peek_elem:
 20952					insn->imm = BPF_CALL_IMM(ops->map_peek_elem);
 20953					goto next_insn;
 20954				case BPF_FUNC_redirect_map:
 20955					insn->imm = BPF_CALL_IMM(ops->map_redirect);
 20956					goto next_insn;
 20957				case BPF_FUNC_for_each_map_elem:
 20958					insn->imm = BPF_CALL_IMM(ops->map_for_each_callback);
 20959					goto next_insn;
 20960				case BPF_FUNC_map_lookup_percpu_elem:
 20961					insn->imm = BPF_CALL_IMM(ops->map_lookup_percpu_elem);
 20962					goto next_insn;
 20963				}
 20964	
 20965				goto patch_call_imm;
 20966			}
 20967	
 20968			/* Implement bpf_jiffies64 inline. */
 20969			if (prog->jit_requested && BITS_PER_LONG == 64 &&
 20970			    insn->imm == BPF_FUNC_jiffies64) {
 20971				struct bpf_insn ld_jiffies_addr[2] = {
 20972					BPF_LD_IMM64(BPF_REG_0,
 20973						     (unsigned long)&jiffies),
 20974				};
 20975	
 20976				insn_buf[0] = ld_jiffies_addr[0];
 20977				insn_buf[1] = ld_jiffies_addr[1];
 20978				insn_buf[2] = BPF_LDX_MEM(BPF_DW, BPF_REG_0,
 20979							  BPF_REG_0, 0);
 20980				cnt = 3;
 20981	
 20982				new_prog = bpf_patch_insn_data(env, i + delta, insn_buf,
 20983							       cnt);
 20984				if (!new_prog)
 20985					return -ENOMEM;
 20986	
 20987				delta    += cnt - 1;
 20988				env->prog = prog = new_prog;
 20989				insn      = new_prog->insnsi + i + delta;
 20990				goto next_insn;
 20991			}
 20992	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux