bpf loader improvements for better long term compatibility with mainline
This is bpfLoader v0.1, previously we had no version number,
the version immediately preceding this commit we'll call v0.0.
Versions older than that are either pre-S and don't matter, since
loading mainline eBpf code was only added in S, or are from early
during the S development cycle (ie. pre-March 5th 2021 or earlier)
and simply no longer supported (no need to maintain compatibility).
Bug: 190519702
Test: atest, TreeHugger - existing bpf programs load
examination of bpfloader logs
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I36fa5b917540be7ea3ecfddc5fe7834e9eb18d88
diff --git a/progs/include/bpf_helpers.h b/progs/include/bpf_helpers.h
index 075ea94..82ed72e 100644
--- a/progs/include/bpf_helpers.h
+++ b/progs/include/bpf_helpers.h
@@ -6,11 +6,47 @@
#include "bpf_map_def.h"
+/******************************************************************************
+ * WARNING: CHANGES TO THIS FILE OUTSIDE OF AOSP/MASTER ARE LIKELY TO BREAK *
+ * DEVICE COMPATIBILITY WITH MAINLINE MODULES SHIPPING EBPF CODE. *
+ * *
+ * THIS WILL LIKELY RESULT IN BRICKED DEVICES AT SOME ARBITRARY FUTURE TIME *
+ * *
+ * THAT GOES ESPECIALLY FOR THE 'SEC' 'LICENSE' AND 'CRITICAL' MACRO DEFINES *
+ * *
+ * We strongly suggest that if you need changes to bpfloader functionality *
+ * you get your changes reviewed and accepted into aosp/master. *
+ * *
+ ******************************************************************************/
+
/* place things in different elf sections */
#define SEC(NAME) __attribute__((section(NAME), used))
-/* Example use: LICENSE("GPL"); or LICENSE("Apache 2.0"); */
-#define LICENSE(NAME) char _license[] SEC("license") = (NAME)
+/* Must be present in every program, example usage:
+ * LICENSE("GPL"); or LICENSE("Apache 2.0");
+ *
+ * We also take this opportunity to embed a bunch of other useful values in
+ * the resulting .o (This is to enable some limited forward compatibility
+ * with mainline module shipped ebpf programs)
+ *
+ * The bpfloader_{min/max}_ver defines the [min, max) range of bpfloader
+ * versions that should load this .o file (bpfloaders outside of this range
+ * will simply ignore/skip this *entire* .o)
+ * The [inclusive,exclusive) matches what we do for kernel ver dependencies.
+ *
+ * The size_of_bpf_{map,prog}_def allow the bpfloader to load programs where
+ * these structures have been extended with additional fields (they will of
+ * course simply be ignored then).
+ *
+ * If missing, bpfloader_{min/max}_ver default to 0/0x10000 ie. [v0.0, v1.0),
+ * while size_of_bpf_{map/prog}_def default to 32/20 which are the v0.0 sizes.
+ */
+#define LICENSE(NAME) \
+ unsigned int _bpfloader_min_ver SEC("bpfloader_min_ver") = DEFAULT_BPFLOADER_MIN_VER; \
+ unsigned int _bpfloader_max_ver SEC("bpfloader_max_ver") = DEFAULT_BPFLOADER_MAX_VER; \
+ size_t _size_of_bpf_map_def SEC("size_of_bpf_map_def") = sizeof(struct bpf_map_def); \
+ size_t _size_of_bpf_prog_def SEC("size_of_bpf_prog_def") = sizeof(struct bpf_prog_def); \
+ char _license[] SEC("license") = (NAME)
/* flag the resulting bpf .o file as critical to system functionality,
* loading all kernel version appropriate programs in it must succeed
@@ -68,6 +104,7 @@
.key_size = sizeof(TypeOfKey), \
.value_size = sizeof(TypeOfValue), \
.max_entries = (num_entries), \
+ .map_flags = 0, \
.uid = (usr), \
.gid = (grp), \
.mode = (md), \
diff --git a/progs/include/bpf_map_def.h b/progs/include/bpf_map_def.h
index 50a822c..d80bfe7 100644
--- a/progs/include/bpf_map_def.h
+++ b/progs/include/bpf_map_def.h
@@ -25,6 +25,34 @@
// Pull in AID_* constants from //system/core/libcutils/include/private/android_filesystem_config.h
#include <private/android_filesystem_config.h>
+/******************************************************************************
+ * *
+ * ! ! ! W A R N I N G ! ! ! *
+ * *
+ * CHANGES TO THESE STRUCTURE DEFINITIONS OUTSIDE OF AOSP/MASTER *WILL* BREAK *
+ * MAINLINE MODULE COMPATIBILITY *
+ * *
+ * AND THUS MAY RESULT IN YOUR DEVICE BRICKING AT SOME ARBITRARY POINT IN *
+ * THE FUTURE *
+ * *
+ * (and even in aosp/master you may only append new fields at the very end, *
+ * you may *never* delete fields, change their types, ordering, insert in *
+ * the middle, etc. If a mainline module using the old definition has *
+ * already shipped (which happens roughly monthly), then it's set in stone) *
+ * *
+ ******************************************************************************/
+
+// For now we default to v0.0 format
+#ifndef BPFLOADER_VERSION
+#define BPFLOADER_VERSION 0u
+#endif
+
+// These are the values used if these fields are missing
+#define DEFAULT_BPFLOADER_MIN_VER 0u // v0.0
+#define DEFAULT_BPFLOADER_MAX_VER 0x10000u // 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
+
/*
* Map structure to be used by Android eBPF C programs. The Android eBPF loader
* uses this structure from eBPF object to create maps at boot time.
@@ -51,6 +79,12 @@
unsigned int uid; // uid_t
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
};
struct bpf_prog_def {
@@ -62,4 +96,10 @@
unsigned int max_kver;
bool optional; // program section (ie. function) may fail to load, continue onto next func.
+
+#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
};