@@ -4386,6 +4386,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
43864386 case PTR_TO_MEM:
43874387 case PTR_TO_FUNC:
43884388 case PTR_TO_MAP_KEY:
4389+ case PTR_TO_ARENA:
43894390 return true;
43904391 default:
43914392 return false;
@@ -5828,6 +5829,8 @@ static int check_ptr_alignment(struct bpf_verifier_env *env,
58285829 case PTR_TO_XDP_SOCK:
58295830 pointer_desc = "xdp_sock ";
58305831 break;
5832+ case PTR_TO_ARENA:
5833+ return 0;
58315834 default:
58325835 break;
58335836 }
@@ -6937,6 +6940,9 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
69376940
69386941 if (!err && value_regno >= 0 && (rdonly_mem || t == BPF_READ))
69396942 mark_reg_unknown(env, regs, value_regno);
6943+ } else if (reg->type == PTR_TO_ARENA) {
6944+ if (t == BPF_READ && value_regno >= 0)
6945+ mark_reg_unknown(env, regs, value_regno);
69406946 } else {
69416947 verbose(env, "R%d invalid mem access '%s'\n", regno,
69426948 reg_type_str(env, reg->type));
@@ -8408,6 +8414,7 @@ static int check_func_arg_reg_off(struct bpf_verifier_env *env,
84088414 case PTR_TO_MEM | MEM_RINGBUF:
84098415 case PTR_TO_BUF:
84108416 case PTR_TO_BUF | MEM_RDONLY:
8417+ case PTR_TO_ARENA:
84118418 case SCALAR_VALUE:
84128419 return 0;
84138420 /* All the rest must be rejected, except PTR_TO_BTF_ID which allows
@@ -13852,6 +13859,21 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
1385213859
1385313860 dst_reg = ®s[insn->dst_reg];
1385413861 src_reg = NULL;
13862+
13863+ if (dst_reg->type == PTR_TO_ARENA) {
13864+ struct bpf_insn_aux_data *aux = cur_aux(env);
13865+
13866+ if (BPF_CLASS(insn->code) == BPF_ALU64)
13867+ /*
13868+ * 32-bit operations zero upper bits automatically.
13869+ * 64-bit operations need to be converted to 32.
13870+ */
13871+ aux->needs_zext = true;
13872+
13873+ /* Any arithmetic operations are allowed on arena pointers */
13874+ return 0;
13875+ }
13876+
1385513877 if (dst_reg->type != SCALAR_VALUE)
1385613878 ptr_reg = dst_reg;
1385713879 else
@@ -13969,19 +13991,20 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
1396913991 } else if (opcode == BPF_MOV) {
1397013992
1397113993 if (BPF_SRC(insn->code) == BPF_X) {
13972- if (insn->imm != 0) {
13973- verbose(env, "BPF_MOV uses reserved fields\n");
13974- return -EINVAL;
13975- }
13976-
1397713994 if (BPF_CLASS(insn->code) == BPF_ALU) {
13978- if (insn->off != 0 && insn->off != 8 && insn->off != 16) {
13995+ if ((insn->off != 0 && insn->off != 8 && insn->off != 16) ||
13996+ insn->imm) {
1397913997 verbose(env, "BPF_MOV uses reserved fields\n");
1398013998 return -EINVAL;
1398113999 }
14000+ } else if (insn->off == BPF_ADDR_SPACE_CAST) {
14001+ if (insn->imm != 1 && insn->imm != 1u << 16) {
14002+ verbose(env, "addr_space_cast insn can only convert between address space 1 and 0\n");
14003+ return -EINVAL;
14004+ }
1398214005 } else {
13983- if (insn->off != 0 && insn->off != 8 && insn->off != 16 &&
13984- insn->off != 32) {
14006+ if (( insn->off != 0 && insn->off != 8 && insn->off != 16 &&
14007+ insn->off != 32) || insn->imm ) {
1398514008 verbose(env, "BPF_MOV uses reserved fields\n");
1398614009 return -EINVAL;
1398714010 }
@@ -14008,7 +14031,12 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
1400814031 struct bpf_reg_state *dst_reg = regs + insn->dst_reg;
1400914032
1401014033 if (BPF_CLASS(insn->code) == BPF_ALU64) {
14011- if (insn->off == 0) {
14034+ if (insn->imm) {
14035+ /* off == BPF_ADDR_SPACE_CAST */
14036+ mark_reg_unknown(env, regs, insn->dst_reg);
14037+ if (insn->imm == 1) /* cast from as(1) to as(0) */
14038+ dst_reg->type = PTR_TO_ARENA;
14039+ } else if (insn->off == 0) {
1401214040 /* case: R1 = R2
1401314041 * copy register state to dest reg
1401414042 */
@@ -15182,6 +15210,10 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
1518215210
1518315211 if (insn->src_reg == BPF_PSEUDO_MAP_VALUE ||
1518415212 insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE) {
15213+ if (map->map_type == BPF_MAP_TYPE_ARENA) {
15214+ __mark_reg_unknown(env, dst_reg);
15215+ return 0;
15216+ }
1518515217 dst_reg->type = PTR_TO_MAP_VALUE;
1518615218 dst_reg->off = aux->map_off;
1518715219 WARN_ON_ONCE(map->max_entries != 1);
@@ -16568,6 +16600,8 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
1656816600 * the same stack frame, since fp-8 in foo != fp-8 in bar
1656916601 */
1657016602 return regs_exact(rold, rcur, idmap) && rold->frameno == rcur->frameno;
16603+ case PTR_TO_ARENA:
16604+ return true;
1657116605 default:
1657216606 return regs_exact(rold, rcur, idmap);
1657316607 }
@@ -17443,6 +17477,7 @@ static bool reg_type_mismatch_ok(enum bpf_reg_type type)
1744317477 case PTR_TO_TCP_SOCK:
1744417478 case PTR_TO_XDP_SOCK:
1744517479 case PTR_TO_BTF_ID:
17480+ case PTR_TO_ARENA:
1744617481 return false;
1744717482 default:
1744817483 return true;
@@ -18296,6 +18331,31 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env)
1829618331 fdput(f);
1829718332 return -EBUSY;
1829818333 }
18334+ if (map->map_type == BPF_MAP_TYPE_ARENA) {
18335+ if (env->prog->aux->arena) {
18336+ verbose(env, "Only one arena per program\n");
18337+ fdput(f);
18338+ return -EBUSY;
18339+ }
18340+ if (!env->allow_ptr_leaks || !env->bpf_capable) {
18341+ verbose(env, "CAP_BPF and CAP_PERFMON are required to use arena\n");
18342+ fdput(f);
18343+ return -EPERM;
18344+ }
18345+ if (!env->prog->jit_requested) {
18346+ verbose(env, "JIT is required to use arena\n");
18347+ return -EOPNOTSUPP;
18348+ }
18349+ if (!bpf_jit_supports_arena()) {
18350+ verbose(env, "JIT doesn't support arena\n");
18351+ return -EOPNOTSUPP;
18352+ }
18353+ env->prog->aux->arena = (void *)map;
18354+ if (!bpf_arena_get_user_vm_start(env->prog->aux->arena)) {
18355+ verbose(env, "arena's user address must be set via map_extra or mmap()\n");
18356+ return -EINVAL;
18357+ }
18358+ }
1829918359
1830018360 fdput(f);
1830118361next_insn:
@@ -18917,6 +18977,14 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
1891718977 env->prog->aux->num_exentries++;
1891818978 }
1891918979 continue;
18980+ case PTR_TO_ARENA:
18981+ if (BPF_MODE(insn->code) == BPF_MEMSX) {
18982+ verbose(env, "sign extending loads from arena are not supported yet\n");
18983+ return -EOPNOTSUPP;
18984+ }
18985+ insn->code = BPF_CLASS(insn->code) | BPF_PROBE_MEM32 | BPF_SIZE(insn->code);
18986+ env->prog->aux->num_exentries++;
18987+ continue;
1892018988 default:
1892118989 continue;
1892218990 }
@@ -19102,13 +19170,19 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1910219170 func[i]->aux->nr_linfo = prog->aux->nr_linfo;
1910319171 func[i]->aux->jited_linfo = prog->aux->jited_linfo;
1910419172 func[i]->aux->linfo_idx = env->subprog_info[i].linfo_idx;
19173+ func[i]->aux->arena = prog->aux->arena;
1910519174 num_exentries = 0;
1910619175 insn = func[i]->insnsi;
1910719176 for (j = 0; j < func[i]->len; j++, insn++) {
1910819177 if (BPF_CLASS(insn->code) == BPF_LDX &&
1910919178 (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
19179+ BPF_MODE(insn->code) == BPF_PROBE_MEM32 ||
1911019180 BPF_MODE(insn->code) == BPF_PROBE_MEMSX))
1911119181 num_exentries++;
19182+ if ((BPF_CLASS(insn->code) == BPF_STX ||
19183+ BPF_CLASS(insn->code) == BPF_ST) &&
19184+ BPF_MODE(insn->code) == BPF_PROBE_MEM32)
19185+ num_exentries++;
1911219186 }
1911319187 func[i]->aux->num_exentries = num_exentries;
1911419188 func[i]->aux->tail_call_reachable = env->subprog_info[i].tail_call_reachable;
@@ -19507,6 +19581,21 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1950719581 }
1950819582
1950919583 for (i = 0; i < insn_cnt;) {
19584+ if (insn->code == (BPF_ALU64 | BPF_MOV | BPF_X) && insn->imm) {
19585+ if ((insn->off == BPF_ADDR_SPACE_CAST && insn->imm == 1) ||
19586+ (((struct bpf_map *)env->prog->aux->arena)->map_flags & BPF_F_NO_USER_CONV)) {
19587+ /* convert to 32-bit mov that clears upper 32-bit */
19588+ insn->code = BPF_ALU | BPF_MOV | BPF_X;
19589+ /* clear off, so it's a normal 'wX = wY' from JIT pov */
19590+ insn->off = 0;
19591+ } /* cast from as(0) to as(1) should be handled by JIT */
19592+ goto next_insn;
19593+ }
19594+
19595+ if (env->insn_aux_data[i + delta].needs_zext)
19596+ /* Convert BPF_CLASS(insn->code) == BPF_ALU64 to 32-bit ALU */
19597+ insn->code = BPF_ALU | BPF_OP(insn->code) | BPF_SRC(insn->code);
19598+
1951019599 /* Make divide-by-zero exceptions impossible. */
1951119600 if (insn->code == (BPF_ALU64 | BPF_MOD | BPF_X) ||
1951219601 insn->code == (BPF_ALU64 | BPF_DIV | BPF_X) ||
0 commit comments