Snap for 10843824 from aee36fd1ee3774d74666cc5b9c0155a439ad651a to 24Q1-release

Change-Id: I64ad987b334dbbce7077532a59a5891687c34cc4
diff --git a/bpfloader/Android.bp b/bpfloader/Android.bp
index 50d373b..18954eb 100644
--- a/bpfloader/Android.bp
+++ b/bpfloader/Android.bp
@@ -45,7 +45,6 @@
         "libbase",
         "liblog",
         "libnetdutils",
-        "libbpf_bcc",
     ],
     srcs: [
         "BpfLoader.cpp",
@@ -54,7 +53,6 @@
     init_rc: ["bpfloader.rc"],
 
     required: [
-        "btfloader",
         "timeInState.o"
     ],
 
diff --git a/bpfloader/BpfLoader.cpp b/bpfloader/BpfLoader.cpp
index fe51ed5..99a2ab4 100644
--- a/bpfloader/BpfLoader.cpp
+++ b/bpfloader/BpfLoader.cpp
@@ -251,6 +251,35 @@
     (void)argc;
     android::base::InitLogging(argv, &android::base::KernelLogger);
 
+    if (!android::bpf::isAtLeastKernelVersion(4, 19, 0)) {
+        ALOGE("Android U QPR2 requires kernel 4.19.");
+        return 1;
+    }
+
+    if (android::bpf::isUserspace32bit() && android::bpf::isAtLeastKernelVersion(6, 2, 0)) {
+        /* Android 14/U should only launch on 64-bit kernels
+         *   T launches on 5.10/5.15
+         *   U launches on 5.15/6.1
+         * So >=5.16 implies isKernel64Bit()
+         *
+         * We thus added a test to V VTS which requires 5.16+ devices to use 64-bit kernels.
+         *
+         * Starting with Android V, which is the first to support a post 6.1 Linux Kernel,
+         * we also require 64-bit userspace.
+         *
+         * There are various known issues with 32-bit userspace talking to various
+         * kernel interfaces (especially CAP_NET_ADMIN ones) on a 64-bit kernel.
+         * Some of these have userspace or kernel workarounds/hacks.
+         * Some of them don't...
+         * We're going to be removing the hacks.
+         *
+         * Additionally the 32-bit kernel jit support is poor,
+         * and 32-bit userspace on 64-bit kernel bpf ringbuffer compatibility is broken.
+         */
+        ALOGE("64-bit userspace required on 6.2+ kernels.");
+        return 1;
+    }
+
     // Ensure we can determine the Android build type.
     if (!android::bpf::isEng() && !android::bpf::isUser() && !android::bpf::isUserdebug()) {
         ALOGE("Failed to determine the build type: got %s, want 'eng', 'user', or 'userdebug'",
diff --git a/libbpf_android/Android.bp b/libbpf_android/Android.bp
index dda943d..d8272cc 100644
--- a/libbpf_android/Android.bp
+++ b/libbpf_android/Android.bp
@@ -42,8 +42,6 @@
         "libcutils",
         "libutils",
         "liblog",
-        "libbpf_bcc",
-        "libbpf_minimal",
     ],
     header_libs: [
         "bpf_headers",
@@ -51,7 +49,6 @@
     export_header_lib_headers: [
         "bpf_headers",
     ],
-    export_shared_lib_headers: ["libbpf_bcc"],
     export_include_dirs: ["include"],
 
     defaults: ["bpf_defaults"],
@@ -79,7 +76,6 @@
     shared_libs: [
         "libbpf_android",
         "libbpf_bcc",
-        "libbpf_minimal",
         "libbase",
         "liblog",
         "libutils",
@@ -87,7 +83,6 @@
 
     data: [
         ":bpfLoadTpProg.o",
-        ":bpfLoadTpProgBtf.o",
     ],
     require_root: true,
 }
diff --git a/libbpf_android/BpfLoadTest.cpp b/libbpf_android/BpfLoadTest.cpp
index 0c4e6ee..f3a8f85 100644
--- a/libbpf_android/BpfLoadTest.cpp
+++ b/libbpf_android/BpfLoadTest.cpp
@@ -17,6 +17,7 @@
 #include <android-base/file.h>
 #include <android-base/macros.h>
 #include <gtest/gtest.h>
+#include <libbpf.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <iostream>
@@ -66,7 +67,7 @@
         EXPECT_EQ(android::bpf::loadProg(progPath.c_str(), &critical), 0);
         EXPECT_EQ(false, critical);
 
-        mProgFd = bpf_obj_get(mTpProgPath.c_str());
+        mProgFd = retrieveProgram(mTpProgPath.c_str());
         EXPECT_GT(mProgFd, 0);
 
         int ret = bpf_attach_tracepoint(mProgFd, "sched", "sched_switch");
@@ -103,34 +104,18 @@
         EXPECT_EQ(non_zero, 1);
     }
 
-    void checkMapBtf() {
-        // Earlier kernels lack BPF_BTF_LOAD support
-        if (!isAtLeastKernelVersion(4, 19, 0)) GTEST_SKIP() << "pre-4.19 kernel does not support BTF";
-
-        const bool haveBtf = GetParam().find("Btf") != std::string::npos;
-
-        std::string str;
-        EXPECT_EQ(android::base::ReadFileToString(mTpMapPath, &str), haveBtf);
-        if (haveBtf) EXPECT_FALSE(str.empty());
-    }
-
     void checkKernelVersionEnforced() {
-        EXPECT_EQ(bpf_obj_get(mTpNeverLoadProgPath.c_str()), -1);
+        EXPECT_EQ(retrieveProgram(mTpNeverLoadProgPath.c_str()), -1);
         EXPECT_EQ(errno, ENOENT);
     }
 };
 
-INSTANTIATE_TEST_SUITE_P(BpfLoadTests, BpfLoadTest,
-                         ::testing::Values("bpfLoadTpProg", "bpfLoadTpProgBtf"));
+INSTANTIATE_TEST_SUITE_P(BpfLoadTests, BpfLoadTest, ::testing::Values("bpfLoadTpProg"));
 
 TEST_P(BpfLoadTest, bpfCheckMap) {
     checkMapNonZero();
 }
 
-TEST_P(BpfLoadTest, bpfCheckBtf) {
-    checkMapBtf();
-}
-
 TEST_P(BpfLoadTest, bpfCheckMinKernelVersionEnforced) {
     checkKernelVersionEnforced();
 }
diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp
index 83f6a88..d817614 100644
--- a/libbpf_android/Loader.cpp
+++ b/libbpf_android/Loader.cpp
@@ -31,13 +31,13 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-// This is BpfLoader v0.40
+// This is BpfLoader v0.41
 // WARNING: If you ever hit cherrypick conflicts here you're doing it wrong:
 // You are NOT allowed to cherrypick bpfloader related patches out of order.
 // (indeed: cherrypicking is probably a bad idea and you should merge instead)
 // Mainline supports ONLY the published versions of the bpfloader for each Android release.
 #define BPFLOADER_VERSION_MAJOR 0u
-#define BPFLOADER_VERSION_MINOR 40u
+#define BPFLOADER_VERSION_MINOR 41u
 #define BPFLOADER_VERSION ((BPFLOADER_VERSION_MAJOR << 16) | BPFLOADER_VERSION_MINOR)
 
 #include "BpfSyscallWrappers.h"
@@ -49,8 +49,6 @@
 #error "BPFLOADER_VERSION is less than COMPILE_FOR_BPFLOADER_VERSION"
 #endif
 
-#include <bpf/bpf.h>
-
 #include <cstdlib>
 #include <fstream>
 #include <iostream>
@@ -614,81 +612,6 @@
     return getSymName(elfFile, symtab[index].st_name, name);
 }
 
