Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Alexei Starovoitov says: ==================== pull-request: bpf-next 2021-03-09 The following pull-request contains BPF updates for your *net-next* tree. We've added 90 non-merge commits during the last 17 day(s) which contain a total of 114 files changed, 5158 insertions(+), 1288 deletions(-). The main changes are: 1) Faster bpf_redirect_map(), from Björn. 2) skmsg cleanup, from Cong. 3) Support for floating point types in BTF, from Ilya. 4) Documentation for sys_bpf commands, from Joe. 5) Support for sk_lookup in bpf_prog_test_run, form Lorenz. 6) Enable task local storage for tracing programs, from Song. 7) bpf_for_each_map_elem() helper, from Yonghong. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
108
kernel/bpf/btf.c
108
kernel/bpf/btf.c
@@ -173,7 +173,7 @@
|
||||
#define BITS_ROUNDUP_BYTES(bits) \
|
||||
(BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits))
|
||||
|
||||
#define BTF_INFO_MASK 0x8f00ffff
|
||||
#define BTF_INFO_MASK 0x9f00ffff
|
||||
#define BTF_INT_MASK 0x0fffffff
|
||||
#define BTF_TYPE_ID_VALID(type_id) ((type_id) <= BTF_MAX_TYPE)
|
||||
#define BTF_STR_OFFSET_VALID(name_off) ((name_off) <= BTF_MAX_NAME_OFFSET)
|
||||
@@ -280,6 +280,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
|
||||
[BTF_KIND_FUNC_PROTO] = "FUNC_PROTO",
|
||||
[BTF_KIND_VAR] = "VAR",
|
||||
[BTF_KIND_DATASEC] = "DATASEC",
|
||||
[BTF_KIND_FLOAT] = "FLOAT",
|
||||
};
|
||||
|
||||
static const char *btf_type_str(const struct btf_type *t)
|
||||
@@ -574,6 +575,7 @@ static bool btf_type_has_size(const struct btf_type *t)
|
||||
case BTF_KIND_UNION:
|
||||
case BTF_KIND_ENUM:
|
||||
case BTF_KIND_DATASEC:
|
||||
case BTF_KIND_FLOAT:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1704,6 +1706,7 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type,
|
||||
case BTF_KIND_STRUCT:
|
||||
case BTF_KIND_UNION:
|
||||
case BTF_KIND_ENUM:
|
||||
case BTF_KIND_FLOAT:
|
||||
size = type->size;
|
||||
goto resolved;
|
||||
|
||||
@@ -1849,7 +1852,7 @@ static int btf_df_check_kflag_member(struct btf_verifier_env *env,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Used for ptr, array and struct/union type members.
|
||||
/* Used for ptr, array struct/union and float type members.
|
||||
* int, enum and modifier types have their specific callback functions.
|
||||
*/
|
||||
static int btf_generic_check_kflag_member(struct btf_verifier_env *env,
|
||||
@@ -3675,6 +3678,81 @@ static const struct btf_kind_operations datasec_ops = {
|
||||
.show = btf_datasec_show,
|
||||
};
|
||||
|
||||
static s32 btf_float_check_meta(struct btf_verifier_env *env,
|
||||
const struct btf_type *t,
|
||||
u32 meta_left)
|
||||
{
|
||||
if (btf_type_vlen(t)) {
|
||||
btf_verifier_log_type(env, t, "vlen != 0");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (btf_type_kflag(t)) {
|
||||
btf_verifier_log_type(env, t, "Invalid btf_info kind_flag");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (t->size != 2 && t->size != 4 && t->size != 8 && t->size != 12 &&
|
||||
t->size != 16) {
|
||||
btf_verifier_log_type(env, t, "Invalid type_size");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
btf_verifier_log_type(env, t, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btf_float_check_member(struct btf_verifier_env *env,
|
||||
const struct btf_type *struct_type,
|
||||
const struct btf_member *member,
|
||||
const struct btf_type *member_type)
|
||||
{
|
||||
u64 start_offset_bytes;
|
||||
u64 end_offset_bytes;
|
||||
u64 misalign_bits;
|
||||
u64 align_bytes;
|
||||
u64 align_bits;
|
||||
|
||||
/* Different architectures have different alignment requirements, so
|
||||
* here we check only for the reasonable minimum. This way we ensure
|
||||
* that types after CO-RE can pass the kernel BTF verifier.
|
||||
*/
|
||||
align_bytes = min_t(u64, sizeof(void *), member_type->size);
|
||||
align_bits = align_bytes * BITS_PER_BYTE;
|
||||
div64_u64_rem(member->offset, align_bits, &misalign_bits);
|
||||
if (misalign_bits) {
|
||||
btf_verifier_log_member(env, struct_type, member,
|
||||
"Member is not properly aligned");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
start_offset_bytes = member->offset / BITS_PER_BYTE;
|
||||
end_offset_bytes = start_offset_bytes + member_type->size;
|
||||
if (end_offset_bytes > struct_type->size) {
|
||||
btf_verifier_log_member(env, struct_type, member,
|
||||
"Member exceeds struct_size");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btf_float_log(struct btf_verifier_env *env,
|
||||
const struct btf_type *t)
|
||||
{
|
||||
btf_verifier_log(env, "size=%u", t->size);
|
||||
}
|
||||
|
||||
static const struct btf_kind_operations float_ops = {
|
||||
.check_meta = btf_float_check_meta,
|
||||
.resolve = btf_df_resolve,
|
||||
.check_member = btf_float_check_member,
|
||||
.check_kflag_member = btf_generic_check_kflag_member,
|
||||
.log_details = btf_float_log,
|
||||
.show = btf_df_show,
|
||||
};
|
||||
|
||||
static int btf_func_proto_check(struct btf_verifier_env *env,
|
||||
const struct btf_type *t)
|
||||
{
|
||||
@@ -3808,6 +3886,7 @@ static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS] = {
|
||||
[BTF_KIND_FUNC_PROTO] = &func_proto_ops,
|
||||
[BTF_KIND_VAR] = &var_ops,
|
||||
[BTF_KIND_DATASEC] = &datasec_ops,
|
||||
[BTF_KIND_FLOAT] = &float_ops,
|
||||
};
|
||||
|
||||
static s32 btf_check_meta(struct btf_verifier_env *env,
|
||||
@@ -4592,8 +4671,10 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
|
||||
}
|
||||
arg = off / 8;
|
||||
args = (const struct btf_param *)(t + 1);
|
||||
/* if (t == NULL) Fall back to default BPF prog with 5 u64 arguments */
|
||||
nr_args = t ? btf_type_vlen(t) : 5;
|
||||
/* if (t == NULL) Fall back to default BPF prog with
|
||||
* MAX_BPF_FUNC_REG_ARGS u64 arguments.
|
||||
*/
|
||||
nr_args = t ? btf_type_vlen(t) : MAX_BPF_FUNC_REG_ARGS;
|
||||
if (prog->aux->attach_btf_trace) {
|
||||
/* skip first 'void *__data' argument in btf_trace_##name typedef */
|
||||
args++;
|
||||
@@ -4649,7 +4730,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
|
||||
}
|
||||
} else {
|
||||
if (!t)
|
||||
/* Default prog with 5 args */
|
||||
/* Default prog with MAX_BPF_FUNC_REG_ARGS args */
|
||||
return true;
|
||||
t = btf_type_by_id(btf, args[arg].type);
|
||||
}
|
||||
@@ -5100,12 +5181,12 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
|
||||
|
||||
if (!func) {
|
||||
/* BTF function prototype doesn't match the verifier types.
|
||||
* Fall back to 5 u64 args.
|
||||
* Fall back to MAX_BPF_FUNC_REG_ARGS u64 args.
|
||||
*/
|
||||
for (i = 0; i < 5; i++)
|
||||
for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++)
|
||||
m->arg_size[i] = 8;
|
||||
m->ret_size = 8;
|
||||
m->nr_args = 5;
|
||||
m->nr_args = MAX_BPF_FUNC_REG_ARGS;
|
||||
return 0;
|
||||
}
|
||||
args = (const struct btf_param *)(func + 1);
|
||||
@@ -5328,8 +5409,9 @@ int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
|
||||
}
|
||||
args = (const struct btf_param *)(t + 1);
|
||||
nargs = btf_type_vlen(t);
|
||||
if (nargs > 5) {
|
||||
bpf_log(log, "Function %s has %d > 5 args\n", tname, nargs);
|
||||
if (nargs > MAX_BPF_FUNC_REG_ARGS) {
|
||||
bpf_log(log, "Function %s has %d > %d args\n", tname, nargs,
|
||||
MAX_BPF_FUNC_REG_ARGS);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -5458,9 +5540,9 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog,
|
||||
}
|
||||
args = (const struct btf_param *)(t + 1);
|
||||
nargs = btf_type_vlen(t);
|
||||
if (nargs > 5) {
|
||||
bpf_log(log, "Global function %s() with %d > 5 args. Buggy compiler.\n",
|
||||
tname, nargs);
|
||||
if (nargs > MAX_BPF_FUNC_REG_ARGS) {
|
||||
bpf_log(log, "Global function %s() with %d > %d args. Buggy compiler.\n",
|
||||
tname, nargs, MAX_BPF_FUNC_REG_ARGS);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* check that function returns int */
|
||||
|
||||
Reference in New Issue
Block a user