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
This commit is contained in:
Tyler Wear 2022-02-03 09:46:01 -08:00
commit 4e2f4608c0

View file

@ -30,9 +30,9 @@
#include <sys/wait.h>
#include <unistd.h>
// 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<char> data;
vector<char> 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<struct bpf_prog_def>& pd,
size_t sizeOfBpfProgDef) {
vector<char> pdData;
@ -426,27 +426,30 @@ static int readCodeSections(ifstream& elfFile, vector<codeSection>& 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<string> 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<string> 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<codeSection>& 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<codeSection>& cs, const
} else {
vector<char> 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"));