@@ -5615,21 +5615,46 @@ static u8 bpf_ctx_convert_map[] = {
56155615#undef BPF_MAP_TYPE
56165616#undef BPF_LINK_TYPE
56175617
5618- const struct btf_member *
5619- btf_get_prog_ctx_type (struct bpf_verifier_log * log , const struct btf * btf ,
5620- const struct btf_type * t , enum bpf_prog_type prog_type ,
5621- int arg )
5618+ static const struct btf_type * find_canonical_prog_ctx_type (enum bpf_prog_type prog_type )
56225619{
56235620 const struct btf_type * conv_struct ;
5624- const struct btf_type * ctx_struct ;
56255621 const struct btf_member * ctx_type ;
5626- const char * tname , * ctx_tname ;
56275622
56285623 conv_struct = bpf_ctx_convert .t ;
5629- if (!conv_struct ) {
5630- bpf_log (log , "btf_vmlinux is malformed\n" );
5624+ if (!conv_struct )
56315625 return NULL ;
5632- }
5626+ /* prog_type is valid bpf program type. No need for bounds check. */
5627+ ctx_type = btf_type_member (conv_struct ) + bpf_ctx_convert_map [prog_type ] * 2 ;
5628+ /* ctx_type is a pointer to prog_ctx_type in vmlinux.
5629+ * Like 'struct __sk_buff'
5630+ */
5631+ return btf_type_by_id (btf_vmlinux , ctx_type -> type );
5632+ }
5633+
5634+ static int find_kern_ctx_type_id (enum bpf_prog_type prog_type )
5635+ {
5636+ const struct btf_type * conv_struct ;
5637+ const struct btf_member * ctx_type ;
5638+
5639+ conv_struct = bpf_ctx_convert .t ;
5640+ if (!conv_struct )
5641+ return - EFAULT ;
5642+ /* prog_type is valid bpf program type. No need for bounds check. */
5643+ ctx_type = btf_type_member (conv_struct ) + bpf_ctx_convert_map [prog_type ] * 2 + 1 ;
5644+ /* ctx_type is a pointer to prog_ctx_type in vmlinux.
5645+ * Like 'struct sk_buff'
5646+ */
5647+ return ctx_type -> type ;
5648+ }
5649+
5650+ const struct btf_type *
5651+ btf_get_prog_ctx_type (struct bpf_verifier_log * log , const struct btf * btf ,
5652+ const struct btf_type * t , enum bpf_prog_type prog_type ,
5653+ int arg )
5654+ {
5655+ const struct btf_type * ctx_type ;
5656+ const char * tname , * ctx_tname ;
5657+
56335658 t = btf_type_by_id (btf , t -> type );
56345659 while (btf_type_is_modifier (t ))
56355660 t = btf_type_by_id (btf , t -> type );
@@ -5646,17 +5671,15 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
56465671 bpf_log (log , "arg#%d struct doesn't have a name\n" , arg );
56475672 return NULL ;
56485673 }
5649- /* prog_type is valid bpf program type. No need for bounds check. */
5650- ctx_type = btf_type_member (conv_struct ) + bpf_ctx_convert_map [prog_type ] * 2 ;
5651- /* ctx_struct is a pointer to prog_ctx_type in vmlinux.
5652- * Like 'struct __sk_buff'
5653- */
5654- ctx_struct = btf_type_by_id (btf_vmlinux , ctx_type -> type );
5655- if (!ctx_struct )
5674+
5675+ ctx_type = find_canonical_prog_ctx_type (prog_type );
5676+ if (!ctx_type ) {
5677+ bpf_log (log , "btf_vmlinux is malformed\n" );
56565678 /* should not happen */
56575679 return NULL ;
5680+ }
56585681again :
5659- ctx_tname = btf_name_by_offset (btf_vmlinux , ctx_struct -> name_off );
5682+ ctx_tname = btf_name_by_offset (btf_vmlinux , ctx_type -> name_off );
56605683 if (!ctx_tname ) {
56615684 /* should not happen */
56625685 bpf_log (log , "Please fix kernel include/linux/bpf_types.h\n" );
@@ -5677,28 +5700,167 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
56775700 /* bpf_user_pt_regs_t is a typedef, so resolve it to
56785701 * underlying struct and check name again
56795702 */
5680- if (!btf_type_is_modifier (ctx_struct ))
5703+ if (!btf_type_is_modifier (ctx_type ))
56815704 return NULL ;
5682- while (btf_type_is_modifier (ctx_struct ))
5683- ctx_struct = btf_type_by_id (btf_vmlinux , ctx_struct -> type );
5705+ while (btf_type_is_modifier (ctx_type ))
5706+ ctx_type = btf_type_by_id (btf_vmlinux , ctx_type -> type );
56845707 goto again ;
56855708 }
56865709 return ctx_type ;
56875710}
56885711
5712+ /* forward declarations for arch-specific underlying types of
5713+ * bpf_user_pt_regs_t; this avoids the need for arch-specific #ifdef
5714+ * compilation guards below for BPF_PROG_TYPE_PERF_EVENT checks, but still
5715+ * works correctly with __builtin_types_compatible_p() on respective
5716+ * architectures
5717+ */
5718+ struct user_regs_struct ;
5719+ struct user_pt_regs ;
5720+
5721+ static int btf_validate_prog_ctx_type (struct bpf_verifier_log * log , const struct btf * btf ,
5722+ const struct btf_type * t , int arg ,
5723+ enum bpf_prog_type prog_type ,
5724+ enum bpf_attach_type attach_type )
5725+ {
5726+ const struct btf_type * ctx_type ;
5727+ const char * tname , * ctx_tname ;
5728+
5729+ if (!btf_is_ptr (t )) {
5730+ bpf_log (log , "arg#%d type isn't a pointer\n" , arg );
5731+ return - EINVAL ;
5732+ }
5733+ t = btf_type_by_id (btf , t -> type );
5734+
5735+ /* KPROBE and PERF_EVENT programs allow bpf_user_pt_regs_t typedef */
5736+ if (prog_type == BPF_PROG_TYPE_KPROBE || prog_type == BPF_PROG_TYPE_PERF_EVENT ) {
5737+ while (btf_type_is_modifier (t ) && !btf_type_is_typedef (t ))
5738+ t = btf_type_by_id (btf , t -> type );
5739+
5740+ if (btf_type_is_typedef (t )) {
5741+ tname = btf_name_by_offset (btf , t -> name_off );
5742+ if (tname && strcmp (tname , "bpf_user_pt_regs_t" ) == 0 )
5743+ return 0 ;
5744+ }
5745+ }
5746+
5747+ /* all other program types don't use typedefs for context type */
5748+ while (btf_type_is_modifier (t ))
5749+ t = btf_type_by_id (btf , t -> type );
5750+
5751+ /* `void *ctx __arg_ctx` is always valid */
5752+ if (btf_type_is_void (t ))
5753+ return 0 ;
5754+
5755+ tname = btf_name_by_offset (btf , t -> name_off );
5756+ if (str_is_empty (tname )) {
5757+ bpf_log (log , "arg#%d type doesn't have a name\n" , arg );
5758+ return - EINVAL ;
5759+ }
5760+
5761+ /* special cases */
5762+ switch (prog_type ) {
5763+ case BPF_PROG_TYPE_KPROBE :
5764+ if (__btf_type_is_struct (t ) && strcmp (tname , "pt_regs" ) == 0 )
5765+ return 0 ;
5766+ break ;
5767+ case BPF_PROG_TYPE_PERF_EVENT :
5768+ if (__builtin_types_compatible_p (bpf_user_pt_regs_t , struct pt_regs ) &&
5769+ __btf_type_is_struct (t ) && strcmp (tname , "pt_regs" ) == 0 )
5770+ return 0 ;
5771+ if (__builtin_types_compatible_p (bpf_user_pt_regs_t , struct user_pt_regs ) &&
5772+ __btf_type_is_struct (t ) && strcmp (tname , "user_pt_regs" ) == 0 )
5773+ return 0 ;
5774+ if (__builtin_types_compatible_p (bpf_user_pt_regs_t , struct user_regs_struct ) &&
5775+ __btf_type_is_struct (t ) && strcmp (tname , "user_regs_struct" ) == 0 )
5776+ return 0 ;
5777+ break ;
5778+ case BPF_PROG_TYPE_RAW_TRACEPOINT :
5779+ case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE :
5780+ /* allow u64* as ctx */
5781+ if (btf_is_int (t ) && t -> size == 8 )
5782+ return 0 ;
5783+ break ;
5784+ case BPF_PROG_TYPE_TRACING :
5785+ switch (attach_type ) {
5786+ case BPF_TRACE_RAW_TP :
5787+ /* tp_btf program is TRACING, so need special case here */
5788+ if (__btf_type_is_struct (t ) &&
5789+ strcmp (tname , "bpf_raw_tracepoint_args" ) == 0 )
5790+ return 0 ;
5791+ /* allow u64* as ctx */
5792+ if (btf_is_int (t ) && t -> size == 8 )
5793+ return 0 ;
5794+ break ;
5795+ case BPF_TRACE_ITER :
5796+ /* allow struct bpf_iter__xxx types only */
5797+ if (__btf_type_is_struct (t ) &&
5798+ strncmp (tname , "bpf_iter__" , sizeof ("bpf_iter__" ) - 1 ) == 0 )
5799+ return 0 ;
5800+ break ;
5801+ case BPF_TRACE_FENTRY :
5802+ case BPF_TRACE_FEXIT :
5803+ case BPF_MODIFY_RETURN :
5804+ /* allow u64* as ctx */
5805+ if (btf_is_int (t ) && t -> size == 8 )
5806+ return 0 ;
5807+ break ;
5808+ default :
5809+ break ;
5810+ }
5811+ break ;
5812+ case BPF_PROG_TYPE_LSM :
5813+ case BPF_PROG_TYPE_STRUCT_OPS :
5814+ /* allow u64* as ctx */
5815+ if (btf_is_int (t ) && t -> size == 8 )
5816+ return 0 ;
5817+ break ;
5818+ case BPF_PROG_TYPE_TRACEPOINT :
5819+ case BPF_PROG_TYPE_SYSCALL :
5820+ case BPF_PROG_TYPE_EXT :
5821+ return 0 ; /* anything goes */
5822+ default :
5823+ break ;
5824+ }
5825+
5826+ ctx_type = find_canonical_prog_ctx_type (prog_type );
5827+ if (!ctx_type ) {
5828+ /* should not happen */
5829+ bpf_log (log , "btf_vmlinux is malformed\n" );
5830+ return - EINVAL ;
5831+ }
5832+
5833+ /* resolve typedefs and check that underlying structs are matching as well */
5834+ while (btf_type_is_modifier (ctx_type ))
5835+ ctx_type = btf_type_by_id (btf_vmlinux , ctx_type -> type );
5836+
5837+ /* if program type doesn't have distinctly named struct type for
5838+ * context, then __arg_ctx argument can only be `void *`, which we
5839+ * already checked above
5840+ */
5841+ if (!__btf_type_is_struct (ctx_type )) {
5842+ bpf_log (log , "arg#%d should be void pointer\n" , arg );
5843+ return - EINVAL ;
5844+ }
5845+
5846+ ctx_tname = btf_name_by_offset (btf_vmlinux , ctx_type -> name_off );
5847+ if (!__btf_type_is_struct (t ) || strcmp (ctx_tname , tname ) != 0 ) {
5848+ bpf_log (log , "arg#%d should be `struct %s *`\n" , arg , ctx_tname );
5849+ return - EINVAL ;
5850+ }
5851+
5852+ return 0 ;
5853+ }
5854+
56895855static int btf_translate_to_vmlinux (struct bpf_verifier_log * log ,
56905856 struct btf * btf ,
56915857 const struct btf_type * t ,
56925858 enum bpf_prog_type prog_type ,
56935859 int arg )
56945860{
5695- const struct btf_member * prog_ctx_type , * kern_ctx_type ;
5696-
5697- prog_ctx_type = btf_get_prog_ctx_type (log , btf , t , prog_type , arg );
5698- if (!prog_ctx_type )
5861+ if (!btf_get_prog_ctx_type (log , btf , t , prog_type , arg ))
56995862 return - ENOENT ;
5700- kern_ctx_type = prog_ctx_type + 1 ;
5701- return kern_ctx_type -> type ;
5863+ return find_kern_ctx_type_id (prog_type );
57025864}
57035865
57045866int get_kern_ctx_btf_id (struct bpf_verifier_log * log , enum bpf_prog_type prog_type )
@@ -6934,6 +7096,23 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
69347096 return - EINVAL ;
69357097 }
69367098
7099+ for (i = 0 ; i < nargs ; i ++ ) {
7100+ const char * tag ;
7101+
7102+ if (sub -> args [i ].arg_type != ARG_PTR_TO_CTX )
7103+ continue ;
7104+
7105+ /* check if arg has "arg:ctx" tag */
7106+ t = btf_type_by_id (btf , args [i ].type );
7107+ tag = btf_find_decl_tag_value (btf , fn_t , i , "arg:" );
7108+ if (IS_ERR_OR_NULL (tag ) || strcmp (tag , "ctx" ) != 0 )
7109+ continue ;
7110+
7111+ if (btf_validate_prog_ctx_type (log , btf , t , i , prog_type ,
7112+ prog -> expected_attach_type ))
7113+ return - EINVAL ;
7114+ }
7115+
69377116 sub -> arg_cnt = nargs ;
69387117 sub -> args_cached = true;
69397118
0 commit comments