@@ -7802,6 +7802,84 @@ enum btf_arg_tag {
78027802 ARG_TAG_ARENA = BIT_ULL (5 ),
78037803};
78047804
7805+ static int btf_scan_decl_tags (struct bpf_verifier_env * env ,
7806+ const struct btf * btf ,
7807+ const struct btf_type * fn_t ,
7808+ u32 arg_idx , bool is_global , u32 * tags )
7809+ {
7810+ int id = btf_named_start_id (btf , false) - 1 ;
7811+
7812+ /*
7813+ * The 'arg:<tag>' decl_tag takes precedence over the derivation
7814+ * of the register type from the BTF type itself.
7815+ */
7816+ while ((id = btf_find_next_decl_tag (btf , fn_t , arg_idx , "arg:" , id )) > 0 ) {
7817+ const struct btf_type * tag_t = btf_type_by_id (btf , id );
7818+ const char * tag = __btf_name_by_offset (btf , tag_t -> name_off ) + 4 ;
7819+
7820+ /* disallow arg tags in static subprogs */
7821+ if (!is_global ) {
7822+ bpf_log (& env -> log ,
7823+ "arg#%d type tag is not supported in static functions\n" ,
7824+ arg_idx );
7825+ return - EOPNOTSUPP ;
7826+ }
7827+
7828+ if (strcmp (tag , "ctx" ) == 0 ) {
7829+ * tags |= ARG_TAG_CTX ;
7830+ } else if (strcmp (tag , "trusted" ) == 0 ) {
7831+ * tags |= ARG_TAG_TRUSTED ;
7832+ } else if (strcmp (tag , "untrusted" ) == 0 ) {
7833+ * tags |= ARG_TAG_UNTRUSTED ;
7834+ } else if (strcmp (tag , "nonnull" ) == 0 ) {
7835+ * tags |= ARG_TAG_NONNULL ;
7836+ } else if (strcmp (tag , "nullable" ) == 0 ) {
7837+ * tags |= ARG_TAG_NULLABLE ;
7838+ } else if (strcmp (tag , "arena" ) == 0 ) {
7839+ * tags |= ARG_TAG_ARENA ;
7840+ } else {
7841+ bpf_log (& env -> log , "arg#%d has unsupported set of tags\n" , arg_idx );
7842+ return - EOPNOTSUPP ;
7843+ }
7844+ }
7845+ if (id != - ENOENT ) {
7846+ bpf_log (& env -> log , "arg#%d type tag fetching failure: %d\n" , arg_idx , id );
7847+ return id ;
7848+ }
7849+
7850+ return 0 ;
7851+ }
7852+
7853+ static int btf_scan_type_tags (struct bpf_verifier_env * env ,
7854+ const struct btf * btf , u32 type_id ,
7855+ u32 * tags )
7856+ {
7857+ const struct btf_type * t ;
7858+
7859+ /* Find the first pointer type in the chain. */
7860+ t = btf_type_skip_modifiers (btf , type_id , NULL );
7861+ if (!t || !btf_type_is_ptr (t ))
7862+ return 0 ;
7863+
7864+ /* We got a pointer, get all associated type tags. */
7865+ t = btf_type_by_id (btf , t -> type );
7866+ while (t && btf_type_is_type_tag (t )) {
7867+ const char * tag = __btf_name_by_offset (btf , t -> name_off );
7868+
7869+ if (strcmp (tag , "arena" ) == 0 ) {
7870+ * tags |= ARG_TAG_ARENA ;
7871+ } else {
7872+ bpf_log (& env -> log , "function signature member has unsupported type tag '%s'\n" ,
7873+ tag );
7874+ return - EOPNOTSUPP ;
7875+ }
7876+
7877+ t = btf_type_by_id (btf , t -> type );
7878+ }
7879+
7880+ return 0 ;
7881+ }
7882+
78057883/* Process BTF of a function to produce high-level expectation of function
78067884 * arguments (like ARG_PTR_TO_CTX, or ARG_PTR_TO_MEM, etc). This information
78077885 * is cached in subprog info for reuse.
@@ -7820,6 +7898,7 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
78207898 struct btf * btf = prog -> aux -> btf ;
78217899 const struct btf_param * args ;
78227900 const struct btf_type * t , * ref_t , * fn_t ;
7901+ int err ;
78237902 u32 i , nargs , btf_id ;
78247903 const char * tname ;
78257904
@@ -7903,42 +7982,13 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
79037982 */
79047983 for (i = 0 ; i < nargs ; i ++ ) {
79057984 u32 tags = 0 ;
7906- int id = btf_named_start_id (btf , false) - 1 ;
7907-
7908- /* 'arg:<tag>' decl_tag takes precedence over derivation of
7909- * register type from BTF type itself
7910- */
7911- while ((id = btf_find_next_decl_tag (btf , fn_t , i , "arg:" , id )) > 0 ) {
7912- const struct btf_type * tag_t = btf_type_by_id (btf , id );
7913- const char * tag = __btf_name_by_offset (btf , tag_t -> name_off ) + 4 ;
7914-
7915- /* disallow arg tags in static subprogs */
7916- if (!is_global ) {
7917- bpf_log (log , "arg#%d type tag is not supported in static functions\n" , i );
7918- return - EOPNOTSUPP ;
7919- }
7985+ err = btf_scan_decl_tags (env , btf , fn_t , i , is_global , & tags );
7986+ if (err )
7987+ return err ;
79207988
7921- if (strcmp (tag , "ctx" ) == 0 ) {
7922- tags |= ARG_TAG_CTX ;
7923- } else if (strcmp (tag , "trusted" ) == 0 ) {
7924- tags |= ARG_TAG_TRUSTED ;
7925- } else if (strcmp (tag , "untrusted" ) == 0 ) {
7926- tags |= ARG_TAG_UNTRUSTED ;
7927- } else if (strcmp (tag , "nonnull" ) == 0 ) {
7928- tags |= ARG_TAG_NONNULL ;
7929- } else if (strcmp (tag , "nullable" ) == 0 ) {
7930- tags |= ARG_TAG_NULLABLE ;
7931- } else if (strcmp (tag , "arena" ) == 0 ) {
7932- tags |= ARG_TAG_ARENA ;
7933- } else {
7934- bpf_log (log , "arg#%d has unsupported set of tags\n" , i );
7935- return - EOPNOTSUPP ;
7936- }
7937- }
7938- if (id != - ENOENT ) {
7939- bpf_log (log , "arg#%d type tag fetching failure: %d\n" , i , id );
7940- return id ;
7941- }
7989+ err = btf_scan_type_tags (env , btf , args [i ].type , & tags );
7990+ if (err )
7991+ return err ;
79427992
79437993 t = btf_type_by_id (btf , args [i ].type );
79447994 while (btf_type_is_modifier (t ))
0 commit comments