From 4e2f4608c032ddd53cce74d07e4e700084eae8f8 Mon Sep 17 00:00:00 2001 From: Tyler Wear Date: Thu, 3 Feb 2022 09:46:01 -0800 Subject: [PATCH] Load Bpf Program With Expected Attach Type Move to bcc_prog_load_xattr() so that expected attach type can be passed in when loading program. Change-Id: I72533dd8805fa75287e12e828ee12315c0f8cd2d --- libbpf_android/Loader.cpp | 100 +++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp index eb48cd0..fd223a2 100644 --- a/libbpf_android/Loader.cpp +++ b/libbpf_android/Loader.cpp @@ -30,9 +30,9 @@ #include #include -// This is BpfLoader v0.9 +// This is BpfLoader v0.10 #define BPFLOADER_VERSION_MAJOR 0u -#define BPFLOADER_VERSION_MINOR 9u +#define BPFLOADER_VERSION_MINOR 10u #define BPFLOADER_VERSION ((BPFLOADER_VERSION_MAJOR << 16) | BPFLOADER_VERSION_MINOR) #include "bpf/BpfUtils.h" @@ -59,6 +59,9 @@ // Size of the BPF log buffer for verifier logging #define BPF_LOAD_LOG_SZ 0xfffff +// Unspecified attach type is 0 which is BPF_CGROUP_INET_INGRESS. +#define BPF_ATTACH_TYPE_UNSPEC BPF_CGROUP_INET_INGRESS + using android::base::StartsWith; using android::base::unique_fd; using std::ifstream; @@ -84,6 +87,7 @@ static string pathToFilename(const string& path, bool noext = false) { typedef struct { const char* name; enum bpf_prog_type type; + enum bpf_attach_type expected_attach_type; } sectionType; /* @@ -97,19 +101,21 @@ typedef struct { * Instead use the DEFINE_(BPF|XDP)_(PROG|MAP)... & LICENSE/CRITICAL macros. */ sectionType sectionNameTypes[] = { - {"cgroupskb/", BPF_PROG_TYPE_CGROUP_SKB}, - {"cgroupsock/", BPF_PROG_TYPE_CGROUP_SOCK}, - {"cgroupsockaddr/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR}, - {"kprobe/", BPF_PROG_TYPE_KPROBE}, - {"schedact/", BPF_PROG_TYPE_SCHED_ACT}, - {"schedcls/", BPF_PROG_TYPE_SCHED_CLS}, - {"skfilter/", BPF_PROG_TYPE_SOCKET_FILTER}, - {"tracepoint/", BPF_PROG_TYPE_TRACEPOINT}, - {"xdp/", BPF_PROG_TYPE_XDP}, + {"bind4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND}, + {"bind6/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND}, + {"cgroupskb/", BPF_PROG_TYPE_CGROUP_SKB, BPF_ATTACH_TYPE_UNSPEC}, + {"cgroupsock/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_ATTACH_TYPE_UNSPEC}, + {"kprobe/", BPF_PROG_TYPE_KPROBE, BPF_ATTACH_TYPE_UNSPEC}, + {"schedact/", BPF_PROG_TYPE_SCHED_ACT, BPF_ATTACH_TYPE_UNSPEC}, + {"schedcls/", BPF_PROG_TYPE_SCHED_CLS, BPF_ATTACH_TYPE_UNSPEC}, + {"skfilter/", BPF_PROG_TYPE_SOCKET_FILTER, BPF_ATTACH_TYPE_UNSPEC}, + {"tracepoint/", BPF_PROG_TYPE_TRACEPOINT, BPF_ATTACH_TYPE_UNSPEC}, + {"xdp/", BPF_PROG_TYPE_XDP, BPF_ATTACH_TYPE_UNSPEC}, }; typedef struct { enum bpf_prog_type type; + enum bpf_attach_type expected_attach_type; string name; vector data; vector rel_data; @@ -300,6 +306,12 @@ static enum bpf_prog_type getSectionType(string& name) { return BPF_PROG_TYPE_UNSPEC; } +static enum bpf_attach_type getExpectedAttachType(string& name) { + for (auto& snt : sectionNameTypes) + if (StartsWith(name, snt.name)) return snt.expected_attach_type; + return BPF_ATTACH_TYPE_UNSPEC; +} + /* If ever needed static string getSectionName(enum bpf_prog_type type) { @@ -311,18 +323,6 @@ static string getSectionName(enum bpf_prog_type type) } */ -static bool isRelSection(codeSection& cs, string& name) { - for (auto& snt : sectionNameTypes) { - if (snt.type != cs.type) continue; - - if (StartsWith(name, string(".rel") + snt.name)) - return true; - else - return false; - } - return false; -} - static int readProgDefs(ifstream& elfFile, vector& pd, size_t sizeOfBpfProgDef) { vector pdData; @@ -426,27 +426,30 @@ static int readCodeSections(ifstream& elfFile, vector& cs, size_t s if (ret) return ret; enum bpf_prog_type ptype = getSectionType(name); - if (ptype != BPF_PROG_TYPE_UNSPEC) { - string oldName = name; + if (ptype == BPF_PROG_TYPE_UNSPEC) continue; - // convert all slashes to underscores - std::replace(name.begin(), name.end(), '/', '_'); + // This must be done before '/' is replaced with '_'. + cs_temp.expected_attach_type = getExpectedAttachType(name); - cs_temp.type = ptype; - cs_temp.name = name; + string oldName = name; - ret = readSectionByIdx(elfFile, i, cs_temp.data); - if (ret) return ret; - ALOGD("Loaded code section %d (%s)\n", i, name.c_str()); + // convert all slashes to underscores + std::replace(name.begin(), name.end(), '/', '_'); - vector csSymNames; - ret = getSectionSymNames(elfFile, oldName, csSymNames, STT_FUNC); - if (ret || !csSymNames.size()) return ret; - for (size_t i = 0; i < progDefNames.size(); ++i) { - if (!progDefNames[i].compare(csSymNames[0] + "_def")) { - cs_temp.prog_def = pd[i]; - break; - } + cs_temp.type = ptype; + cs_temp.name = name; + + ret = readSectionByIdx(elfFile, i, cs_temp.data); + if (ret) return ret; + ALOGD("Loaded code section %d (%s)\n", i, name.c_str()); + + vector csSymNames; + ret = getSectionSymNames(elfFile, oldName, csSymNames, STT_FUNC); + if (ret || !csSymNames.size()) return ret; + for (size_t i = 0; i < progDefNames.size(); ++i) { + if (!progDefNames[i].compare(csSymNames[0] + "_def")) { + cs_temp.prog_def = pd[i]; + break; } } @@ -455,7 +458,7 @@ static int readCodeSections(ifstream& elfFile, vector& cs, size_t s ret = getSymName(elfFile, shTable[i + 1].sh_name, name); if (ret) return ret; - if (isRelSection(cs_temp, name)) { + if (name == (".rel" + oldName)) { ret = readSectionByIdx(elfFile, i + 1, cs_temp.rel_data); if (ret) return ret; ALOGD("Loaded relo section %d (%s)\n", i, name.c_str()); @@ -827,9 +830,18 @@ static int loadCodeSections(const char* elfPath, vector& cs, const } else { vector log_buf(BPF_LOAD_LOG_SZ, 0); - fd = bcc_prog_load(cs[i].type, name.c_str(), (struct bpf_insn*)cs[i].data.data(), - cs[i].data.size(), license.c_str(), kvers, 0, log_buf.data(), - log_buf.size()); + 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, + }; + + fd = bcc_prog_load_xattr(&attr, cs[i].data.size(), log_buf.data(), log_buf.size(), + true); + ALOGD("bpf_prog_load lib call for %s (%s) returned fd: %d (%s)\n", elfPath, cs[i].name.c_str(), fd, (fd < 0 ? std::strerror(errno) : "no error"));