| @@ -238,6 +238,8 @@ struct bpf_call_arg_meta { · 237 unmodified lines |
| 238 | u64 msize_max_value; | 238 | u64 msize_max_value; |
| 239 | int ref_obj_id; | 239 | int ref_obj_id; |
| 240 | int func_id; | 240 | int func_id; |
| | 241 | u32 btf_id; |
| | 242 | u32 ret_btf_id; |
| 241 | }; | 243 | }; |
| 242 | | 244 | |
| 243 | struct btf *btf_vmlinux; | 245 | struct btf *btf_vmlinux; |
| @@ -517,6 +519,7 @@ static const char * const reg_type_str[] = { · 273 unmodified lines |
| 517 | [PTR_TO_XDP_SOCK] = "xdp_sock", | 519 | [PTR_TO_XDP_SOCK] = "xdp_sock", |
| 518 | [PTR_TO_BTF_ID] = "ptr_", | 520 | [PTR_TO_BTF_ID] = "ptr_", |
| 519 | [PTR_TO_BTF_ID_OR_NULL] = "ptr_or_null_", | 521 | [PTR_TO_BTF_ID_OR_NULL] = "ptr_or_null_", |
| | 522 | [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_", |
| 520 | [PTR_TO_MEM] = "mem", | 523 | [PTR_TO_MEM] = "mem", |
| 521 | [PTR_TO_MEM_OR_NULL] = "mem_or_null", | 524 | [PTR_TO_MEM_OR_NULL] = "mem_or_null", |
| 522 | [PTR_TO_RDONLY_BUF] = "rdonly_buf", | 525 | [PTR_TO_RDONLY_BUF] = "rdonly_buf", |
| @@ -583,7 +586,9 @@ static void print_verifier_state(struct bpf_verifier_env *env, · 60 unmodified lines |
| 583 | /* reg->off should be 0 for SCALAR_VALUE */ | 586 | /* reg->off should be 0 for SCALAR_VALUE */ |
| 584 | verbose(env, "%lld", reg->var_off.value + reg->off); | 587 | verbose(env, "%lld", reg->var_off.value + reg->off); |
| 585 | } else { | 588 | } else { |
| 586 | if (t == PTR_TO_BTF_ID || t == PTR_TO_BTF_ID_OR_NULL) | 589 | if (t == PTR_TO_BTF_ID || |
| | 590 | t == PTR_TO_BTF_ID_OR_NULL || |
| | 591 | t == PTR_TO_PERCPU_BTF_ID) |
| 587 | verbose(env, "%s", kernel_type_name(reg->btf_id)); | 592 | verbose(env, "%s", kernel_type_name(reg->btf_id)); |
| 588 | verbose(env, "(id=%d", reg->id); | 593 | verbose(env, "(id=%d", reg->id); |
| 589 | if (reg_type_may_be_refcounted_or_null(t)) | 594 | if (reg_type_may_be_refcounted_or_null(t)) |
| @@ -2204,6 +2209,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type) · 1614 unmodified lines |
| 2204 | case PTR_TO_RDONLY_BUF_OR_NULL: | 2209 | case PTR_TO_RDONLY_BUF_OR_NULL: |
| 2205 | case PTR_TO_RDWR_BUF: | 2210 | case PTR_TO_RDWR_BUF: |
| 2206 | case PTR_TO_RDWR_BUF_OR_NULL: | 2211 | case PTR_TO_RDWR_BUF_OR_NULL: |
| | 2212 | case PTR_TO_PERCPU_BTF_ID: |
| 2207 | return true; | 2213 | return true; |
| 2208 | default: | 2214 | default: |
| 2209 | return false; | 2215 | return false; |
| @@ -4017,6 +4023,7 @@ static const struct bpf_reg_types alloc_mem_types = { .types = { PTR_TO_MEM } }; · 1807 unmodified lines |
| 4017 | static const struct bpf_reg_types const_map_ptr_types = { .types = { CONST_PTR_TO_MAP } }; | 4023 | static const struct bpf_reg_types const_map_ptr_types = { .types = { CONST_PTR_TO_MAP } }; |
| 4018 | static const struct bpf_reg_types btf_ptr_types = { .types = { PTR_TO_BTF_ID } }; | 4024 | static const struct bpf_reg_types btf_ptr_types = { .types = { PTR_TO_BTF_ID } }; |
| 4019 | static const struct bpf_reg_types spin_lock_types = { .types = { PTR_TO_MAP_VALUE } }; | 4025 | static const struct bpf_reg_types spin_lock_types = { .types = { PTR_TO_MAP_VALUE } }; |
| | 4026 | static const struct bpf_reg_types percpu_btf_ptr_types = { .types = { PTR_TO_PERCPU_BTF_ID } }; |
| 4020 | | 4027 | |
| 4021 | static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = { | 4028 | static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = { |
| 4022 | [ARG_PTR_TO_MAP_KEY] = &map_key_value_types, | 4029 | [ARG_PTR_TO_MAP_KEY] = &map_key_value_types, |
| @@ -4042,6 +4049,7 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = { · 19 unmodified lines |
| 4042 | [ARG_PTR_TO_ALLOC_MEM_OR_NULL] = &alloc_mem_types, | 4049 | [ARG_PTR_TO_ALLOC_MEM_OR_NULL] = &alloc_mem_types, |
| 4043 | [ARG_PTR_TO_INT] = &int_ptr_types, | 4050 | [ARG_PTR_TO_INT] = &int_ptr_types, |
| 4044 | [ARG_PTR_TO_LONG] = &int_ptr_types, | 4051 | [ARG_PTR_TO_LONG] = &int_ptr_types, |
| | 4052 | [ARG_PTR_TO_PERCPU_BTF_ID] = &percpu_btf_ptr_types, |
| 4045 | }; | 4053 | }; |
| 4046 | | 4054 | |
| 4047 | static int check_reg_type(struct bpf_verifier_env *env, u32 regno, | 4055 | static int check_reg_type(struct bpf_verifier_env *env, u32 regno, |
| @@ -4205,6 +4213,12 @@ skip_type_check: · 157 unmodified lines |
| 4205 | err = check_helper_mem_access(env, regno, | 4213 | err = check_helper_mem_access(env, regno, |
| 4206 | meta->map_ptr->value_size, false, | 4214 | meta->map_ptr->value_size, false, |
| 4207 | meta); | 4215 | meta); |
| | 4216 | } else if (arg_type == ARG_PTR_TO_PERCPU_BTF_ID) { |
| | 4217 | if (!reg->btf_id) { |
| | 4218 | verbose(env, "Helper has invalid btf_id in R%d\n", regno); |
| | 4219 | return -EACCES; |
| | 4220 | } |
| | 4221 | meta->ret_btf_id = reg->btf_id; |
| 4208 | } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) { | 4222 | } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) { |
| 4209 | if (meta->func_id == BPF_FUNC_spin_lock) { | 4223 | if (meta->func_id == BPF_FUNC_spin_lock) { |
| 4210 | if (process_spin_lock(env, regno, true)) | 4224 | if (process_spin_lock(env, regno, true)) |
| @@ -5114,6 +5128,30 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn · 903 unmodified lines |
| 5114 | regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL; | 5128 | regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL; |
| 5115 | regs[BPF_REG_0].id = ++env->id_gen; | 5129 | regs[BPF_REG_0].id = ++env->id_gen; |
| 5116 | regs[BPF_REG_0].mem_size = meta.mem_size; | 5130 | regs[BPF_REG_0].mem_size = meta.mem_size; |
| | 5131 | } else if (fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL) { |
| | 5132 | const struct btf_type *t; |
| | 5133 | |
| | 5134 | mark_reg_known_zero(env, regs, BPF_REG_0); |
| | 5135 | t = btf_type_skip_modifiers(btf_vmlinux, meta.ret_btf_id, NULL); |
| | 5136 | if (!btf_type_is_struct(t)) { |
| | 5137 | u32 tsize; |
| | 5138 | const struct btf_type *ret; |
| | 5139 | const char *tname; |
| | 5140 | |
| | 5141 | /* resolve the type size of ksym. */ |
| | 5142 | ret = btf_resolve_size(btf_vmlinux, t, &tsize); |
| | 5143 | if (IS_ERR(ret)) { |
| | 5144 | tname = btf_name_by_offset(btf_vmlinux, t->name_off); |
| | 5145 | verbose(env, "unable to resolve the size of type '%s': %ld\n", |
| | 5146 | tname, PTR_ERR(ret)); |
| | 5147 | return -EINVAL; |
| | 5148 | } |
| | 5149 | regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL; |
| | 5150 | regs[BPF_REG_0].mem_size = tsize; |
| | 5151 | } else { |
| | 5152 | regs[BPF_REG_0].type = PTR_TO_BTF_ID_OR_NULL; |
| | 5153 | regs[BPF_REG_0].btf_id = meta.ret_btf_id; |
| | 5154 | } |
| 5117 | } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL) { | 5155 | } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL) { |
| 5118 | int ret_btf_id; | 5156 | int ret_btf_id; |
| 5119 | | 5157 | |
| @@ -7523,6 +7561,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) · 2403 unmodified lines |
| 7523 | dst_reg->mem_size = aux->btf_var.mem_size; | 7561 | dst_reg->mem_size = aux->btf_var.mem_size; |
| 7524 | break; | 7562 | break; |
| 7525 | case PTR_TO_BTF_ID: | 7563 | case PTR_TO_BTF_ID: |
| | 7564 | case PTR_TO_PERCPU_BTF_ID: |
| 7526 | dst_reg->btf_id = aux->btf_var.btf_id; | 7565 | dst_reg->btf_id = aux->btf_var.btf_id; |
| 7527 | break; | 7566 | break; |
| 7528 | default: | 7567 | default: |
| @@ -9449,10 +9488,14 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env, · 1920 unmodified lines |
| 9449 | struct bpf_insn *insn, | 9488 | struct bpf_insn *insn, |
| 9450 | struct bpf_insn_aux_data *aux) | 9489 | struct bpf_insn_aux_data *aux) |
| 9451 | { | 9490 | { |
| 9452 | u32 type, id = insn->imm; | 9491 | u32 datasec_id, type, id = insn->imm; |
| | 9492 | const struct btf_var_secinfo *vsi; |
| | 9493 | const struct btf_type *datasec; |
| 9453 | const struct btf_type *t; | 9494 | const struct btf_type *t; |
| 9454 | const char *sym_name; | 9495 | const char *sym_name; |
| | 9496 | bool percpu = false; |
| 9455 | u64 addr; | 9497 | u64 addr; |
| | 9498 | int i; |
| 9456 | | 9499 | |
| 9457 | if (!btf_vmlinux) { | 9500 | if (!btf_vmlinux) { |
| 9458 | verbose(env, "kernel is missing BTF, make sure CONFIG_DEBUG_INFO_BTF=y is specified in Kconfig.\n"); | 9501 | verbose(env, "kernel is missing BTF, make sure CONFIG_DEBUG_INFO_BTF=y is specified in Kconfig.\n"); |
| @@ -9484,12 +9527,27 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env, · 25 unmodified lines |
| 9484 | return -ENOENT; | 9527 | return -ENOENT; |
| 9485 | } | 9528 | } |
| 9486 | | 9529 | |
| | 9530 | datasec_id = btf_find_by_name_kind(btf_vmlinux, ".data..percpu", |
| | 9531 | BTF_KIND_DATASEC); |
| | 9532 | if (datasec_id > 0) { |
| | 9533 | datasec = btf_type_by_id(btf_vmlinux, datasec_id); |
| | 9534 | for_each_vsi(i, datasec, vsi) { |
| | 9535 | if (vsi->type == id) { |
| | 9536 | percpu = true; |
| | 9537 | break; |
| | 9538 | } |
| | 9539 | } |
| | 9540 | } |
| | 9541 | |
| 9487 | insn[0].imm = (u32)addr; | 9542 | insn[0].imm = (u32)addr; |
| 9488 | insn[1].imm = addr >> 32; | 9543 | insn[1].imm = addr >> 32; |
| 9489 | | 9544 | |
| 9490 | type = t->type; | 9545 | type = t->type; |
| 9491 | t = btf_type_skip_modifiers(btf_vmlinux, type, NULL); | 9546 | t = btf_type_skip_modifiers(btf_vmlinux, type, NULL); |
| 9492 | if (!btf_type_is_struct(t)) { | 9547 | if (percpu) { |
| | 9548 | aux->btf_var.reg_type = PTR_TO_PERCPU_BTF_ID; |
| | 9549 | aux->btf_var.btf_id = type; |
| | 9550 | } else if (!btf_type_is_struct(t)) { |
| 9493 | const struct btf_type *ret; | 9551 | const struct btf_type *ret; |
| 9494 | const char *tname; | 9552 | const char *tname; |
| 9495 | u32 tsize; | 9553 | u32 tsize; |