-static bool waitpidTimeout(pid_t pid, int timeoutMs) {
-    // Add SIGCHLD to the signal set.
-    sigset_t child_mask, original_mask;
-    sigemptyset(&child_mask);
-    sigaddset(&child_mask, SIGCHLD);
-    if (sigprocmask(SIG_BLOCK, &child_mask, &original_mask) == -1) return false;
-
-    // Wait for a SIGCHLD notification.
-    errno = 0;
-    timespec ts = {0, timeoutMs * 1000000};
-    int wait_result = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, nullptr, &ts));
-
-    // Restore the original signal set.
-    sigprocmask(SIG_SETMASK, &original_mask, nullptr);
-
-    if (wait_result == -1) return false;
-
-    int status;
-    return TEMP_FAILURE_RETRY(waitpid(pid, &status, WNOHANG)) == pid;
-}
-
-static std::optional<unique_fd> getMapBtfInfo(const char* elfPath,
-                         std::unordered_map<string, std::pair<uint32_t, uint32_t>> &btfTypeIds) {
-    unique_fd bpfloaderSocket, btfloaderSocket;
-    if (!android::base::Socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, &bpfloaderSocket,
-                                   &btfloaderSocket)) {
-        return {};
-    }
-
-    unique_fd pipeRead, pipeWrite;
-    if (!android::base::Pipe(&pipeRead, &pipeWrite, O_NONBLOCK)) {
-        return {};
-    }
-
-    pid_t pid = fork();
-    if (pid < 0) return {};
-    if (!pid) {
-        bpfloaderSocket.reset();
-        pipeRead.reset();
-        auto socketFdStr = std::to_string(btfloaderSocket.release());
-        auto pipeFdStr = std::to_string(pipeWrite.release());
-
-        if (execl("/system/bin/btfloader", "/system/bin/btfloader", socketFdStr.c_str(),
-                  pipeFdStr.c_str(), elfPath, NULL) == -1) {
-            ALOGW("exec btfloader failed with errno %d (%s)", errno, strerror(errno));
-            exit(EX_UNAVAILABLE);
-        }
-    }
-    btfloaderSocket.reset();
-    pipeWrite.reset();
-    if (!waitpidTimeout(pid, 100)) {
-        kill(pid, SIGKILL);
-        return {};
-    }
-
-    unique_fd btfFd;
-    if (android::base::ReceiveFileDescriptors(bpfloaderSocket, nullptr, 0, &btfFd)) return {};
-
-    std::string btfTypeIdStr;
-    if (!android::base::ReadFdToString(pipeRead, &btfTypeIdStr)) return {};
-    if (!btfFd.ok()) return {};
-
-    const auto mapTypeIdLines = android::base::Split(btfTypeIdStr, "\n");
-    for (const auto &line : mapTypeIdLines) {
-        const auto vec = android::base::Split(line, " ");
-        // Splitting on newline will give us one empty line
-        if (vec.size() != 3) continue;
-        const int kTid = atoi(vec[1].c_str());
-        const int vTid = atoi(vec[2].c_str());
-        if (!kTid || !vTid) return {};
-        btfTypeIds[vec[0]] = std::make_pair(kTid, vTid);
-    }
-    return btfFd;
-}
-
 static bool mapMatchesExpectations(const unique_fd& fd, const string& mapName,
                                    const struct bpf_map_def& mapDef, const enum bpf_map_type type) {
     // Assuming fd is a valid Bpf Map file descriptor then
@@ -741,10 +664,9 @@
                       const char* prefix, const unsigned long long allowedDomainBitmask,
                       const size_t sizeOfBpfMapDef) {
     int ret;
-    vector<char> mdData, btfData;
+    vector<char> mdData;
     vector<struct bpf_map_def> md;
     vector<string> mapNames;
-    std::unordered_map<string, std::pair<uint32_t, uint32_t>> btfTypeIdMap;
     string objName = pathToObjName(string(elfPath));
 
     ret = readSectionByName("maps", elfFile, mdData);
@@ -777,19 +699,8 @@
     ret = getSectionSymNames(elfFile, "maps", mapNames);
     if (ret) return ret;
 
-    // BpfLoader before v0.39 unconditionally check only 'btf_min_bpfloader_ver'
-    unsigned btfMinBpfLoaderVer = readSectionUint(
-        isUser() ? "btf_user_min_bpfloader_ver" : "btf_min_bpfloader_ver", elfFile, 0);
-
-    unsigned btfMinKernelVer = readSectionUint("btf_min_kernel_ver", elfFile, 0);
     unsigned kvers = kernelVersion();
 
-    std::optional<unique_fd> btfFd;
-    if ((BPFLOADER_VERSION >= btfMinBpfLoaderVer) && (kvers >= btfMinKernelVer) &&
-        (!readSectionByName(".BTF", elfFile, btfData))) {
-        btfFd = getMapBtfInfo(elfPath, btfTypeIdMap);
-    }
-
     for (int i = 0; i < (int)mapNames.size(); i++) {
         if (md[i].zero != 0) abort();
 
@@ -899,20 +810,15 @@
             ALOGD("bpf_create_map reusing map %s, ret: %d", mapNames[i].c_str(), fd.get());
             reuse = true;
         } else {
-            struct bpf_create_map_attr attr = {
-                .name = mapNames[i].c_str(),
-                .map_type = type,
-                .map_flags = md[i].map_flags,
-                .key_size = md[i].key_size,
-                .value_size = md[i].value_size,
-                .max_entries = max_entries,
+            union bpf_attr req = {
+              .map_type = type,
+              .key_size = md[i].key_size,
+              .value_size = md[i].value_size,
+              .max_entries = max_entries,
+              .map_flags = md[i].map_flags,
             };
-            if (btfFd.has_value() && btfTypeIdMap.find(mapNames[i]) != btfTypeIdMap.end()) {
-                attr.btf_fd = btfFd->get();
-                attr.btf_key_type_id = btfTypeIdMap.at(mapNames[i]).first;
-                attr.btf_value_type_id = btfTypeIdMap.at(mapNames[i]).second;
-            }
-            fd.reset(bcc_create_map_xattr(&attr, true));
+            strlcpy(req.map_name, mapNames[i].c_str(), sizeof(req.map_name));
+            fd.reset(bpf(BPF_MAP_CREATE, req));
             saved_errno = errno;
             ALOGD("bpf_create_map name %s, ret: %d", mapNames[i].c_str(), fd.get());
         }
@@ -928,7 +834,7 @@
             if (specified(selinux_context)) {
                 string createLoc = string(BPF_FS_PATH) + lookupPinSubdir(selinux_context) +
                                    "tmp_map_" + objName + "_" + mapNames[i];
-                ret = bpf_obj_pin(fd, createLoc.c_str());
+                ret = bpfFdPin(fd, createLoc.c_str());
                 if (ret) {
                     int err = errno;
                     ALOGE("create %s -> %d [%d:%s]", createLoc.c_str(), ret, err, strerror(err));
@@ -943,7 +849,7 @@
                     return -err;
                 }
             } else {
-                ret = bpf_obj_pin(fd, mapPinLoc.c_str());
+                ret = bpfFdPin(fd, mapPinLoc.c_str());
                 if (ret) {
                     int err = errno;
                     ALOGE("pin %s -> %d [%d:%s]", mapPinLoc.c_str(), ret, err, strerror(err));
@@ -966,13 +872,11 @@
             }
         }
 
-        struct bpf_map_info map_info = {};
-        __u32 map_info_len = sizeof(map_info);
-        int rv = bpf_obj_get_info_by_fd(fd, &map_info, &map_info_len);
-        if (rv) {
-            ALOGE("bpf_obj_get_info_by_fd failed, ret: %d [%d]", rv, errno);
+        int mapId = bpfGetFdMapId(fd);
+        if (mapId == -1) {
+            ALOGE("bpfGetFdMapId failed, ret: %d [%d]", mapId, errno);
         } else {
-            ALOGI("map %s id %d", mapPinLoc.c_str(), map_info.id);
+            ALOGI("map %s id %d", mapPinLoc.c_str(), mapId);
         }
 
         mapFds.push_back(std::move(fd));
@@ -1059,7 +963,6 @@
 static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const string& license,
                             const char* prefix, const unsigned long long allowedDomainBitmask) {
     unsigned kvers = kernelVersion();
-    int ret, fd;
 
     if (!kvers) {
         ALOGE("unable to get kernel version");
@@ -1069,6 +972,8 @@
     string objName = pathToObjName(string(elfPath));
 
     for (int i = 0; i < (int)cs.size(); i++) {
+        unique_fd& fd = cs[i].prog_fd;
+        int ret;
         string name = cs[i].name;
 
         if (!cs[i].prog_def.has_value()) {
@@ -1146,34 +1051,36 @@
         string progPinLoc = string(BPF_FS_PATH) + lookupPinSubdir(pin_subdir, prefix) + "prog_" +
                             objName + '_' + string(name);
         if (access(progPinLoc.c_str(), F_OK) == 0) {
-            fd = retrieveProgram(progPinLoc.c_str());
-            ALOGD("New bpf prog load reusing prog %s, ret: %d (%s)", progPinLoc.c_str(), fd,
-                  (fd < 0 ? std::strerror(errno) : "no error"));
+            fd.reset(retrieveProgram(progPinLoc.c_str()));
+            ALOGD("New bpf prog load reusing prog %s, ret: %d (%s)", progPinLoc.c_str(), fd.get(),
+                  (!fd.ok() ? std::strerror(errno) : "no error"));
             reuse = true;
         } else {
             vector<char> log_buf(BPF_LOAD_LOG_SZ, 0);
 
-            struct bpf_load_program_attr attr = {
-                .prog_type = cs[i].type,
-                .name = name.c_str(),
-                .insns = (struct bpf_insn*)cs[i].data.data(),
-                .license = license.c_str(),
-                .log_level = 0,
-                .expected_attach_type = cs[i].expected_attach_type,
+            union bpf_attr req = {
+              .prog_type = cs[i].type,
+              .kern_version = kvers,
+              .license = ptr_to_u64(license.c_str()),
+              .insns = ptr_to_u64(cs[i].data.data()),
+              .insn_cnt = static_cast<__u32>(cs[i].data.size() / sizeof(struct bpf_insn)),
+              .log_level = 1,
+              .log_buf = ptr_to_u64(log_buf.data()),
+              .log_size = static_cast<__u32>(log_buf.size()),
+              .expected_attach_type = cs[i].expected_attach_type,
             };
+            strlcpy(req.prog_name, cs[i].name.c_str(), sizeof(req.prog_name));
+            fd.reset(bpf(BPF_PROG_LOAD, req));
 
-            fd = bcc_prog_load_xattr(&attr, cs[i].data.size(), log_buf.data(), log_buf.size(),
-                    true);
+            ALOGD("BPF_PROG_LOAD call for %s (%s) returned fd: %d (%s)", elfPath,
+                  cs[i].name.c_str(), fd.get(), (!fd.ok() ? std::strerror(errno) : "no error"));
 
-            ALOGD("bpf_prog_load lib call for %s (%s) returned fd: %d (%s)", elfPath,
-                  cs[i].name.c_str(), fd, (fd < 0 ? std::strerror(errno) : "no error"));
-
-            if (fd < 0) {
+            if (!fd.ok()) {
                 vector<string> lines = android::base::Split(log_buf.data(), "\n");
 
-                ALOGW("bpf_prog_load - BEGIN log_buf contents:");
+                ALOGW("BPF_PROG_LOAD - BEGIN log_buf contents:");
                 for (const auto& line : lines) ALOGW("%s", line.c_str());
-                ALOGW("bpf_prog_load - END log_buf contents.");
+                ALOGW("BPF_PROG_LOAD - END log_buf contents.");
 
                 if (cs[i].prog_def->optional) {
                     ALOGW("failed program is marked optional - continuing...");
@@ -1183,14 +1090,13 @@
             }
         }
 
-        if (fd < 0) return fd;
-        if (fd == 0) return -EINVAL;
+        if (!fd.ok()) return fd.get();
 
         if (!reuse) {
             if (specified(selinux_context)) {
                 string createLoc = string(BPF_FS_PATH) + lookupPinSubdir(selinux_context) +
                                    "tmp_prog_" + objName + '_' + string(name);
-                ret = bpf_obj_pin(fd, createLoc.c_str());
+                ret = bpfFdPin(fd, createLoc.c_str());
                 if (ret) {
                     int err = errno;
                     ALOGE("create %s -> %d [%d:%s]", createLoc.c_str(), ret, err, strerror(err));
@@ -1205,7 +1111,7 @@
                     return -err;
                 }
             } else {
-                ret = bpf_obj_pin(fd, progPinLoc.c_str());
+                ret = bpfFdPin(fd, progPinLoc.c_str());
                 if (ret) {
                     int err = errno;
                     ALOGE("create %s -> %d [%d:%s]", progPinLoc.c_str(), ret, err, strerror(err));
@@ -1226,16 +1132,12 @@
             }
         }
 
-        struct bpf_prog_info prog_info = {};
-        __u32 prog_info_len = sizeof(prog_info);
-        int rv = bpf_obj_get_info_by_fd(fd, &prog_info, &prog_info_len);
-        if (rv) {
-            ALOGE("bpf_obj_get_info_by_fd failed, ret: %d [%d]", rv, errno);
+        int progId = bpfGetFdProgId(fd);
+        if (progId == -1) {
+            ALOGE("bpfGetFdProgId failed, ret: %d [%d]", progId, errno);
         } else {
-            ALOGI("prog %s id %d", progPinLoc.c_str(), prog_info.id);
+            ALOGI("prog %s id %d", progPinLoc.c_str(), progId);
         }
-
-        cs[i].prog_fd.reset(fd);
     }
 
     return 0;
diff --git a/libbpf_android/include/libbpf_android.h b/libbpf_android/include/libbpf_android.h
index 31bd539..cc8a942 100644
--- a/libbpf_android/include/libbpf_android.h
+++ b/libbpf_android/include/libbpf_android.h
@@ -17,7 +17,6 @@
 
 #pragma once
 
-#include <libbpf.h>
 #include <linux/bpf.h>
 
 #include <fstream>