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

Merge branch 'enhance-bpf-global-subprogs-with-argument-tags'

Andrii Nakryiko says:

====================
Enhance BPF global subprogs with argument tags

This patch set adds verifier support for annotating user's global BPF subprog
arguments with few commonly requested annotations, to improve global subprog
verification experience.

These tags are:
- ability to annotate a special PTR_TO_CTX argument;
- ability to annotate a generic PTR_TO_MEM as non-null.

We utilize btf_decl_tag attribute for this and provide two helper macros as
part of bpf_helpers.h in libbpf (patch #8).

Besides this we also add abilit to pass a pointer to dynptr into global
subprog. This is done based on type name match (struct bpf_dynptr *). This
allows to pass dynptrs into global subprogs, for use cases that deal with
variable-sized generic memory pointers.

Big chunk of the patch set (patches #1 through #5) are various refactorings to
make verifier internals around global subprog validation logic easier to
extend and support long term, eliminating BTF parsing logic duplication,
factoring out argument expectation definitions from BTF parsing, etc.

New functionality is added in patch #6 (ctx and non-null) and patch #7
(dynptr), extending global subprog checks with awareness for arg tags.

Patch #9 adds simple tests validating each of the added tags and dynptr
argument passing.

Patch #10 adds a simple negative case for freplace programs to make sure that
target BPF programs with "unreliable" BTF func proto cannot be freplaced.

v2->v3:
- patch #10 improved by checking expected verifier error (Eduard);
v1->v2:
- dropped packet args for now (Eduard);
- added back unreliable=true detection for entry BPF programs (Eduard);
- improved subprog arg validation (Eduard);
- switched dynptr arg from tag to just type name based check (Eduard).
====================

Link: https://lore.kernel.org/r/20231215011334.2307144-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+418 -272
+1 -6
include/linux/bpf.h
··· 2466 2466 struct btf_func_model *m); 2467 2467 2468 2468 struct bpf_reg_state; 2469 - int btf_check_subprog_arg_match(struct bpf_verifier_env *env, int subprog, 2470 - struct bpf_reg_state *regs); 2471 - int btf_check_subprog_call(struct bpf_verifier_env *env, int subprog, 2472 - struct bpf_reg_state *regs); 2473 - int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog, 2474 - struct bpf_reg_state *reg, u32 *nargs); 2469 + int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog); 2475 2470 int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *prog, 2476 2471 struct btf *btf, const struct btf_type *t); 2477 2472 const char *btf_find_decl_tag_value(const struct btf *btf, const struct btf_type *pt,
+21 -8
include/linux/bpf_verifier.h
··· 606 606 607 607 #define BPF_MAX_SUBPROGS 256 608 608 609 + struct bpf_subprog_arg_info { 610 + enum bpf_arg_type arg_type; 611 + union { 612 + u32 mem_size; 613 + }; 614 + }; 615 + 609 616 struct bpf_subprog_info { 610 617 /* 'start' has to be the first field otherwise find_subprog() won't work */ 611 618 u32 start; /* insn idx of function entry point */ ··· 624 617 bool is_cb: 1; 625 618 bool is_async_cb: 1; 626 619 bool is_exception_cb: 1; 620 + bool args_cached: 1; 621 + 622 + u8 arg_cnt; 623 + struct bpf_subprog_arg_info args[MAX_BPF_FUNC_REG_ARGS]; 627 624 }; 628 625 629 626 struct bpf_verifier_env; ··· 738 727 char tmp_str_buf[TMP_STR_BUF_LEN]; 739 728 }; 740 729 730 + static inline struct bpf_func_info_aux *subprog_aux(struct bpf_verifier_env *env, int subprog) 731 + { 732 + return &env->prog->aux->func_info_aux[subprog]; 733 + } 734 + 735 + static inline struct bpf_subprog_info *subprog_info(struct bpf_verifier_env *env, int subprog) 736 + { 737 + return &env->subprog_info[subprog]; 738 + } 739 + 741 740 __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log, 742 741 const char *fmt, va_list args); 743 742 __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, ··· 784 763 struct bpf_insn *insn); 785 764 void 786 765 bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt); 787 - 788 - int check_ptr_off_reg(struct bpf_verifier_env *env, 789 - const struct bpf_reg_state *reg, int regno); 790 - int check_func_arg_reg_off(struct bpf_verifier_env *env, 791 - const struct bpf_reg_state *reg, int regno, 792 - enum bpf_arg_type arg_type); 793 - int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, 794 - u32 regno, u32 mem_size); 795 766 796 767 /* this lives here instead of in bpf.h because it needs to dereference tgt_prog */ 797 768 static inline u64 bpf_trampoline_compute_key(const struct bpf_prog *tgt_prog,
+79 -205
kernel/bpf/btf.c
··· 6765 6765 return btf_check_func_type_match(log, btf1, t1, btf2, t2); 6766 6766 } 6767 6767 6768 - static int btf_check_func_arg_match(struct bpf_verifier_env *env, 6769 - const struct btf *btf, u32 func_id, 6770 - struct bpf_reg_state *regs, 6771 - bool ptr_to_mem_ok, 6772 - bool processing_call) 6768 + static bool btf_is_dynptr_ptr(const struct btf *btf, const struct btf_type *t) 6773 6769 { 6774 - enum bpf_prog_type prog_type = resolve_prog_type(env->prog); 6775 - struct bpf_verifier_log *log = &env->log; 6776 - const char *func_name, *ref_tname; 6777 - const struct btf_type *t, *ref_t; 6778 - const struct btf_param *args; 6779 - u32 i, nargs, ref_id; 6780 - int ret; 6770 + const char *name; 6781 6771 6782 - t = btf_type_by_id(btf, func_id); 6783 - if (!t || !btf_type_is_func(t)) { 6784 - /* These checks were already done by the verifier while loading 6785 - * struct bpf_func_info or in add_kfunc_call(). 6786 - */ 6787 - bpf_log(log, "BTF of func_id %u doesn't point to KIND_FUNC\n", 6788 - func_id); 6789 - return -EFAULT; 6790 - } 6791 - func_name = btf_name_by_offset(btf, t->name_off); 6772 + t = btf_type_by_id(btf, t->type); /* skip PTR */ 6792 6773 6793 - t = btf_type_by_id(btf, t->type); 6794 - if (!t || !btf_type_is_func_proto(t)) { 6795 - bpf_log(log, "Invalid BTF of func %s\n", func_name); 6796 - return -EFAULT; 6797 - } 6798 - args = (const struct btf_param *)(t + 1); 6799 - nargs = btf_type_vlen(t); 6800 - if (nargs > MAX_BPF_FUNC_REG_ARGS) { 6801 - bpf_log(log, "Function %s has %d > %d args\n", func_name, nargs, 6802 - MAX_BPF_FUNC_REG_ARGS); 6803 - return -EINVAL; 6774 + while (btf_type_is_modifier(t)) 6775 + t = btf_type_by_id(btf, t->type); 6776 + 6777 + /* allow either struct or struct forward declaration */ 6778 + if (btf_type_is_struct(t) || 6779 + (btf_type_is_fwd(t) && btf_type_kflag(t) == 0)) { 6780 + name = btf_str_by_offset(btf, t->name_off); 6781 + return name && strcmp(name, "bpf_dynptr") == 0; 6804 6782 } 6805 6783 6806 - /* check that BTF function arguments match actual types that the 6807 - * verifier sees. 6808 - */ 6809 - for (i = 0; i < nargs; i++) { 6810 - enum bpf_arg_type arg_type = ARG_DONTCARE; 6811 - u32 regno = i + 1; 6812 - struct bpf_reg_state *reg = &regs[regno]; 6813 - 6814 - t = btf_type_skip_modifiers(btf, args[i].type, NULL); 6815 - if (btf_type_is_scalar(t)) { 6816 - if (reg->type == SCALAR_VALUE) 6817 - continue; 6818 - bpf_log(log, "R%d is not a scalar\n", regno); 6819 - return -EINVAL; 6820 - } 6821 - 6822 - if (!btf_type_is_ptr(t)) { 6823 - bpf_log(log, "Unrecognized arg#%d type %s\n", 6824 - i, btf_type_str(t)); 6825 - return -EINVAL; 6826 - } 6827 - 6828 - ref_t = btf_type_skip_modifiers(btf, t->type, &ref_id); 6829 - ref_tname = btf_name_by_offset(btf, ref_t->name_off); 6830 - 6831 - ret = check_func_arg_reg_off(env, reg, regno, arg_type); 6832 - if (ret < 0) 6833 - return ret; 6834 - 6835 - if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { 6836 - /* If function expects ctx type in BTF check that caller 6837 - * is passing PTR_TO_CTX. 6838 - */ 6839 - if (reg->type != PTR_TO_CTX) { 6840 - bpf_log(log, 6841 - "arg#%d expected pointer to ctx, but got %s\n", 6842 - i, btf_type_str(t)); 6843 - return -EINVAL; 6844 - } 6845 - } else if (ptr_to_mem_ok && processing_call) { 6846 - const struct btf_type *resolve_ret; 6847 - u32 type_size; 6848 - 6849 - resolve_ret = btf_resolve_size(btf, ref_t, &type_size); 6850 - if (IS_ERR(resolve_ret)) { 6851 - bpf_log(log, 6852 - "arg#%d reference type('%s %s') size cannot be determined: %ld\n", 6853 - i, btf_type_str(ref_t), ref_tname, 6854 - PTR_ERR(resolve_ret)); 6855 - return -EINVAL; 6856 - } 6857 - 6858 - if (check_mem_reg(env, reg, regno, type_size)) 6859 - return -EINVAL; 6860 - } else { 6861 - bpf_log(log, "reg type unsupported for arg#%d function %s#%d\n", i, 6862 - func_name, func_id); 6863 - return -EINVAL; 6864 - } 6865 - } 6866 - 6867 - return 0; 6784 + return false; 6868 6785 } 6869 6786 6870 - /* Compare BTF of a function declaration with given bpf_reg_state. 6871 - * Returns: 6872 - * EFAULT - there is a verifier bug. Abort verification. 6873 - * EINVAL - there is a type mismatch or BTF is not available. 6874 - * 0 - BTF matches with what bpf_reg_state expects. 6875 - * Only PTR_TO_CTX and SCALAR_VALUE states are recognized. 6876 - */ 6877 - int btf_check_subprog_arg_match(struct bpf_verifier_env *env, int subprog, 6878 - struct bpf_reg_state *regs) 6879 - { 6880 - struct bpf_prog *prog = env->prog; 6881 - struct btf *btf = prog->aux->btf; 6882 - bool is_global; 6883 - u32 btf_id; 6884 - int err; 6885 - 6886 - if (!prog->aux->func_info) 6887 - return -EINVAL; 6888 - 6889 - btf_id = prog->aux->func_info[subprog].type_id; 6890 - if (!btf_id) 6891 - return -EFAULT; 6892 - 6893 - if (prog->aux->func_info_aux[subprog].unreliable) 6894 - return -EINVAL; 6895 - 6896 - is_global = prog->aux->func_info_aux[subprog].linkage == BTF_FUNC_GLOBAL; 6897 - err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, false); 6898 - 6899 - /* Compiler optimizations can remove arguments from static functions 6900 - * or mismatched type can be passed into a global function. 6901 - * In such cases mark the function as unreliable from BTF point of view. 6902 - */ 6903 - if (err) 6904 - prog->aux->func_info_aux[subprog].unreliable = true; 6905 - return err; 6906 - } 6907 - 6908 - /* Compare BTF of a function call with given bpf_reg_state. 6909 - * Returns: 6910 - * EFAULT - there is a verifier bug. Abort verification. 6911 - * EINVAL - there is a type mismatch or BTF is not available. 6912 - * 0 - BTF matches with what bpf_reg_state expects. 6913 - * Only PTR_TO_CTX and SCALAR_VALUE states are recognized. 6914 - * 6915 - * NOTE: the code is duplicated from btf_check_subprog_arg_match() 6916 - * because btf_check_func_arg_match() is still doing both. Once that 6917 - * function is split in 2, we can call from here btf_check_subprog_arg_match() 6918 - * first, and then treat the calling part in a new code path. 6919 - */ 6920 - int btf_check_subprog_call(struct bpf_verifier_env *env, int subprog, 6921 - struct bpf_reg_state *regs) 6922 - { 6923 - struct bpf_prog *prog = env->prog; 6924 - struct btf *btf = prog->aux->btf; 6925 - bool is_global; 6926 - u32 btf_id; 6927 - int err; 6928 - 6929 - if (!prog->aux->func_info) 6930 - return -EINVAL; 6931 - 6932 - btf_id = prog->aux->func_info[subprog].type_id; 6933 - if (!btf_id) 6934 - return -EFAULT; 6935 - 6936 - if (prog->aux->func_info_aux[subprog].unreliable) 6937 - return -EINVAL; 6938 - 6939 - is_global = prog->aux->func_info_aux[subprog].linkage == BTF_FUNC_GLOBAL; 6940 - err = btf_check_func_arg_match(env, btf, btf_id, regs, is_global, true); 6941 - 6942 - /* Compiler optimizations can remove arguments from static functions 6943 - * or mismatched type can be passed into a global function. 6944 - * In such cases mark the function as unreliable from BTF point of view. 6945 - */ 6946 - if (err) 6947 - prog->aux->func_info_aux[subprog].unreliable = true; 6948 - return err; 6949 - } 6950 - 6951 - /* Convert BTF of a function into bpf_reg_state if possible 6787 + /* Process BTF of a function to produce high-level expectation of function 6788 + * arguments (like ARG_PTR_TO_CTX, or ARG_PTR_TO_MEM, etc). This information 6789 + * is cached in subprog info for reuse. 6952 6790 * Returns: 6953 6791 * EFAULT - there is a verifier bug. Abort verification. 6954 6792 * EINVAL - cannot convert BTF. 6955 - * 0 - Successfully converted BTF into bpf_reg_state 6956 - * (either PTR_TO_CTX or SCALAR_VALUE). 6793 + * 0 - Successfully processed BTF and constructed argument expectations. 6957 6794 */ 6958 - int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog, 6959 - struct bpf_reg_state *regs, u32 *arg_cnt) 6795 + int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog) 6960 6796 { 6797 + bool is_global = subprog_aux(env, subprog)->linkage == BTF_FUNC_GLOBAL; 6798 + struct bpf_subprog_info *sub = subprog_info(env, subprog); 6961 6799 struct bpf_verifier_log *log = &env->log; 6962 6800 struct bpf_prog *prog = env->prog; 6963 6801 enum bpf_prog_type prog_type = prog->type; 6964 6802 struct btf *btf = prog->aux->btf; 6965 6803 const struct btf_param *args; 6966 - const struct btf_type *t, *ref_t; 6804 + const struct btf_type *t, *ref_t, *fn_t; 6967 6805 u32 i, nargs, btf_id; 6968 6806 const char *tname; 6969 6807 6970 - if (!prog->aux->func_info || 6971 - prog->aux->func_info_aux[subprog].linkage != BTF_FUNC_GLOBAL) { 6808 + if (sub->args_cached) 6809 + return 0; 6810 + 6811 + if (!prog->aux->func_info) { 6972 6812 bpf_log(log, "Verifier bug\n"); 6973 6813 return -EFAULT; 6974 6814 } 6975 6815 6976 6816 btf_id = prog->aux->func_info[subprog].type_id; 6977 6817 if (!btf_id) { 6818 + if (!is_global) /* not fatal for static funcs */ 6819 + return -EINVAL; 6978 6820 bpf_log(log, "Global functions need valid BTF\n"); 6979 6821 return -EFAULT; 6980 6822 } 6981 6823 6982 - t = btf_type_by_id(btf, btf_id); 6983 - if (!t || !btf_type_is_func(t)) { 6824 + fn_t = btf_type_by_id(btf, btf_id); 6825 + if (!fn_t || !btf_type_is_func(fn_t)) { 6984 6826 /* These checks were already done by the verifier while loading 6985 6827 * struct bpf_func_info 6986 6828 */ ··· 6830 6988 subprog); 6831 6989 return -EFAULT; 6832 6990 } 6833 - tname = btf_name_by_offset(btf, t->name_off); 6834 - 6835 - if (log->level & BPF_LOG_LEVEL) 6836 - bpf_log(log, "Validating %s() func#%d...\n", 6837 - tname, subprog); 6991 + tname = btf_name_by_offset(btf, fn_t->name_off); 6838 6992 6839 6993 if (prog->aux->func_info_aux[subprog].unreliable) { 6840 6994 bpf_log(log, "Verifier bug in function %s()\n", tname); ··· 6839 7001 if (prog_type == BPF_PROG_TYPE_EXT) 6840 7002 prog_type = prog->aux->dst_prog->type; 6841 7003 6842 - t = btf_type_by_id(btf, t->type); 7004 + t = btf_type_by_id(btf, fn_t->type); 6843 7005 if (!t || !btf_type_is_func_proto(t)) { 6844 7006 bpf_log(log, "Invalid type of function %s()\n", tname); 6845 7007 return -EFAULT; ··· 6851 7013 tname, nargs, MAX_BPF_FUNC_REG_ARGS); 6852 7014 return -EINVAL; 6853 7015 } 6854 - *arg_cnt = nargs; 6855 7016 /* check that function returns int, exception cb also requires this */ 6856 7017 t = btf_type_by_id(btf, t->type); 6857 7018 while (btf_type_is_modifier(t)) ··· 6865 7028 * Only PTR_TO_CTX and SCALAR are supported atm. 6866 7029 */ 6867 7030 for (i = 0; i < nargs; i++) { 6868 - struct bpf_reg_state *reg = &regs[i + 1]; 7031 + bool is_nonnull = false; 7032 + const char *tag; 6869 7033 6870 7034 t = btf_type_by_id(btf, args[i].type); 7035 + 7036 + tag = btf_find_decl_tag_value(btf, fn_t, i, "arg:"); 7037 + if (IS_ERR(tag) && PTR_ERR(tag) == -ENOENT) { 7038 + tag = NULL; 7039 + } else if (IS_ERR(tag)) { 7040 + bpf_log(log, "arg#%d type's tag fetching failure: %ld\n", i, PTR_ERR(tag)); 7041 + return PTR_ERR(tag); 7042 + } 7043 + /* 'arg:<tag>' decl_tag takes precedence over derivation of 7044 + * register type from BTF type itself 7045 + */ 7046 + if (tag) { 7047 + /* disallow arg tags in static subprogs */ 7048 + if (!is_global) { 7049 + bpf_log(log, "arg#%d type tag is not supported in static functions\n", i); 7050 + return -EOPNOTSUPP; 7051 + } 7052 + if (strcmp(tag, "ctx") == 0) { 7053 + sub->args[i].arg_type = ARG_PTR_TO_CTX; 7054 + continue; 7055 + } 7056 + if (strcmp(tag, "nonnull") == 0) 7057 + is_nonnull = true; 7058 + } 7059 + 6871 7060 while (btf_type_is_modifier(t)) 6872 7061 t = btf_type_by_id(btf, t->type); 6873 7062 if (btf_type_is_int(t) || btf_is_any_enum(t)) { 6874 - reg->type = SCALAR_VALUE; 7063 + sub->args[i].arg_type = ARG_ANYTHING; 6875 7064 continue; 6876 7065 } 6877 - if (btf_type_is_ptr(t)) { 6878 - if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { 6879 - reg->type = PTR_TO_CTX; 6880 - continue; 6881 - } 7066 + if (btf_type_is_ptr(t) && btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { 7067 + sub->args[i].arg_type = ARG_PTR_TO_CTX; 7068 + continue; 7069 + } 7070 + if (btf_type_is_ptr(t) && btf_is_dynptr_ptr(btf, t)) { 7071 + sub->args[i].arg_type = ARG_PTR_TO_DYNPTR | MEM_RDONLY; 7072 + continue; 7073 + } 7074 + if (is_global && btf_type_is_ptr(t)) { 7075 + u32 mem_size; 6882 7076 6883 7077 t = btf_type_skip_modifiers(btf, t->type, NULL); 6884 - 6885 - ref_t = btf_resolve_size(btf, t, &reg->mem_size); 7078 + ref_t = btf_resolve_size(btf, t, &mem_size); 6886 7079 if (IS_ERR(ref_t)) { 6887 7080 bpf_log(log, 6888 7081 "arg#%d reference type('%s %s') size cannot be determined: %ld\n", ··· 6921 7054 return -EINVAL; 6922 7055 } 6923 7056 6924 - reg->type = PTR_TO_MEM | PTR_MAYBE_NULL; 6925 - reg->id = ++env->id_gen; 6926 - 7057 + sub->args[i].arg_type = is_nonnull ? ARG_PTR_TO_MEM : ARG_PTR_TO_MEM_OR_NULL; 7058 + sub->args[i].mem_size = mem_size; 6927 7059 continue; 7060 + } 7061 + if (is_nonnull) { 7062 + bpf_log(log, "arg#%d marked as non-null, but is not a pointer type\n", i); 7063 + return -EINVAL; 6928 7064 } 6929 7065 bpf_log(log, "Arg#%d type %s in %s() is not supported yet.\n", 6930 7066 i, btf_type_str(t), tname); 6931 7067 return -EINVAL; 6932 7068 } 7069 + 7070 + sub->arg_cnt = nargs; 7071 + sub->args_cached = true; 7072 + 6933 7073 return 0; 6934 7074 } 6935 7075
+145 -41
kernel/bpf/verifier.c
··· 437 437 return btf_type_name(env->prog->aux->btf, info->type_id); 438 438 } 439 439 440 - static struct bpf_func_info_aux *subprog_aux(const struct bpf_verifier_env *env, int subprog) 441 - { 442 - return &env->prog->aux->func_info_aux[subprog]; 443 - } 444 - 445 - static struct bpf_subprog_info *subprog_info(struct bpf_verifier_env *env, int subprog) 446 - { 447 - return &env->subprog_info[subprog]; 448 - } 449 - 450 440 static void mark_subprog_exc_cb(struct bpf_verifier_env *env, int subprog) 451 441 { 452 442 struct bpf_subprog_info *info = subprog_info(env, subprog); ··· 5127 5137 return 0; 5128 5138 } 5129 5139 5130 - int check_ptr_off_reg(struct bpf_verifier_env *env, 5131 - const struct bpf_reg_state *reg, int regno) 5140 + static int check_ptr_off_reg(struct bpf_verifier_env *env, 5141 + const struct bpf_reg_state *reg, int regno) 5132 5142 { 5133 5143 return __check_ptr_off_reg(env, reg, regno, false); 5134 5144 } ··· 7300 7310 return err; 7301 7311 } 7302 7312 7303 - int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, 7304 - u32 regno, u32 mem_size) 7313 + static int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg, 7314 + u32 regno, u32 mem_size) 7305 7315 { 7306 7316 bool may_be_null = type_may_be_null(reg->type); 7307 7317 struct bpf_reg_state saved_reg; ··· 8286 8296 return field; 8287 8297 } 8288 8298 8289 - int check_func_arg_reg_off(struct bpf_verifier_env *env, 8290 - const struct bpf_reg_state *reg, int regno, 8291 - enum bpf_arg_type arg_type) 8299 + static int check_func_arg_reg_off(struct bpf_verifier_env *env, 8300 + const struct bpf_reg_state *reg, int regno, 8301 + enum bpf_arg_type arg_type) 8292 8302 { 8293 8303 u32 type = reg->type; 8294 8304 ··· 9246 9256 err_out: 9247 9257 free_func_state(callee); 9248 9258 state->frame[state->curframe + 1] = NULL; 9259 + return err; 9260 + } 9261 + 9262 + static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog, 9263 + const struct btf *btf, 9264 + struct bpf_reg_state *regs) 9265 + { 9266 + struct bpf_subprog_info *sub = subprog_info(env, subprog); 9267 + struct bpf_verifier_log *log = &env->log; 9268 + u32 i; 9269 + int ret; 9270 + 9271 + ret = btf_prepare_func_args(env, subprog); 9272 + if (ret) 9273 + return ret; 9274 + 9275 + /* check that BTF function arguments match actual types that the 9276 + * verifier sees. 9277 + */ 9278 + for (i = 0; i < sub->arg_cnt; i++) { 9279 + u32 regno = i + 1; 9280 + struct bpf_reg_state *reg = &regs[regno]; 9281 + struct bpf_subprog_arg_info *arg = &sub->args[i]; 9282 + 9283 + if (arg->arg_type == ARG_ANYTHING) { 9284 + if (reg->type != SCALAR_VALUE) { 9285 + bpf_log(log, "R%d is not a scalar\n", regno); 9286 + return -EINVAL; 9287 + } 9288 + } else if (arg->arg_type == ARG_PTR_TO_CTX) { 9289 + ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE); 9290 + if (ret < 0) 9291 + return ret; 9292 + /* If function expects ctx type in BTF check that caller 9293 + * is passing PTR_TO_CTX. 9294 + */ 9295 + if (reg->type != PTR_TO_CTX) { 9296 + bpf_log(log, "arg#%d expects pointer to ctx\n", i); 9297 + return -EINVAL; 9298 + } 9299 + } else if (base_type(arg->arg_type) == ARG_PTR_TO_MEM) { 9300 + ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE); 9301 + if (ret < 0) 9302 + return ret; 9303 + if (check_mem_reg(env, reg, regno, arg->mem_size)) 9304 + return -EINVAL; 9305 + if (!(arg->arg_type & PTR_MAYBE_NULL) && (reg->type & PTR_MAYBE_NULL)) { 9306 + bpf_log(log, "arg#%d is expected to be non-NULL\n", i); 9307 + return -EINVAL; 9308 + } 9309 + } else if (arg->arg_type == (ARG_PTR_TO_DYNPTR | MEM_RDONLY)) { 9310 + ret = process_dynptr_func(env, regno, -1, arg->arg_type, 0); 9311 + if (ret) 9312 + return ret; 9313 + } else { 9314 + bpf_log(log, "verifier bug: unrecognized arg#%d type %d\n", 9315 + i, arg->arg_type); 9316 + return -EFAULT; 9317 + } 9318 + } 9319 + 9320 + return 0; 9321 + } 9322 + 9323 + /* Compare BTF of a function call with given bpf_reg_state. 9324 + * Returns: 9325 + * EFAULT - there is a verifier bug. Abort verification. 9326 + * EINVAL - there is a type mismatch or BTF is not available. 9327 + * 0 - BTF matches with what bpf_reg_state expects. 9328 + * Only PTR_TO_CTX and SCALAR_VALUE states are recognized. 9329 + */ 9330 + static int btf_check_subprog_call(struct bpf_verifier_env *env, int subprog, 9331 + struct bpf_reg_state *regs) 9332 + { 9333 + struct bpf_prog *prog = env->prog; 9334 + struct btf *btf = prog->aux->btf; 9335 + u32 btf_id; 9336 + int err; 9337 + 9338 + if (!prog->aux->func_info) 9339 + return -EINVAL; 9340 + 9341 + btf_id = prog->aux->func_info[subprog].type_id; 9342 + if (!btf_id) 9343 + return -EFAULT; 9344 + 9345 + if (prog->aux->func_info_aux[subprog].unreliable) 9346 + return -EINVAL; 9347 + 9348 + err = btf_check_func_arg_match(env, subprog, btf, regs); 9349 + /* Compiler optimizations can remove arguments from static functions 9350 + * or mismatched type can be passed into a global function. 9351 + * In such cases mark the function as unreliable from BTF point of view. 9352 + */ 9353 + if (err) 9354 + prog->aux->func_info_aux[subprog].unreliable = true; 9249 9355 return err; 9250 9356 } 9251 9357 ··· 19995 19909 static int do_check_common(struct bpf_verifier_env *env, int subprog) 19996 19910 { 19997 19911 bool pop_log = !(env->log.level & BPF_LOG_LEVEL2); 19912 + struct bpf_subprog_info *sub = subprog_info(env, subprog); 19998 19913 struct bpf_verifier_state *state; 19999 19914 struct bpf_reg_state *regs; 20000 19915 int ret, i; ··· 20022 19935 state->first_insn_idx = env->subprog_info[subprog].start; 20023 19936 state->last_insn_idx = -1; 20024 19937 19938 + 20025 19939 regs = state->frame[state->curframe]->regs; 20026 19940 if (subprog || env->prog->type == BPF_PROG_TYPE_EXT) { 20027 - u32 nargs; 19941 + const char *sub_name = subprog_name(env, subprog); 19942 + struct bpf_subprog_arg_info *arg; 19943 + struct bpf_reg_state *reg; 20028 19944 20029 - ret = btf_prepare_func_args(env, subprog, regs, &nargs); 19945 + verbose(env, "Validating %s() func#%d...\n", sub_name, subprog); 19946 + ret = btf_prepare_func_args(env, subprog); 20030 19947 if (ret) 20031 19948 goto out; 19949 + 20032 19950 if (subprog_is_exc_cb(env, subprog)) { 20033 19951 state->frame[0]->in_exception_callback_fn = true; 20034 19952 /* We have already ensured that the callback returns an integer, just 20035 19953 * like all global subprogs. We need to determine it only has a single 20036 19954 * scalar argument. 20037 19955 */ 20038 - if (nargs != 1 || regs[BPF_REG_1].type != SCALAR_VALUE) { 19956 + if (sub->arg_cnt != 1 || sub->args[0].arg_type != ARG_ANYTHING) { 20039 19957 verbose(env, "exception cb only supports single integer argument\n"); 20040 19958 ret = -EINVAL; 20041 19959 goto out; 20042 19960 } 20043 19961 } 20044 - for (i = BPF_REG_1; i <= BPF_REG_5; i++) { 20045 - if (regs[i].type == PTR_TO_CTX) 20046 - mark_reg_known_zero(env, regs, i); 20047 - else if (regs[i].type == SCALAR_VALUE) 20048 - mark_reg_unknown(env, regs, i); 20049 - else if (base_type(regs[i].type) == PTR_TO_MEM) { 20050 - const u32 mem_size = regs[i].mem_size; 19962 + for (i = BPF_REG_1; i <= sub->arg_cnt; i++) { 19963 + arg = &sub->args[i - BPF_REG_1]; 19964 + reg = &regs[i]; 20051 19965 19966 + if (arg->arg_type == ARG_PTR_TO_CTX) { 19967 + reg->type = PTR_TO_CTX; 20052 19968 mark_reg_known_zero(env, regs, i); 20053 - regs[i].mem_size = mem_size; 20054 - regs[i].id = ++env->id_gen; 19969 + } else if (arg->arg_type == ARG_ANYTHING) { 19970 + reg->type = SCALAR_VALUE; 19971 + mark_reg_unknown(env, regs, i); 19972 + } else if (arg->arg_type == (ARG_PTR_TO_DYNPTR | MEM_RDONLY)) { 19973 + /* assume unspecial LOCAL dynptr type */ 19974 + __mark_dynptr_reg(reg, BPF_DYNPTR_TYPE_LOCAL, true, ++env->id_gen); 19975 + } else if (base_type(arg->arg_type) == ARG_PTR_TO_MEM) { 19976 + reg->type = PTR_TO_MEM; 19977 + if (arg->arg_type & PTR_MAYBE_NULL) 19978 + reg->type |= PTR_MAYBE_NULL; 19979 + mark_reg_known_zero(env, regs, i); 19980 + reg->mem_size = arg->mem_size; 19981 + reg->id = ++env->id_gen; 19982 + } else { 19983 + WARN_ONCE(1, "BUG: unhandled arg#%d type %d\n", 19984 + i - BPF_REG_1, arg->arg_type); 19985 + ret = -EFAULT; 19986 + goto out; 20055 19987 } 20056 19988 } 20057 19989 } else { 19990 + /* if main BPF program has associated BTF info, validate that 19991 + * it's matching expected signature, and otherwise mark BTF 19992 + * info for main program as unreliable 19993 + */ 19994 + if (env->prog->aux->func_info_aux) { 19995 + ret = btf_prepare_func_args(env, 0); 19996 + if (ret || sub->arg_cnt != 1 || sub->args[0].arg_type != ARG_PTR_TO_CTX) 19997 + env->prog->aux->func_info_aux[0].unreliable = true; 19998 + } 19999 + 20058 20000 /* 1st arg to a function */ 20059 20001 regs[BPF_REG_1].type = PTR_TO_CTX; 20060 20002 mark_reg_known_zero(env, regs, BPF_REG_1); 20061 - ret = btf_check_subprog_arg_match(env, subprog, regs); 20062 - if (ret == -EFAULT) 20063 - /* unlikely verifier bug. abort. 20064 - * ret == 0 and ret < 0 are sadly acceptable for 20065 - * main() function due to backward compatibility. 20066 - * Like socket filter program may be written as: 20067 - * int bpf_prog(struct pt_regs *ctx) 20068 - * and never dereference that ctx in the program. 20069 - * 'struct pt_regs' is a type mismatch for socket 20070 - * filter that should be using 'struct __sk_buff'. 20071 - */ 20072 - goto out; 20073 20003 } 20074 20004 20075 20005 ret = do_check(env);
+3
tools/lib/bpf/bpf_helpers.h
··· 188 188 !!sym; \ 189 189 }) 190 190 191 + #define __arg_ctx __attribute__((btf_decl_tag("arg:ctx"))) 192 + #define __arg_nonnull __attribute((btf_decl_tag("arg:nonnull"))) 193 + 191 194 #ifndef ___bpf_concat 192 195 #define ___bpf_concat(a, b) a ## b 193 196 #endif
+27 -3
tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
··· 348 348 } 349 349 350 350 static void test_obj_load_failure_common(const char *obj_file, 351 - const char *target_obj_file) 351 + const char *target_obj_file, 352 + const char *exp_msg) 352 353 { 353 354 /* 354 355 * standalone test that asserts failure to load freplace prog ··· 357 356 */ 358 357 struct bpf_object *obj = NULL, *pkt_obj; 359 358 struct bpf_program *prog; 359 + char log_buf[64 * 1024]; 360 360 int err, pkt_fd; 361 361 __u32 duration = 0; 362 362 ··· 376 374 err = bpf_program__set_attach_target(prog, pkt_fd, NULL); 377 375 ASSERT_OK(err, "set_attach_target"); 378 376 377 + log_buf[0] = '\0'; 378 + if (exp_msg) 379 + bpf_program__set_log_buf(prog, log_buf, sizeof(log_buf)); 380 + if (env.verbosity > VERBOSE_NONE) 381 + bpf_program__set_log_level(prog, 2); 382 + 379 383 /* It should fail to load the program */ 380 384 err = bpf_object__load(obj); 385 + if (env.verbosity > VERBOSE_NONE && exp_msg) /* we overtook log */ 386 + printf("VERIFIER LOG:\n================\n%s\n================\n", log_buf); 381 387 if (CHECK(!err, "bpf_obj_load should fail", "err %d\n", err)) 382 388 goto close_prog; 383 389 390 + if (exp_msg) 391 + ASSERT_HAS_SUBSTR(log_buf, exp_msg, "fail_msg"); 384 392 close_prog: 385 393 bpf_object__close(obj); 386 394 bpf_object__close(pkt_obj); ··· 400 388 { 401 389 /* test invalid return code in the replaced program */ 402 390 test_obj_load_failure_common("./freplace_connect_v4_prog.bpf.o", 403 - "./connect4_prog.bpf.o"); 391 + "./connect4_prog.bpf.o", NULL); 404 392 } 405 393 406 394 static void test_func_map_prog_compatibility(void) 407 395 { 408 396 /* test with spin lock map value in the replaced program */ 409 397 test_obj_load_failure_common("./freplace_attach_probe.bpf.o", 410 - "./test_attach_probe.bpf.o"); 398 + "./test_attach_probe.bpf.o", NULL); 399 + } 400 + 401 + static void test_func_replace_unreliable(void) 402 + { 403 + /* freplace'ing unreliable main prog should fail with error 404 + * "Cannot replace static functions" 405 + */ 406 + test_obj_load_failure_common("freplace_unreliable_prog.bpf.o", 407 + "./verifier_btf_unreliable_prog.bpf.o", 408 + "Cannot replace static functions"); 411 409 } 412 410 413 411 static void test_func_replace_global_func(void) ··· 585 563 test_func_replace_return_code(); 586 564 if (test__start_subtest("func_map_prog_compatibility")) 587 565 test_func_map_prog_compatibility(); 566 + if (test__start_subtest("func_replace_unreliable")) 567 + test_func_replace_unreliable(); 588 568 if (test__start_subtest("func_replace_multi")) 589 569 test_func_replace_multi(); 590 570 if (test__start_subtest("fmod_ret_freplace"))
+2 -2
tools/testing/selftests/bpf/prog_tests/log_fixup.c
··· 169 169 if (test__start_subtest("bad_core_relo_trunc_none")) 170 170 bad_core_relo(0, TRUNC_NONE /* full buf */); 171 171 if (test__start_subtest("bad_core_relo_trunc_partial")) 172 - bad_core_relo(300, TRUNC_PARTIAL /* truncate original log a bit */); 172 + bad_core_relo(280, TRUNC_PARTIAL /* truncate original log a bit */); 173 173 if (test__start_subtest("bad_core_relo_trunc_full")) 174 - bad_core_relo(210, TRUNC_FULL /* truncate also libbpf's message patch */); 174 + bad_core_relo(220, TRUNC_FULL /* truncate also libbpf's message patch */); 175 175 if (test__start_subtest("bad_core_relo_subprog")) 176 176 bad_core_relo_subprog(); 177 177 if (test__start_subtest("missing_map"))
+2
tools/testing/selftests/bpf/prog_tests/verifier.c
··· 14 14 #include "verifier_bpf_get_stack.skel.h" 15 15 #include "verifier_bswap.skel.h" 16 16 #include "verifier_btf_ctx_access.skel.h" 17 + #include "verifier_btf_unreliable_prog.skel.h" 17 18 #include "verifier_cfg.skel.h" 18 19 #include "verifier_cgroup_inv_retcode.skel.h" 19 20 #include "verifier_cgroup_skb.skel.h" ··· 126 125 void test_verifier_bpf_get_stack(void) { RUN(verifier_bpf_get_stack); } 127 126 void test_verifier_bswap(void) { RUN(verifier_bswap); } 128 127 void test_verifier_btf_ctx_access(void) { RUN(verifier_btf_ctx_access); } 128 + void test_verifier_btf_unreliable_prog(void) { RUN(verifier_btf_unreliable_prog); } 129 129 void test_verifier_cfg(void) { RUN(verifier_cfg); } 130 130 void test_verifier_cgroup_inv_retcode(void) { RUN(verifier_cgroup_inv_retcode); } 131 131 void test_verifier_cgroup_skb(void) { RUN(verifier_cgroup_skb); }
+1 -1
tools/testing/selftests/bpf/progs/cgrp_kfunc_failure.c
··· 78 78 } 79 79 80 80 SEC("kretprobe/cgroup_destroy_locked") 81 - __failure __msg("reg type unsupported for arg#0 function") 81 + __failure __msg("calling kernel function bpf_cgroup_acquire is not allowed") 82 82 int BPF_PROG(cgrp_kfunc_acquire_unsafe_kretprobe, struct cgroup *cgrp) 83 83 { 84 84 struct cgroup *acquired;
+20
tools/testing/selftests/bpf/progs/freplace_unreliable_prog.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2020 Facebook 3 + 4 + #include "vmlinux.h" 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + 8 + SEC("freplace/btf_unreliable_kprobe") 9 + /* context type is what BPF verifier expects for kprobe context, but target 10 + * program has `stuct whatever *ctx` argument, so freplace operation will be 11 + * rejected with the following message: 12 + * 13 + * arg0 replace_btf_unreliable_kprobe(struct pt_regs *) doesn't match btf_unreliable_kprobe(struct whatever *) 14 + */ 15 + int replace_btf_unreliable_kprobe(bpf_user_pt_regs_t *ctx) 16 + { 17 + return 0; 18 + } 19 + 20 + char _license[] SEC("license") = "GPL";
+1 -1
tools/testing/selftests/bpf/progs/task_kfunc_failure.c
··· 248 248 } 249 249 250 250 SEC("lsm/task_free") 251 - __failure __msg("reg type unsupported for arg#0 function") 251 + __failure __msg("R1 must be a rcu pointer") 252 252 int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task) 253 253 { 254 254 struct task_struct *acquired;
+1 -1
tools/testing/selftests/bpf/progs/test_global_func5.c
··· 26 26 } 27 27 28 28 SEC("tc") 29 - __failure __msg("expected pointer to ctx, but got PTR") 29 + __failure __msg("expects pointer to ctx") 30 30 int global_func5(struct __sk_buff *skb) 31 31 { 32 32 return f1(skb) + f2(2, skb) + f3(3, skb);
+20
tools/testing/selftests/bpf/progs/verifier_btf_unreliable_prog.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2017 Facebook 3 + 4 + #include "vmlinux.h" 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + #include <bpf/bpf_core_read.h> 8 + #include "bpf_misc.h" 9 + 10 + struct whatever {}; 11 + 12 + SEC("kprobe") 13 + __success __log_level(2) 14 + /* context type is wrong, making it impossible to freplace this program */ 15 + int btf_unreliable_kprobe(struct whatever *ctx) 16 + { 17 + return 0; 18 + } 19 + 20 + char _license[] SEC("license") = "GPL";
+95 -4
tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ 3 3 4 - #include <stdbool.h> 5 - #include <errno.h> 6 - #include <string.h> 7 - #include <linux/bpf.h> 4 + #include <vmlinux.h> 8 5 #include <bpf/bpf_helpers.h> 9 6 #include "bpf_misc.h" 7 + #include "xdp_metadata.h" 8 + #include "bpf_kfuncs.h" 10 9 11 10 int arr[1]; 12 11 int unkn_idx; ··· 95 96 int x = 0; 96 97 97 98 return global_unsupp(&x); 99 + } 100 + 101 + long stack[128]; 102 + 103 + __weak int subprog_nullable_ptr_bad(int *p) 104 + { 105 + return (*p) * 2; /* bad, missing null check */ 106 + } 107 + 108 + SEC("?raw_tp") 109 + __failure __log_level(2) 110 + __msg("invalid mem access 'mem_or_null'") 111 + int arg_tag_nullable_ptr_fail(void *ctx) 112 + { 113 + int x = 42; 114 + 115 + return subprog_nullable_ptr_bad(&x); 116 + } 117 + 118 + __noinline __weak int subprog_nonnull_ptr_good(int *p1 __arg_nonnull, int *p2 __arg_nonnull) 119 + { 120 + return (*p1) * (*p2); /* good, no need for NULL checks */ 121 + } 122 + 123 + int x = 47; 124 + 125 + SEC("?raw_tp") 126 + __success __log_level(2) 127 + int arg_tag_nonnull_ptr_good(void *ctx) 128 + { 129 + int y = 74; 130 + 131 + return subprog_nonnull_ptr_good(&x, &y); 132 + } 133 + 134 + /* this global subprog can be now called from many types of entry progs, each 135 + * with different context type 136 + */ 137 + __weak int subprog_ctx_tag(void *ctx __arg_ctx) 138 + { 139 + return bpf_get_stack(ctx, stack, sizeof(stack), 0); 140 + } 141 + 142 + SEC("?raw_tp") 143 + __success __log_level(2) 144 + int arg_tag_ctx_raw_tp(void *ctx) 145 + { 146 + return subprog_ctx_tag(ctx); 147 + } 148 + 149 + SEC("?tp") 150 + __success __log_level(2) 151 + int arg_tag_ctx_tp(void *ctx) 152 + { 153 + return subprog_ctx_tag(ctx); 154 + } 155 + 156 + SEC("?kprobe") 157 + __success __log_level(2) 158 + int arg_tag_ctx_kprobe(void *ctx) 159 + { 160 + return subprog_ctx_tag(ctx); 161 + } 162 + 163 + __weak int subprog_dynptr(struct bpf_dynptr *dptr) 164 + { 165 + long *d, t, buf[1] = {}; 166 + 167 + d = bpf_dynptr_data(dptr, 0, sizeof(long)); 168 + if (!d) 169 + return 0; 170 + 171 + t = *d + 1; 172 + 173 + d = bpf_dynptr_slice(dptr, 0, &buf, sizeof(long)); 174 + if (!d) 175 + return t; 176 + 177 + t = *d + 2; 178 + 179 + return t; 180 + } 181 + 182 + SEC("?xdp") 183 + __success __log_level(2) 184 + int arg_tag_dynptr(struct xdp_md *ctx) 185 + { 186 + struct bpf_dynptr dptr; 187 + 188 + bpf_dynptr_from_xdp(ctx, 0, &dptr); 189 + 190 + return subprog_dynptr(&dptr); 98 191 } 99 192 100 193 char _license[] SEC("license") = "GPL";