bpfloader: provide a way to fail loading a bpf .o due to old version

we currently have a way to entirely ignore a bpf .o file on older
bpfloaders, however sometimes (especially during development) we
don't want the file to be ignored (because it is required for correct
system operation) but we already know at build time that it is incompatible
due to some missing bpfloader functionality.

While in such a situation stuff will likely fail anyway (either
bpfloader will fail due to missing privs or maps/programs won't
be created and netd updatable library will fail, or something else...),
this happens *much* later and is actually much harder to debug.

This way the failure is early, and the error message is clear.

This will make it easier for us to prevent such broken setups
from ever making it out to devices, as - for a critical program
- the resulting bpfloader boot time failure will trigger a mainline
module rollback.

While developing further isolation changes to tethering apex bpf
programs I've run into cases where I've wanted to make changes
that requires bpfloader >= X to work correctly.  This will help
make such changes safely in the future.

Bug: 218408035
Test: TreeHugger, manual testing
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Ic11b48312dfe5960b787e1786b690773a41a4d18
diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp
index 7c5b5cb..b13baa1 100644
--- a/libbpf_android/Loader.cpp
+++ b/libbpf_android/Loader.cpp
@@ -30,9 +30,9 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-// This is BpfLoader v0.23
+// This is BpfLoader v0.24
 #define BPFLOADER_VERSION_MAJOR 0u
-#define BPFLOADER_VERSION_MINOR 23u
+#define BPFLOADER_VERSION_MINOR 24u
 #define BPFLOADER_VERSION ((BPFLOADER_VERSION_MAJOR << 16) | BPFLOADER_VERSION_MINOR)
 
 #include "bpf/BpfUtils.h"
@@ -1180,6 +1180,8 @@
             readSectionUint("bpfloader_min_ver", elfFile, DEFAULT_BPFLOADER_MIN_VER);
     unsigned int bpfLoaderMaxVer =
             readSectionUint("bpfloader_max_ver", elfFile, DEFAULT_BPFLOADER_MAX_VER);
+    unsigned int bpfLoaderMinRequiredVer =
+            readSectionUint("bpfloader_min_required_ver", elfFile, 0);
     size_t sizeOfBpfMapDef =
             readSectionUint("size_of_bpf_map_def", elfFile, DEFAULT_SIZEOF_BPF_MAP_DEF);
     size_t sizeOfBpfProgDef =
@@ -1199,6 +1201,12 @@
         return 0;
     }
 
+    if (BPFLOADER_VERSION < bpfLoaderMinRequiredVer) {
+        ALOGI("BpfLoader version 0x%05x failing due to ELF object %s with required min ver 0x%05x",
+              BPFLOADER_VERSION, elfPath, bpfLoaderMinRequiredVer);
+        return -1;
+    }
+
     ALOGI("BpfLoader version 0x%05x processing ELF object %s with ver [0x%05x,0x%05x)",
           BPFLOADER_VERSION, elfPath, bpfLoaderMinVer, bpfLoaderMaxVer);