put tethering bpf maps & programs in /sys/fs/bpf/tethering/...
This makes it harder for system and mainline bpf programs to conflict with each other, thus enabling easier mainline module updates. Test: builds and boots, atest, TreeHugger Signed-off-by: Maciej Żenczykowski <maze@google.com> Change-Id: Ic1b69bb1ddc4a10bd4861dadbd6b97e2520c532d
This commit is contained in:
parent
da5d7ec6a7
commit
d8a4578f30
3 changed files with 52 additions and 17 deletions
|
@ -51,10 +51,23 @@
|
|||
using android::base::EndsWith;
|
||||
using std::string;
|
||||
|
||||
#define BPF_PROG_PATH_MAINLINE_TETHERING "/apex/com.android.tethering/etc/bpf/"
|
||||
#define BPF_PROG_PATH_SYSTEM "/system/etc/bpf/"
|
||||
struct {
|
||||
const char* const dir;
|
||||
const char* const prefix;
|
||||
} locations[] = {
|
||||
// Tethering mainline module
|
||||
{
|
||||
.dir = "/apex/com.android.tethering/etc/bpf/",
|
||||
.prefix = "tethering/",
|
||||
},
|
||||
// Core operating system
|
||||
{
|
||||
.dir = "/system/etc/bpf/",
|
||||
.prefix = "",
|
||||
},
|
||||
};
|
||||
|
||||
int loadAllElfObjects(const char* progDir) {
|
||||
int loadAllElfObjects(const char* const progDir, const char* const prefix) {
|
||||
int retVal = 0;
|
||||
DIR* dir;
|
||||
struct dirent* ent;
|
||||
|
@ -68,7 +81,7 @@ int loadAllElfObjects(const char* progDir) {
|
|||
progPath += s;
|
||||
|
||||
bool critical;
|
||||
int ret = android::bpf::loadProg(progPath.c_str(), &critical);
|
||||
int ret = android::bpf::loadProg(progPath.c_str(), &critical, prefix);
|
||||
if (ret) {
|
||||
if (critical) retVal = ret;
|
||||
ALOGE("Failed to load object: %s, ret: %s", progPath.c_str(), std::strerror(-ret));
|
||||
|
@ -81,11 +94,29 @@ int loadAllElfObjects(const char* progDir) {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
void createSysFsBpfSubDir(const char* const prefix) {
|
||||
if (*prefix) {
|
||||
mode_t prevUmask = umask(0);
|
||||
|
||||
string s = "/sys/fs/bpf/";
|
||||
s += prefix;
|
||||
|
||||
errno = 0;
|
||||
int ret = mkdir(s.c_str(), S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
if (ret && errno != EEXIST) {
|
||||
ALOGW("Failed to create directory: %s, ret: %s", s.c_str(), std::strerror(errno));
|
||||
}
|
||||
|
||||
umask(prevUmask);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Load all ELF objects, create programs and maps, and pin them
|
||||
for (const auto dir : {BPF_PROG_PATH_MAINLINE_TETHERING, BPF_PROG_PATH_SYSTEM}) {
|
||||
if (loadAllElfObjects(dir) != 0) {
|
||||
ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS FROM %s ===", dir);
|
||||
for (const auto location : locations) {
|
||||
createSysFsBpfSubDir(location.prefix);
|
||||
if (loadAllElfObjects(location.dir, location.prefix) != 0) {
|
||||
ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS FROM %s ===", location.dir);
|
||||
ALOGE("If this triggers reliably, you're probably missing kernel options or patches.");
|
||||
ALOGE("If this triggers randomly, you might be hitting some memory allocation "
|
||||
"problems or startup script race.");
|
||||
|
|
|
@ -403,7 +403,8 @@ static int getSymNameByIdx(ifstream& elfFile, int index, string& name) {
|
|||
return getSymName(elfFile, symtab[index].st_name, name);
|
||||
}
|
||||
|
||||
static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>& mapFds) {
|
||||
static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>& mapFds,
|
||||
const char* prefix) {
|
||||
int ret;
|
||||
vector<char> mdData;
|
||||
vector<struct bpf_map_def> md;
|
||||
|
@ -421,11 +422,11 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>&
|
|||
|
||||
for (int i = 0; i < (int)mapNames.size(); i++) {
|
||||
unique_fd fd;
|
||||
// Format of pin location is /sys/fs/bpf/map_<filename>_<mapname>
|
||||
// Format of pin location is /sys/fs/bpf/<prefix>map_<filename>_<mapname>
|
||||
string mapPinLoc;
|
||||
bool reuse = false;
|
||||
|
||||
mapPinLoc = string(BPF_FS_PATH) + "map_" + fname + "_" + string(mapNames[i]);
|
||||
mapPinLoc = string(BPF_FS_PATH) + prefix + "map_" + fname + "_" + string(mapNames[i]);
|
||||
if (access(mapPinLoc.c_str(), F_OK) == 0) {
|
||||
fd.reset(bpf_obj_get(mapPinLoc.c_str()));
|
||||
ALOGD("bpf_create_map reusing map %s, ret: %d\n", mapNames[i].c_str(), fd.get());
|
||||
|
@ -527,7 +528,8 @@ static void applyMapRelo(ifstream& elfFile, vector<unique_fd> &mapFds, vector<co
|
|||
}
|
||||
}
|
||||
|
||||
static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const string& license) {
|
||||
static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const string& license,
|
||||
const char* prefix) {
|
||||
unsigned kvers = kernelVersion();
|
||||
int ret, fd;
|
||||
|
||||
|
@ -554,8 +556,10 @@ static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const
|
|||
|
||||
bool reuse = false;
|
||||
// Format of pin location is
|
||||
// /sys/fs/bpf/prog_<filename>_<mapname>
|
||||
string progPinLoc = BPF_FS_PATH "prog_";
|
||||
// /sys/fs/bpf/<prefix>prog_<filename>_<mapname>
|
||||
string progPinLoc = BPF_FS_PATH;
|
||||
progPinLoc += prefix;
|
||||
progPinLoc += "prog_";
|
||||
progPinLoc += fname;
|
||||
progPinLoc += '_';
|
||||
progPinLoc += name;
|
||||
|
@ -609,7 +613,7 @@ static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
int loadProg(const char* elfPath, bool* isCritical) {
|
||||
int loadProg(const char* elfPath, bool* isCritical, const char* prefix) {
|
||||
vector<char> license;
|
||||
vector<char> critical;
|
||||
vector<codeSection> cs;
|
||||
|
@ -644,7 +648,7 @@ int loadProg(const char* elfPath, bool* isCritical) {
|
|||
/* Just for future debugging */
|
||||
if (0) dumpAllCs(cs);
|
||||
|
||||
ret = createMaps(elfPath, elfFile, mapFds);
|
||||
ret = createMaps(elfPath, elfFile, mapFds, prefix);
|
||||
if (ret) {
|
||||
ALOGE("Failed to create maps: (ret=%d) in %s\n", ret, elfPath);
|
||||
return ret;
|
||||
|
@ -655,7 +659,7 @@ int loadProg(const char* elfPath, bool* isCritical) {
|
|||
|
||||
applyMapRelo(elfFile, mapFds, cs);
|
||||
|
||||
ret = loadCodeSections(elfPath, cs, string(license.data()));
|
||||
ret = loadCodeSections(elfPath, cs, string(license.data()), prefix);
|
||||
if (ret) ALOGE("Failed to load programs, loadCodeSections ret=%d\n", ret);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace android {
|
|||
namespace bpf {
|
||||
|
||||
// BPF loader implementation. Loads an eBPF ELF object
|
||||
int loadProg(const char* elfPath, bool* isCritical);
|
||||
int loadProg(const char* elfPath, bool* isCritical, const char* prefix = "");
|
||||
|
||||
// Wait for bpfloader to load BPF programs.
|
||||
void waitForProgsLoaded();
|
||||
|
|
Loading…
Reference in a new issue