diff --git a/bpfloader/BpfLoader.cpp b/bpfloader/BpfLoader.cpp index 9bc6451..7a68894 100644 --- a/bpfloader/BpfLoader.cpp +++ b/bpfloader/BpfLoader.cpp @@ -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."); diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp index e61f460..05a5067 100644 --- a/libbpf_android/Loader.cpp +++ b/libbpf_android/Loader.cpp @@ -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& mapFds) { +static int createMaps(const char* elfPath, ifstream& elfFile, vector& mapFds, + const char* prefix) { int ret; vector mdData; vector md; @@ -421,11 +422,11 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector& for (int i = 0; i < (int)mapNames.size(); i++) { unique_fd fd; - // Format of pin location is /sys/fs/bpf/map__ + // Format of pin location is /sys/fs/bpf/map__ 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 &mapFds, vector& cs, const string& license) { +static int loadCodeSections(const char* elfPath, vector& cs, const string& license, + const char* prefix) { unsigned kvers = kernelVersion(); int ret, fd; @@ -554,8 +556,10 @@ static int loadCodeSections(const char* elfPath, vector& cs, const bool reuse = false; // Format of pin location is - // /sys/fs/bpf/prog__ - string progPinLoc = BPF_FS_PATH "prog_"; + // /sys/fs/bpf/prog__ + 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& cs, const return 0; } -int loadProg(const char* elfPath, bool* isCritical) { +int loadProg(const char* elfPath, bool* isCritical, const char* prefix) { vector license; vector critical; vector 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; diff --git a/libbpf_android/include/libbpf_android.h b/libbpf_android/include/libbpf_android.h index 3810d07..a2f78b4 100644 --- a/libbpf_android/include/libbpf_android.h +++ b/libbpf_android/include/libbpf_android.h @@ -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();