diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-07 01:09:53 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-07 01:09:53 +0000 |
commit | 860fa57e5ad47e1be73061834e96b8331166bde1 (patch) | |
tree | b4608f90b54a697c11c980d1bc849e4e5e03e7f8 | |
parent | a0f17b1347bb17833ba8f7f0bdd2c2b66e5e01a7 (diff) | |
parent | bb1485f836d496570a337f6d7b809a3e44191f71 (diff) | |
download | bpf-android12L-platform-release.tar.gz |
Snap for 7526832 from bb1485f836d496570a337f6d7b809a3e44191f71 to sc-v2-releaseandroid-vts-12.1_r9android-vts-12.1_r8android-vts-12.1_r7android-vts-12.1_r6android-vts-12.1_r5android-vts-12.1_r4android-vts-12.1_r3android-vts-12.1_r2android-vts-12.1_r10android-vts-12.1_r1android-platform-12.1.0_r9android-platform-12.1.0_r8android-platform-12.1.0_r7android-platform-12.1.0_r6android-platform-12.1.0_r5android-platform-12.1.0_r4android-platform-12.1.0_r3android-platform-12.1.0_r27android-platform-12.1.0_r26android-platform-12.1.0_r25android-platform-12.1.0_r24android-platform-12.1.0_r23android-platform-12.1.0_r22android-platform-12.1.0_r21android-platform-12.1.0_r20android-platform-12.1.0_r2android-platform-12.1.0_r19android-platform-12.1.0_r18android-platform-12.1.0_r17android-platform-12.1.0_r16android-platform-12.1.0_r15android-platform-12.1.0_r14android-platform-12.1.0_r13android-platform-12.1.0_r12android-platform-12.1.0_r11android-platform-12.1.0_r10android-platform-12.1.0_r1android-cts-12.1_r9android-cts-12.1_r8android-cts-12.1_r7android-cts-12.1_r6android-cts-12.1_r5android-cts-12.1_r4android-cts-12.1_r3android-cts-12.1_r2android-cts-12.1_r10android-cts-12.1_r1android-12.1.0_r6android-12.1.0_r5android-12.1.0_r4android-12.1.0_r3android-12.1.0_r27android-12.1.0_r2android-12.1.0_r1android12L-tests-releaseandroid12L-s1-releaseandroid12L-releaseandroid12L-platform-releaseandroid12L-gsi
Change-Id: Ief52c115940a7a55e36ba1dda99cebed153c15ed
-rw-r--r-- | libbpf_android/Loader.cpp | 38 | ||||
-rw-r--r-- | libbpf_android/include/libbpf_android.h | 3 | ||||
-rw-r--r-- | progs/include/bpf_helpers.h | 10 | ||||
-rw-r--r-- | progs/include/bpf_map_def.h | 94 |
4 files changed, 119 insertions, 26 deletions
diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp index b1af34f..259068a 100644 --- a/libbpf_android/Loader.cpp +++ b/libbpf_android/Loader.cpp @@ -28,10 +28,9 @@ #include <sys/utsname.h> #include <unistd.h> -// This is BpfLoader 0.1, we need to define this prior to including bpf_map_def.h -// to get the 0.1 struct definitions +// This is BpfLoader v0.2 #define BPFLOADER_VERSION_MAJOR 0u -#define BPFLOADER_VERSION_MINOR 1u +#define BPFLOADER_VERSION_MINOR 2u #define BPFLOADER_VERSION ((BPFLOADER_VERSION_MAJOR << 16) | BPFLOADER_VERSION_MINOR) #include "../progs/include/bpf_map_def.h" @@ -211,7 +210,7 @@ static int readSectionByName(const char* name, ifstream& elfFile, vector<char>& return -2; } -static unsigned int readSectionUint(const char* name, ifstream& elfFile, unsigned int defVal) { +unsigned int readSectionUint(const char* name, ifstream& elfFile, unsigned int defVal) { vector<char> theBytes; int ret = readSectionByName(name, elfFile, theBytes); if (ret) { @@ -494,6 +493,7 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>& memset(&m, 0, sizeof(m)); // Then we set non-zero defaults m.bpfloader_max_ver = DEFAULT_BPFLOADER_MAX_VER; // v1.0 + m.max_kver = 0xFFFFFFFFu; // matches KVER_INF from bpf_helpers.h // Then we copy over the structure prefix from the ELF file. memcpy(&m, dataPtr, trimmedSize); // Move to next struct in the ELF file @@ -503,14 +503,9 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>& ret = getSectionSymNames(elfFile, "maps", mapNames); if (ret) return ret; - for (int i = 0; i < (int)mapNames.size(); i++) { - unique_fd fd; - int saved_errno; - // Format of pin location is /sys/fs/bpf/<prefix>map_<filename>_<mapname> - string mapPinLoc = - string(BPF_FS_PATH) + prefix + "map_" + fname + "_" + string(mapNames[i]); - bool reuse = false; + unsigned kvers = kernelVersion(); + for (int i = 0; i < (int)mapNames.size(); i++) { if (BPFLOADER_VERSION < md[i].bpfloader_min_ver) { ALOGI("skipping map %s which requires bpfloader min ver 0x%05x\n", mapNames[i].c_str(), md[i].bpfloader_min_ver); @@ -525,6 +520,27 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>& continue; } + if (kvers < md[i].min_kver) { + ALOGI("skipping map %s which requires kernel version 0x%x >= 0x%x\n", + mapNames[i].c_str(), kvers, md[i].min_kver); + mapFds.push_back(unique_fd()); + continue; + } + + if (kvers >= md[i].max_kver) { + ALOGI("skipping map %s which requires kernel version 0x%x < 0x%x\n", + mapNames[i].c_str(), kvers, md[i].max_kver); + mapFds.push_back(unique_fd()); + continue; + } + + // Format of pin location is /sys/fs/bpf/<prefix>map_<filename>_<mapname> + string mapPinLoc = + string(BPF_FS_PATH) + prefix + "map_" + fname + "_" + string(mapNames[i]); + bool reuse = false; + unique_fd fd; + int saved_errno; + if (access(mapPinLoc.c_str(), F_OK) == 0) { fd.reset(bpf_obj_get(mapPinLoc.c_str())); saved_errno = errno; diff --git a/libbpf_android/include/libbpf_android.h b/libbpf_android/include/libbpf_android.h index 90c9906..640f35b 100644 --- a/libbpf_android/include/libbpf_android.h +++ b/libbpf_android/include/libbpf_android.h @@ -29,6 +29,9 @@ namespace bpf { // BPF loader implementation. Loads an eBPF ELF object int loadProg(const char* elfPath, bool* isCritical, const char* prefix = ""); +// Exposed for testing +unsigned int readSectionUint(const char* name, std::ifstream& elfFile, unsigned int defVal); + // Wait for bpfloader to load BPF programs. static inline void waitForProgsLoaded() { // infinite loop until success with 5/10/20/40/60/60/60... delay diff --git a/progs/include/bpf_helpers.h b/progs/include/bpf_helpers.h index 6e5fe69..abd19c6 100644 --- a/progs/include/bpf_helpers.h +++ b/progs/include/bpf_helpers.h @@ -59,6 +59,10 @@ * implemented in the kernel sources. */ +#define KVER_NONE 0 +#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c)) +#define KVER_INF 0xFFFFFFFFu + /* generic functions */ /* @@ -110,6 +114,8 @@ static int (*bpf_map_delete_elem_unsafe)(const struct bpf_map_def* map, .mode = (md), \ .bpfloader_min_ver = DEFAULT_BPFLOADER_MIN_VER, \ .bpfloader_max_ver = DEFAULT_BPFLOADER_MAX_VER, \ + .min_kver = KVER_NONE, \ + .max_kver = KVER_INF, \ }; \ \ static inline __always_inline __unused TypeOfValue* bpf_##the_map##_lookup_elem( \ @@ -147,10 +153,6 @@ static unsigned long long (*bpf_get_current_pid_tgid)(void) = (void*) BPF_FUNC_g static unsigned long long (*bpf_get_current_uid_gid)(void) = (void*) BPF_FUNC_get_current_uid_gid; static unsigned long long (*bpf_get_smp_processor_id)(void) = (void*) BPF_FUNC_get_smp_processor_id; -#define KVER_NONE 0 -#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c)) -#define KVER_INF 0xFFFFFFFF - #define DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \ opt) \ const struct bpf_prog_def SEC("progs") the_prog##_def = { \ diff --git a/progs/include/bpf_map_def.h b/progs/include/bpf_map_def.h index 0034a35..647c813 100644 --- a/progs/include/bpf_map_def.h +++ b/progs/include/bpf_map_def.h @@ -42,16 +42,74 @@ * * ******************************************************************************/ -// We currently default to v0.1 format -#ifndef BPFLOADER_VERSION -#define BPFLOADER_VERSION 1u -#endif - // These are the values used if these fields are missing #define DEFAULT_BPFLOADER_MIN_VER 0u // v0.0 (this is inclusive ie. >= v0.0) #define DEFAULT_BPFLOADER_MAX_VER 0x10000u // v1.0 (this is exclusive ie. < v1.0) -#define DEFAULT_SIZEOF_BPF_MAP_DEF 32 // v0.0 struct: enum + alignment padding + 7 uint -#define DEFAULT_SIZEOF_BPF_PROG_DEF 20 // v0.0 struct: 4 uint + bool + alignment padding +#define DEFAULT_SIZEOF_BPF_MAP_DEF 32 // v0.0 struct: enum (uint sized) + 7 uint +#define DEFAULT_SIZEOF_BPF_PROG_DEF 20 // v0.0 struct: 4 uint + bool + 3 byte alignment pad + +/* + * The bpf_{map,prog}_def structures are compiled for different architectures. + * Once by the BPF compiler for the BPF architecture, and once by a C++ + * compiler for the native Android architecture for the bpfloader. + * + * For things to work, their layout must be the same between the two. + * The BPF architecture is platform independent ('64-bit LSB bpf'). + * So this effectively means these structures must be the same layout + * on 5 architectures, all of them little endian: + * 64-bit BPF, x86_64, arm and 32-bit x86 and arm + * + * As such for any types we use inside of these structs we must make sure that + * the size and alignment are the same, so the same amount of padding is used. + * + * Currently we only use: bool, enum bpf_map_type and unsigned int. + * Additionally we use char for padding. + * + * !!! WARNING: HERE BE DRAGONS !!! + * + * Be particularly careful with 64-bit integers. + * You will need to manually override their alignment to 8 bytes. + * + * To quote some parts of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 + * + * Some types have weaker alignment requirements when they are structure members. + * + * unsigned long long on x86 is such a type. + * + * C distinguishes C11 _Alignof (the minimum alignment the type is guaranteed + * to have in all contexts, so 4, see min_align_of_type) from GNU C __alignof + * (the normal alignment of the type, so 8). + * + * alignof / _Alignof == minimum alignment required by target ABI + * __alignof / __alignof__ == preferred alignment + * + * When in a struct, apparently the minimum alignment is used. + */ + +_Static_assert(sizeof(bool) == 1, "sizeof bool != 1"); +_Static_assert(__alignof__(bool) == 1, "__alignof__ bool != 1"); +_Static_assert(_Alignof(bool) == 1, "_Alignof bool != 1"); + +_Static_assert(sizeof(char) == 1, "sizeof char != 1"); +_Static_assert(__alignof__(char) == 1, "__alignof__ char != 1"); +_Static_assert(_Alignof(char) == 1, "_Alignof char != 1"); + +// This basically verifies that an enum is 'just' a 32-bit int +_Static_assert(sizeof(enum bpf_map_type) == 4, "sizeof enum bpf_map_type != 4"); +_Static_assert(__alignof__(enum bpf_map_type) == 4, "__alignof__ enum bpf_map_type != 4"); +_Static_assert(_Alignof(enum bpf_map_type) == 4, "_Alignof enum bpf_map_type != 4"); + +// Linux kernel requires sizeof(int) == 4, sizeof(void*) == sizeof(long), sizeof(long long) == 8 +_Static_assert(sizeof(unsigned int) == 4, "sizeof unsigned int != 4"); +_Static_assert(__alignof__(unsigned int) == 4, "__alignof__ unsigned int != 4"); +_Static_assert(_Alignof(unsigned int) == 4, "_Alignof unsigned int != 4"); + +// We don't currently use any 64-bit types in these structs, so this is purely to document issue. +// Here sizeof & __alignof__ are consistent, but _Alignof is not: compile for 'aosp_cf_x86_phone' +_Static_assert(sizeof(unsigned long long) == 8, "sizeof unsigned long long != 8"); +_Static_assert(__alignof__(unsigned long long) == 8, "__alignof__ unsigned long long != 8"); +// BPF wants 8, but 32-bit x86 wants 4 +//_Static_assert(_Alignof(unsigned long long) == 8, "_Alignof unsigned long long != 8"); /* * Map structure to be used by Android eBPF C programs. The Android eBPF loader @@ -80,13 +138,21 @@ struct bpf_map_def { unsigned int gid; // gid_t unsigned int mode; // mode_t -#if BPFLOADER_VERSION >= 1u // The following fields were added in version 0.1 unsigned int bpfloader_min_ver; // if missing, defaults to 0, ie. v0.0 unsigned int bpfloader_max_ver; // if missing, defaults to 0x10000, ie. v1.0 -#endif + + // The following fields were added in version 0.2 + // kernelVersion() must be >= min_kver and < max_kver + unsigned int min_kver; + unsigned int max_kver; }; +// This needs to be updated whenever the above structure definition is expanded. +_Static_assert(sizeof(struct bpf_map_def) == 48, "sizeof struct bpf_map_def != 48"); +_Static_assert(__alignof__(struct bpf_map_def) == 4, "__alignof__ struct bpf_map_def != 4"); +_Static_assert(_Alignof(struct bpf_map_def) == 4, "_Alignof struct bpf_map_def != 4"); + struct bpf_prog_def { unsigned int uid; unsigned int gid; @@ -96,10 +162,16 @@ struct bpf_prog_def { unsigned int max_kver; bool optional; // program section (ie. function) may fail to load, continue onto next func. + char pad0[3]; -#if BPFLOADER_VERSION >= 1u // The following fields were added in version 0.1 unsigned int bpfloader_min_ver; // if missing, defaults to 0, ie. v0.0 unsigned int bpfloader_max_ver; // if missing, defaults to 0x10000, ie. v1.0 -#endif + + // No new fields in version 0.2 }; + +// This needs to be updated whenever the above structure definition is expanded. +_Static_assert(sizeof(struct bpf_prog_def) == 28, "sizeof struct bpf_prog_def != 28"); +_Static_assert(__alignof__(struct bpf_prog_def) == 4, "__alignof__ struct bpf_prog_def != 4"); +_Static_assert(_Alignof(struct bpf_prog_def) == 4, "_Alignof struct bpf_prog_def != 4"); |