mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
![Alexei Starovoitov](/assets/img/avatar_default.png)
New llvm and old llvm with libbpf help produce BTF that distinguish global and static functions. Unlike arguments of static function the arguments of global functions cannot be removed or optimized away by llvm. The compiler has to use exactly the arguments specified in a function prototype. The argument type information allows the verifier validate each global function independently. For now only supported argument types are pointer to context and scalars. In the future pointers to structures, sizes, pointer to packet data can be supported as well. Consider the following example: static int f1(int ...) { ... } int f3(int b); int f2(int a) { f1(a) + f3(a); } int f3(int b) { ... } int main(...) { f1(...) + f2(...) + f3(...); } The verifier will start its safety checks from the first global function f2(). It will recursively descend into f1() because it's static. Then it will check that arguments match for the f3() invocation inside f2(). It will not descend into f3(). It will finish f2() that has to be successfully verified for all possible values of 'a'. Then it will proceed with f3(). That function also has to be safe for all possible values of 'b'. Then it will start subprog 0 (which is main() function). It will recursively descend into f1() and will skip full check of f2() and f3(), since they are global. The order of processing global functions doesn't affect safety, since all global functions must be proven safe based on their arguments only. Such function by function verification can drastically improve speed of the verification and reduce complexity. Note that the stack limit of 512 still applies to the call chain regardless whether functions were static or global. The nested level of 8 also still applies. The same recursion prevention checks are in place as well. The type information and static/global kind is preserved after the verification hence in the above example global function f2() and f3() can be replaced later by equivalent functions with the same types that are loaded and verified later without affecting safety of this main() program. Such replacement (re-linking) of global functions is a subject of future patches. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Song Liu <songliubraving@fb.com> Link: https://lore.kernel.org/bpf/20200110064124.1760511-3-ast@kernel.org
172 lines
4.7 KiB
C
172 lines
4.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
/* Copyright (c) 2018 Facebook */
|
|
#ifndef _UAPI__LINUX_BTF_H__
|
|
#define _UAPI__LINUX_BTF_H__
|
|
|
|
#include <linux/types.h>
|
|
|
|
#define BTF_MAGIC 0xeB9F
|
|
#define BTF_VERSION 1
|
|
|
|
struct btf_header {
|
|
__u16 magic;
|
|
__u8 version;
|
|
__u8 flags;
|
|
__u32 hdr_len;
|
|
|
|
/* All offsets are in bytes relative to the end of this header */
|
|
__u32 type_off; /* offset of type section */
|
|
__u32 type_len; /* length of type section */
|
|
__u32 str_off; /* offset of string section */
|
|
__u32 str_len; /* length of string section */
|
|
};
|
|
|
|
/* Max # of type identifier */
|
|
#define BTF_MAX_TYPE 0x000fffff
|
|
/* Max offset into the string section */
|
|
#define BTF_MAX_NAME_OFFSET 0x00ffffff
|
|
/* Max # of struct/union/enum members or func args */
|
|
#define BTF_MAX_VLEN 0xffff
|
|
|
|
struct btf_type {
|
|
__u32 name_off;
|
|
/* "info" bits arrangement
|
|
* bits 0-15: vlen (e.g. # of struct's members)
|
|
* bits 16-23: unused
|
|
* bits 24-27: kind (e.g. int, ptr, array...etc)
|
|
* bits 28-30: unused
|
|
* bit 31: kind_flag, currently used by
|
|
* struct, union and fwd
|
|
*/
|
|
__u32 info;
|
|
/* "size" is used by INT, ENUM, STRUCT, UNION and DATASEC.
|
|
* "size" tells the size of the type it is describing.
|
|
*
|
|
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
|
|
* FUNC, FUNC_PROTO and VAR.
|
|
* "type" is a type_id referring to another type.
|
|
*/
|
|
union {
|
|
__u32 size;
|
|
__u32 type;
|
|
};
|
|
};
|
|
|
|
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
|
|
#define BTF_INFO_VLEN(info) ((info) & 0xffff)
|
|
#define BTF_INFO_KFLAG(info) ((info) >> 31)
|
|
|
|
#define BTF_KIND_UNKN 0 /* Unknown */
|
|
#define BTF_KIND_INT 1 /* Integer */
|
|
#define BTF_KIND_PTR 2 /* Pointer */
|
|
#define BTF_KIND_ARRAY 3 /* Array */
|
|
#define BTF_KIND_STRUCT 4 /* Struct */
|
|
#define BTF_KIND_UNION 5 /* Union */
|
|
#define BTF_KIND_ENUM 6 /* Enumeration */
|
|
#define BTF_KIND_FWD 7 /* Forward */
|
|
#define BTF_KIND_TYPEDEF 8 /* Typedef */
|
|
#define BTF_KIND_VOLATILE 9 /* Volatile */
|
|
#define BTF_KIND_CONST 10 /* Const */
|
|
#define BTF_KIND_RESTRICT 11 /* Restrict */
|
|
#define BTF_KIND_FUNC 12 /* Function */
|
|
#define BTF_KIND_FUNC_PROTO 13 /* Function Proto */
|
|
#define BTF_KIND_VAR 14 /* Variable */
|
|
#define BTF_KIND_DATASEC 15 /* Section */
|
|
#define BTF_KIND_MAX BTF_KIND_DATASEC
|
|
#define NR_BTF_KINDS (BTF_KIND_MAX + 1)
|
|
|
|
/* For some specific BTF_KIND, "struct btf_type" is immediately
|
|
* followed by extra data.
|
|
*/
|
|
|
|
/* BTF_KIND_INT is followed by a u32 and the following
|
|
* is the 32 bits arrangement:
|
|
*/
|
|
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
|
|
#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
|
|
#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
|
|
|
|
/* Attributes stored in the BTF_INT_ENCODING */
|
|
#define BTF_INT_SIGNED (1 << 0)
|
|
#define BTF_INT_CHAR (1 << 1)
|
|
#define BTF_INT_BOOL (1 << 2)
|
|
|
|
/* BTF_KIND_ENUM is followed by multiple "struct btf_enum".
|
|
* The exact number of btf_enum is stored in the vlen (of the
|
|
* info in "struct btf_type").
|
|
*/
|
|
struct btf_enum {
|
|
__u32 name_off;
|
|
__s32 val;
|
|
};
|
|
|
|
/* BTF_KIND_ARRAY is followed by one "struct btf_array" */
|
|
struct btf_array {
|
|
__u32 type;
|
|
__u32 index_type;
|
|
__u32 nelems;
|
|
};
|
|
|
|
/* BTF_KIND_STRUCT and BTF_KIND_UNION are followed
|
|
* by multiple "struct btf_member". The exact number
|
|
* of btf_member is stored in the vlen (of the info in
|
|
* "struct btf_type").
|
|
*/
|
|
struct btf_member {
|
|
__u32 name_off;
|
|
__u32 type;
|
|
/* If the type info kind_flag is set, the btf_member offset
|
|
* contains both member bitfield size and bit offset. The
|
|
* bitfield size is set for bitfield members. If the type
|
|
* info kind_flag is not set, the offset contains only bit
|
|
* offset.
|
|
*/
|
|
__u32 offset;
|
|
};
|
|
|
|
/* If the struct/union type info kind_flag is set, the
|
|
* following two macros are used to access bitfield_size
|
|
* and bit_offset from btf_member.offset.
|
|
*/
|
|
#define BTF_MEMBER_BITFIELD_SIZE(val) ((val) >> 24)
|
|
#define BTF_MEMBER_BIT_OFFSET(val) ((val) & 0xffffff)
|
|
|
|
/* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param".
|
|
* The exact number of btf_param is stored in the vlen (of the
|
|
* info in "struct btf_type").
|
|
*/
|
|
struct btf_param {
|
|
__u32 name_off;
|
|
__u32 type;
|
|
};
|
|
|
|
enum {
|
|
BTF_VAR_STATIC = 0,
|
|
BTF_VAR_GLOBAL_ALLOCATED = 1,
|
|
BTF_VAR_GLOBAL_EXTERN = 2,
|
|
};
|
|
|
|
enum btf_func_linkage {
|
|
BTF_FUNC_STATIC = 0,
|
|
BTF_FUNC_GLOBAL = 1,
|
|
BTF_FUNC_EXTERN = 2,
|
|
};
|
|
|
|
/* BTF_KIND_VAR is followed by a single "struct btf_var" to describe
|
|
* additional information related to the variable such as its linkage.
|
|
*/
|
|
struct btf_var {
|
|
__u32 linkage;
|
|
};
|
|
|
|
/* BTF_KIND_DATASEC is followed by multiple "struct btf_var_secinfo"
|
|
* to describe all BTF_KIND_VAR types it contains along with it's
|
|
* in-section offset as well as size.
|
|
*/
|
|
struct btf_var_secinfo {
|
|
__u32 type;
|
|
__u32 offset;
|
|
__u32 size;
|
|
};
|
|
|
|
#endif /* _UAPI__LINUX_BTF_H__ */
|