Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bpf_func_info-improvements'

Martin KaFai Lau says:

====================
The patchset has a few improvements on bpf_func_info:
1. Improvements on the behaviors of info.func_info, info.func_info_cnt
and info.func_info_rec_size.
2. Name change: s/insn_offset/insn_off/

Please see individual patch for details.
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+53 -46
+1 -1
include/uapi/linux/bpf.h
··· 2991 2991 }; 2992 2992 2993 2993 struct bpf_func_info { 2994 - __u32 insn_offset; 2994 + __u32 insn_off; 2995 2995 __u32 type_id; 2996 2996 }; 2997 2997
+1 -1
kernel/bpf/core.c
··· 410 410 sym = bin2hex(sym, prog->tag, sizeof(prog->tag)); 411 411 412 412 /* prog->aux->name will be ignored if full btf name is available */ 413 - if (prog->aux->btf) { 413 + if (prog->aux->func_info_cnt) { 414 414 type = btf_type_by_id(prog->aux->btf, 415 415 prog->aux->func_info[prog->aux->func_idx].type_id); 416 416 func_name = btf_name_by_offset(prog->aux->btf, type->name_off);
+19 -25
kernel/bpf/syscall.c
··· 2083 2083 return -EFAULT; 2084 2084 } 2085 2085 2086 + if ((info.func_info_cnt || info.func_info_rec_size) && 2087 + info.func_info_rec_size != sizeof(struct bpf_func_info)) 2088 + return -EINVAL; 2089 + 2090 + info.func_info_rec_size = sizeof(struct bpf_func_info); 2091 + 2086 2092 if (!capable(CAP_SYS_ADMIN)) { 2087 2093 info.jited_prog_len = 0; 2088 2094 info.xlated_prog_len = 0; ··· 2232 2226 } 2233 2227 } 2234 2228 2235 - if (prog->aux->btf) { 2236 - u32 krec_size = sizeof(struct bpf_func_info); 2237 - u32 ucnt, urec_size; 2238 - 2229 + if (prog->aux->btf) 2239 2230 info.btf_id = btf_id(prog->aux->btf); 2240 2231 2241 - ucnt = info.func_info_cnt; 2242 - info.func_info_cnt = prog->aux->func_info_cnt; 2243 - urec_size = info.func_info_rec_size; 2244 - info.func_info_rec_size = krec_size; 2245 - if (ucnt) { 2246 - /* expect passed-in urec_size is what the kernel expects */ 2247 - if (urec_size != info.func_info_rec_size) 2248 - return -EINVAL; 2232 + ulen = info.func_info_cnt; 2233 + info.func_info_cnt = prog->aux->func_info_cnt; 2234 + if (info.func_info_cnt && ulen) { 2235 + if (bpf_dump_raw_ok()) { 2236 + char __user *user_finfo; 2249 2237 2250 - if (bpf_dump_raw_ok()) { 2251 - char __user *user_finfo; 2252 - 2253 - user_finfo = u64_to_user_ptr(info.func_info); 2254 - ucnt = min_t(u32, info.func_info_cnt, ucnt); 2255 - if (copy_to_user(user_finfo, prog->aux->func_info, 2256 - krec_size * ucnt)) 2257 - return -EFAULT; 2258 - } else { 2259 - info.func_info_cnt = 0; 2260 - } 2238 + user_finfo = u64_to_user_ptr(info.func_info); 2239 + ulen = min_t(u32, info.func_info_cnt, ulen); 2240 + if (copy_to_user(user_finfo, prog->aux->func_info, 2241 + info.func_info_rec_size * ulen)) 2242 + return -EFAULT; 2243 + } else { 2244 + info.func_info = 0; 2261 2245 } 2262 - } else { 2263 - info.func_info_cnt = 0; 2264 2246 } 2265 2247 2266 2248 done:
+9 -9
kernel/bpf/verifier.c
··· 4707 4707 goto free_btf; 4708 4708 } 4709 4709 4710 - /* check insn_offset */ 4710 + /* check insn_off */ 4711 4711 if (i == 0) { 4712 - if (krecord[i].insn_offset) { 4712 + if (krecord[i].insn_off) { 4713 4713 verbose(env, 4714 - "nonzero insn_offset %u for the first func info record", 4715 - krecord[i].insn_offset); 4714 + "nonzero insn_off %u for the first func info record", 4715 + krecord[i].insn_off); 4716 4716 ret = -EINVAL; 4717 4717 goto free_btf; 4718 4718 } 4719 - } else if (krecord[i].insn_offset <= prev_offset) { 4719 + } else if (krecord[i].insn_off <= prev_offset) { 4720 4720 verbose(env, 4721 4721 "same or smaller insn offset (%u) than previous func info record (%u)", 4722 - krecord[i].insn_offset, prev_offset); 4722 + krecord[i].insn_off, prev_offset); 4723 4723 ret = -EINVAL; 4724 4724 goto free_btf; 4725 4725 } 4726 4726 4727 - if (env->subprog_info[i].start != krecord[i].insn_offset) { 4727 + if (env->subprog_info[i].start != krecord[i].insn_off) { 4728 4728 verbose(env, "func_info BTF section doesn't match subprog layout in BPF program\n"); 4729 4729 ret = -EINVAL; 4730 4730 goto free_btf; ··· 4739 4739 goto free_btf; 4740 4740 } 4741 4741 4742 - prev_offset = krecord[i].insn_offset; 4742 + prev_offset = krecord[i].insn_off; 4743 4743 urecord += urec_size; 4744 4744 } 4745 4745 ··· 4762 4762 return; 4763 4763 4764 4764 for (i = 0; i < env->subprog_cnt; i++) 4765 - env->prog->aux->func_info[i].insn_offset = env->subprog_info[i].start; 4765 + env->prog->aux->func_info[i].insn_off = env->subprog_info[i].start; 4766 4766 } 4767 4767 4768 4768 /* check %cur's range satisfies %old's */
+7
tools/bpf/bpftool/prog.c
··· 589 589 goto err_free; 590 590 } 591 591 592 + if (func_info && !info.func_info) { 593 + /* kernel.kptr_restrict is set. No func_info available. */ 594 + free(func_info); 595 + func_info = NULL; 596 + finfo_cnt = 0; 597 + } 598 + 592 599 if ((member_len == &info.jited_prog_len && 593 600 info.jited_prog_insns == 0) || 594 601 (member_len == &info.xlated_prog_len &&
+2 -2
tools/bpf/bpftool/xlated_dumper.c
··· 261 261 jsonw_start_object(json_wtr); 262 262 263 263 if (btf && record) { 264 - if (record->insn_offset == i) { 264 + if (record->insn_off == i) { 265 265 btf_dumper_type_only(btf, record->type_id, 266 266 func_sig, 267 267 sizeof(func_sig)); ··· 330 330 } 331 331 332 332 if (btf && record) { 333 - if (record->insn_offset == i) { 333 + if (record->insn_off == i) { 334 334 btf_dumper_type_only(btf, record->type_id, 335 335 func_sig, 336 336 sizeof(func_sig));
+1 -1
tools/include/uapi/linux/bpf.h
··· 2991 2991 }; 2992 2992 2993 2993 struct bpf_func_info { 2994 - __u32 insn_offset; 2994 + __u32 insn_off; 2995 2995 __u32 type_id; 2996 2996 }; 2997 2997
+6 -6
tools/lib/bpf/btf.c
··· 45 45 46 46 /* The minimum bpf_func_info checked by the loader */ 47 47 struct bpf_func_info_min { 48 - __u32 insn_offset; 48 + __u32 insn_off; 49 49 __u32 type_id; 50 50 }; 51 51 ··· 670 670 671 671 memcpy(data, sinfo->data, records_len); 672 672 673 - /* adjust the insn_offset, the data in .BTF.ext is 673 + /* adjust the insn_off, the data in .BTF.ext is 674 674 * the actual byte offset, and the kernel expects 675 675 * the offset in term of bpf_insn. 676 676 * ··· 681 681 struct bpf_func_info_min *record; 682 682 683 683 record = data + i * record_size; 684 - record->insn_offset /= sizeof(struct bpf_insn); 684 + record->insn_off /= sizeof(struct bpf_insn); 685 685 } 686 686 687 687 *func_info = data; ··· 722 722 return -ENOMEM; 723 723 724 724 memcpy(data + existing_flen, sinfo->data, records_len); 725 - /* adjust insn_offset only, the rest data will be passed 725 + /* adjust insn_off only, the rest data will be passed 726 726 * to the kernel. 727 727 */ 728 728 for (i = 0; i < sinfo->num_func_info; i++) { 729 729 struct bpf_func_info_min *record; 730 730 731 731 record = data + existing_flen + i * record_size; 732 - record->insn_offset = 733 - record->insn_offset / sizeof(struct bpf_insn) + 732 + record->insn_off = 733 + record->insn_off / sizeof(struct bpf_insn) + 734 734 insns_cnt; 735 735 } 736 736 *func_info = data;
+7 -1
tools/testing/selftests/bpf/test_btf.c
··· 3156 3156 }, 3157 3157 3158 3158 { 3159 - .descr = "func_type (Incorrect bpf_func_info.insn_offset)", 3159 + .descr = "func_type (Incorrect bpf_func_info.insn_off)", 3160 3160 .raw_types = { 3161 3161 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3162 3162 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */ ··· 3299 3299 if (CHECK(info.func_info_rec_size != rec_size, 3300 3300 "incorrect info.func_info_rec_size (2nd) %d\n", 3301 3301 info.func_info_rec_size)) { 3302 + err = -1; 3303 + goto done; 3304 + } 3305 + 3306 + if (CHECK(!info.func_info, 3307 + "info.func_info == 0. kernel.kptr_restrict is set?")) { 3302 3308 err = -1; 3303 3309 goto done; 3304 3310 }