Commit aea2f7b8 authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Daniel Borkmann

bpf: btf: Remove unused bits from uapi/linux/btf.h

This patch does the followings:
1. Limit BTF_MAX_TYPES and BTF_MAX_NAME_OFFSET to 64k.  We can
   raise it later.

2. Remove the BTF_TYPE_PARENT and BTF_STR_TBL_ELF_ID.  They are
   currently encoded at the highest bit of a u32.
   It is because the current use case does not require supporting
   parent type (i.e type_id referring to a type in another BTF file).
   It also does not support referring to a string in ELF.

   The BTF_TYPE_PARENT and BTF_STR_TBL_ELF_ID checks are replaced
   by BTF_TYPE_ID_CHECK and BTF_STR_OFFSET_CHECK which are
   defined in btf.c instead of uapi/linux/btf.h.

3. Limit the BTF_INFO_KIND from 5 bits to 4 bits which is enough.
   There is unused bits headroom if we ever needed it later.

4. The root bit in BTF_INFO is also removed because it is not
   used in the current use case.

5. Remove BTF_INT_VARARGS since func type is not supported now.
   The BTF_INT_ENCODING is limited to 4 bits instead of 8 bits.

The above can be added back later because the verifier
ensures the unused bits are zeros.
Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 4ef5f574
...@@ -22,28 +22,19 @@ struct btf_header { ...@@ -22,28 +22,19 @@ struct btf_header {
}; };
/* Max # of type identifier */ /* Max # of type identifier */
#define BTF_MAX_TYPE 0x7fffffff #define BTF_MAX_TYPE 0x0000ffff
/* Max offset into the string section */ /* Max offset into the string section */
#define BTF_MAX_NAME_OFFSET 0x7fffffff #define BTF_MAX_NAME_OFFSET 0x0000ffff
/* Max # of struct/union/enum members or func args */ /* Max # of struct/union/enum members or func args */
#define BTF_MAX_VLEN 0xffff #define BTF_MAX_VLEN 0xffff
/* The type id is referring to a parent BTF */
#define BTF_TYPE_PARENT(id) (((id) >> 31) & 0x1)
#define BTF_TYPE_ID(id) ((id) & BTF_MAX_TYPE)
/* String is in the ELF string section */
#define BTF_STR_TBL_ELF_ID(ref) (((ref) >> 31) & 0x1)
#define BTF_STR_OFFSET(ref) ((ref) & BTF_MAX_NAME_OFFSET)
struct btf_type { struct btf_type {
__u32 name_off; __u32 name_off;
/* "info" bits arrangement /* "info" bits arrangement
* bits 0-15: vlen (e.g. # of struct's members) * bits 0-15: vlen (e.g. # of struct's members)
* bits 16-23: unused * bits 16-23: unused
* bits 24-28: kind (e.g. int, ptr, array...etc) * bits 24-27: kind (e.g. int, ptr, array...etc)
* bits 29-30: unused * bits 28-31: unused
* bits 31: root
*/ */
__u32 info; __u32 info;
/* "size" is used by INT, ENUM, STRUCT and UNION. /* "size" is used by INT, ENUM, STRUCT and UNION.
...@@ -58,8 +49,7 @@ struct btf_type { ...@@ -58,8 +49,7 @@ struct btf_type {
}; };
}; };
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x1f) #define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
#define BTF_INFO_ISROOT(info) (!!(((info) >> 24) & 0x80))
#define BTF_INFO_VLEN(info) ((info) & 0xffff) #define BTF_INFO_VLEN(info) ((info) & 0xffff)
#define BTF_KIND_UNKN 0 /* Unknown */ #define BTF_KIND_UNKN 0 /* Unknown */
...@@ -84,15 +74,14 @@ struct btf_type { ...@@ -84,15 +74,14 @@ struct btf_type {
/* BTF_KIND_INT is followed by a u32 and the following /* BTF_KIND_INT is followed by a u32 and the following
* is the 32 bits arrangement: * is the 32 bits arrangement:
*/ */
#define BTF_INT_ENCODING(VAL) (((VAL) & 0xff000000) >> 24) #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) #define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff) #define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff)
/* Attributes stored in the BTF_INT_ENCODING */ /* Attributes stored in the BTF_INT_ENCODING */
#define BTF_INT_SIGNED 0x1 #define BTF_INT_SIGNED (1 << 0)
#define BTF_INT_CHAR 0x2 #define BTF_INT_CHAR (1 << 1)
#define BTF_INT_BOOL 0x4 #define BTF_INT_BOOL (1 << 2)
#define BTF_INT_VARARGS 0x8
/* BTF_KIND_ENUM is followed by multiple "struct btf_enum". /* BTF_KIND_ENUM is followed by multiple "struct btf_enum".
* The exact number of btf_enum is stored in the vlen (of the * The exact number of btf_enum is stored in the vlen (of the
......
...@@ -163,13 +163,16 @@ ...@@ -163,13 +163,16 @@
#define BITS_ROUNDUP_BYTES(bits) \ #define BITS_ROUNDUP_BYTES(bits) \
(BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits)) (BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits))
#define BTF_INFO_MASK 0x0f00ffff
#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)
/* 16MB for 64k structs and each has 16 members and /* 16MB for 64k structs and each has 16 members and
* a few MB spaces for the string section. * a few MB spaces for the string section.
* The hard limit is S32_MAX. * The hard limit is S32_MAX.
*/ */
#define BTF_MAX_SIZE (16 * 1024 * 1024) #define BTF_MAX_SIZE (16 * 1024 * 1024)
/* 64k. We can raise it later. The hard limit is S32_MAX. */
#define BTF_MAX_NR_TYPES 65535
#define for_each_member(i, struct_type, member) \ #define for_each_member(i, struct_type, member) \
for (i = 0, member = btf_type_member(struct_type); \ for (i = 0, member = btf_type_member(struct_type); \
...@@ -383,8 +386,6 @@ static const char *btf_int_encoding_str(u8 encoding) ...@@ -383,8 +386,6 @@ static const char *btf_int_encoding_str(u8 encoding)
return "CHAR"; return "CHAR";
else if (encoding == BTF_INT_BOOL) else if (encoding == BTF_INT_BOOL)
return "BOOL"; return "BOOL";
else if (encoding == BTF_INT_VARARGS)
return "VARARGS";
else else
return "UNKN"; return "UNKN";
} }
...@@ -421,16 +422,16 @@ static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t) ...@@ -421,16 +422,16 @@ static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t)
static bool btf_name_offset_valid(const struct btf *btf, u32 offset) static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
{ {
return !BTF_STR_TBL_ELF_ID(offset) && return BTF_STR_OFFSET_VALID(offset) &&
BTF_STR_OFFSET(offset) < btf->hdr.str_len; offset < btf->hdr.str_len;
} }
static const char *btf_name_by_offset(const struct btf *btf, u32 offset) static const char *btf_name_by_offset(const struct btf *btf, u32 offset)
{ {
if (!BTF_STR_OFFSET(offset)) if (!offset)
return "(anon)"; return "(anon)";
else if (BTF_STR_OFFSET(offset) < btf->hdr.str_len) else if (offset < btf->hdr.str_len)
return &btf->strings[BTF_STR_OFFSET(offset)]; return &btf->strings[offset];
else else
return "(invalid-name-offset)"; return "(invalid-name-offset)";
} }
...@@ -598,13 +599,13 @@ static int btf_add_type(struct btf_verifier_env *env, struct btf_type *t) ...@@ -598,13 +599,13 @@ static int btf_add_type(struct btf_verifier_env *env, struct btf_type *t)
struct btf_type **new_types; struct btf_type **new_types;
u32 expand_by, new_size; u32 expand_by, new_size;
if (btf->types_size == BTF_MAX_NR_TYPES) { if (btf->types_size == BTF_MAX_TYPE) {
btf_verifier_log(env, "Exceeded max num of types"); btf_verifier_log(env, "Exceeded max num of types");
return -E2BIG; return -E2BIG;
} }
expand_by = max_t(u32, btf->types_size >> 2, 16); expand_by = max_t(u32, btf->types_size >> 2, 16);
new_size = min_t(u32, BTF_MAX_NR_TYPES, new_size = min_t(u32, BTF_MAX_TYPE,
btf->types_size + expand_by); btf->types_size + expand_by);
new_types = kvzalloc(new_size * sizeof(*new_types), new_types = kvzalloc(new_size * sizeof(*new_types),
...@@ -934,6 +935,12 @@ static s32 btf_int_check_meta(struct btf_verifier_env *env, ...@@ -934,6 +935,12 @@ static s32 btf_int_check_meta(struct btf_verifier_env *env,
} }
int_data = btf_type_int(t); int_data = btf_type_int(t);
if (int_data & ~BTF_INT_MASK) {
btf_verifier_log_basic(env, t, "Invalid int_data:%x",
int_data);
return -EINVAL;
}
nr_bits = BTF_INT_BITS(int_data) + BTF_INT_OFFSET(int_data); nr_bits = BTF_INT_BITS(int_data) + BTF_INT_OFFSET(int_data);
if (nr_bits > BITS_PER_U64) { if (nr_bits > BITS_PER_U64) {
...@@ -947,12 +954,17 @@ static s32 btf_int_check_meta(struct btf_verifier_env *env, ...@@ -947,12 +954,17 @@ static s32 btf_int_check_meta(struct btf_verifier_env *env,
return -EINVAL; return -EINVAL;
} }
/*
* Only one of the encoding bits is allowed and it
* should be sufficient for the pretty print purpose (i.e. decoding).
* Multiple bits can be allowed later if it is found
* to be insufficient.
*/
encoding = BTF_INT_ENCODING(int_data); encoding = BTF_INT_ENCODING(int_data);
if (encoding && if (encoding &&
encoding != BTF_INT_SIGNED && encoding != BTF_INT_SIGNED &&
encoding != BTF_INT_CHAR && encoding != BTF_INT_CHAR &&
encoding != BTF_INT_BOOL && encoding != BTF_INT_BOOL) {
encoding != BTF_INT_VARARGS) {
btf_verifier_log_type(env, t, "Unsupported encoding"); btf_verifier_log_type(env, t, "Unsupported encoding");
return -ENOTSUPP; return -ENOTSUPP;
} }
...@@ -1126,7 +1138,7 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env, ...@@ -1126,7 +1138,7 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env,
return -EINVAL; return -EINVAL;
} }
if (BTF_TYPE_PARENT(t->type)) { if (!BTF_TYPE_ID_VALID(t->type)) {
btf_verifier_log_type(env, t, "Invalid type_id"); btf_verifier_log_type(env, t, "Invalid type_id");
return -EINVAL; return -EINVAL;
} }
...@@ -1333,12 +1345,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env *env, ...@@ -1333,12 +1345,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env *env,
/* Array elem type and index type cannot be in type void, /* Array elem type and index type cannot be in type void,
* so !array->type and !array->index_type are not allowed. * so !array->type and !array->index_type are not allowed.
*/ */
if (!array->type || BTF_TYPE_PARENT(array->type)) { if (!array->type || !BTF_TYPE_ID_VALID(array->type)) {
btf_verifier_log_type(env, t, "Invalid elem"); btf_verifier_log_type(env, t, "Invalid elem");
return -EINVAL; return -EINVAL;
} }
if (!array->index_type || BTF_TYPE_PARENT(array->index_type)) { if (!array->index_type || !BTF_TYPE_ID_VALID(array->index_type)) {
btf_verifier_log_type(env, t, "Invalid index"); btf_verifier_log_type(env, t, "Invalid index");
return -EINVAL; return -EINVAL;
} }
...@@ -1507,7 +1519,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env, ...@@ -1507,7 +1519,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
} }
/* A member cannot be in type void */ /* A member cannot be in type void */
if (!member->type || BTF_TYPE_PARENT(member->type)) { if (!member->type || !BTF_TYPE_ID_VALID(member->type)) {
btf_verifier_log_member(env, t, member, btf_verifier_log_member(env, t, member,
"Invalid type_id"); "Invalid type_id");
return -EINVAL; return -EINVAL;
...@@ -1760,6 +1772,12 @@ static s32 btf_check_meta(struct btf_verifier_env *env, ...@@ -1760,6 +1772,12 @@ static s32 btf_check_meta(struct btf_verifier_env *env,
} }
meta_left -= sizeof(*t); meta_left -= sizeof(*t);
if (t->info & ~BTF_INFO_MASK) {
btf_verifier_log(env, "[%u] Invalid btf_info:%x",
env->log_type_id, t->info);
return -EINVAL;
}
if (BTF_INFO_KIND(t->info) > BTF_KIND_MAX || if (BTF_INFO_KIND(t->info) > BTF_KIND_MAX ||
BTF_INFO_KIND(t->info) == BTF_KIND_UNKN) { BTF_INFO_KIND(t->info) == BTF_KIND_UNKN) {
btf_verifier_log(env, "[%u] Invalid kind:%u", btf_verifier_log(env, "[%u] Invalid kind:%u",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment