@@ -5339,7 +5339,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
struct bpf_verifier_log *log = info->log;
const struct btf_param *args;
const char *tag_value;
- u32 nr_args, arg;
+ u32 nr_args, arg, curr_tid = 0;
int i, ret;
if (off % 8) {
@@ -5385,6 +5385,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
*/
if (!t)
return true;
+ curr_tid = t->type;
t = btf_type_by_id(btf, t->type);
break;
case BPF_MODIFY_RETURN:
@@ -5394,7 +5395,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
if (!t)
return false;
- t = btf_type_skip_modifiers(btf, t->type, NULL);
+ t = btf_type_skip_modifiers(btf, t->type, &curr_tid);
if (!btf_type_is_small_int(t)) {
bpf_log(log,
"ret type %s not allowed for fmod_ret\n",
@@ -5411,15 +5412,25 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
if (!t)
/* Default prog with MAX_BPF_FUNC_REG_ARGS args */
return true;
+ curr_tid = args[arg].type;
t = btf_type_by_id(btf, args[arg].type);
}
/* skip modifiers */
- while (btf_type_is_modifier(t))
+ while (btf_type_is_modifier(t)) {
+ curr_tid = t->type;
t = btf_type_by_id(btf, t->type);
+ }
if (btf_type_is_small_int(t) || btf_is_any_enum(t))
/* accessing a scalar */
return true;
+ if (__btf_type_is_struct(t) && curr_tid) {
+ info->reg_type = PTR_TO_BTF_ID;
+ info->btf = btf;
+ info->btf_id = curr_tid;
+ return true;
+ }
+
if (!btf_type_is_ptr(t)) {
bpf_log(log,
"func '%s' arg%d '%s' has type %s. Only pointer access is allowed\n",
@@ -5878,7 +5889,7 @@ static int __get_type_size(struct btf *btf, u32 btf_id,
if (!t)
return -EINVAL;
*ret_type = t;
- if (btf_type_is_ptr(t))
+ if (btf_type_is_ptr(t) || __btf_type_is_struct(t))
/* kernel size of pointer. Not BPF's size of pointer*/
return sizeof(void *);
if (btf_type_is_int(t) || btf_is_any_enum(t))
@@ -5901,8 +5912,10 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
/* BTF function prototype doesn't match the verifier types.
* Fall back to MAX_BPF_FUNC_REG_ARGS u64 args.
*/
- for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++)
+ for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
m->arg_size[i] = 8;
+ m->arg_flags[i] = 0;
+ }
m->ret_size = 8;
m->nr_args = MAX_BPF_FUNC_REG_ARGS;
return 0;
@@ -5944,7 +5957,12 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
tname);
return -EINVAL;
}
- m->arg_size[i] = ret;
+ if (__btf_type_is_struct(t)) {
+ m->arg_flags[i] = BTF_FMODEL_STRUCT_ARG;
+ m->arg_size[i] = t->size;
+ } else {
+ m->arg_size[i] = ret;
+ }
}
m->nr_args = nargs;
return 0;
Add struct argument support in btf_ctx_access() and btf_distill_func_proto(). The arch-specific code will handle whether and how such struct arguments are supported. Signed-off-by: Yonghong Song <yhs@fb.com> --- kernel/bpf/btf.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-)