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:
Maciej Żenczykowski 2021-01-14 23:36:32 -08:00
parent da5d7ec6a7
commit d8a4578f30
3 changed files with 52 additions and 17 deletions

View file

@ -51,10 +51,23 @@
using android::base::EndsWith; using android::base::EndsWith;
using std::string; using std::string;
#define BPF_PROG_PATH_MAINLINE_TETHERING "/apex/com.android.tethering/etc/bpf/" struct {
#define BPF_PROG_PATH_SYSTEM "/system/etc/bpf/" 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; int retVal = 0;
DIR* dir; DIR* dir;
struct dirent* ent; struct dirent* ent;
@ -68,7 +81,7 @@ int loadAllElfObjects(const char* progDir) {
progPath += s; progPath += s;
bool critical; bool critical;
int ret = android::bpf::loadProg(progPath.c_str(), &critical); int ret = android::bpf::loadProg(progPath.c_str(), &critical, prefix);
if (ret) { if (ret) {
if (critical) retVal = ret; if (critical) retVal = ret;
ALOGE("Failed to load object: %s, ret: %s", progPath.c_str(), std::strerror(-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; 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() { int main() {
// Load all ELF objects, create programs and maps, and pin them // Load all ELF objects, create programs and maps, and pin them
for (const auto dir : {BPF_PROG_PATH_MAINLINE_TETHERING, BPF_PROG_PATH_SYSTEM}) { for (const auto location : locations) {
if (loadAllElfObjects(dir) != 0) { createSysFsBpfSubDir(location.prefix);
ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS FROM %s ===", dir); 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 reliably, you're probably missing kernel options or patches.");
ALOGE("If this triggers randomly, you might be hitting some memory allocation " ALOGE("If this triggers randomly, you might be hitting some memory allocation "
"problems or startup script race."); "problems or startup script race.");

View file

@ -403,7 +403,8 @@ static int getSymNameByIdx(ifstream& elfFile, int index, string& name) {
return getSymName(elfFile, symtab[index].st_name, 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; int ret;
vector<char> mdData; vector<char> mdData;
vector<struct bpf_map_def> md; 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++) { for (int i = 0; i < (int)mapNames.size(); i++) {
unique_fd fd; 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; string mapPinLoc;
bool reuse = false; 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) { if (access(mapPinLoc.c_str(), F_OK) == 0) {
fd.reset(bpf_obj_get(mapPinLoc.c_str())); fd.reset(bpf_obj_get(mapPinLoc.c_str()));
ALOGD("bpf_create_map reusing map %s, ret: %d\n", mapNames[i].c_str(), fd.get()); 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(); unsigned kvers = kernelVersion();
int ret, fd; int ret, fd;
@ -554,8 +556,10 @@ static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const
bool reuse = false; bool reuse = false;
// Format of pin location is // Format of pin location is
// /sys/fs/bpf/prog_<filename>_<mapname> // /sys/fs/bpf/<prefix>prog_<filename>_<mapname>
string progPinLoc = BPF_FS_PATH "prog_"; string progPinLoc = BPF_FS_PATH;
progPinLoc += prefix;
progPinLoc += "prog_";
progPinLoc += fname; progPinLoc += fname;
progPinLoc += '_'; progPinLoc += '_';
progPinLoc += name; progPinLoc += name;
@ -609,7 +613,7 @@ static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const
return 0; return 0;
} }
int loadProg(const char* elfPath, bool* isCritical) { int loadProg(const char* elfPath, bool* isCritical, const char* prefix) {
vector<char> license; vector<char> license;
vector<char> critical; vector<char> critical;
vector<codeSection> cs; vector<codeSection> cs;
@ -644,7 +648,7 @@ int loadProg(const char* elfPath, bool* isCritical) {
/* Just for future debugging */ /* Just for future debugging */
if (0) dumpAllCs(cs); if (0) dumpAllCs(cs);
ret = createMaps(elfPath, elfFile, mapFds); ret = createMaps(elfPath, elfFile, mapFds, prefix);
if (ret) { if (ret) {
ALOGE("Failed to create maps: (ret=%d) in %s\n", ret, elfPath); ALOGE("Failed to create maps: (ret=%d) in %s\n", ret, elfPath);
return ret; return ret;
@ -655,7 +659,7 @@ int loadProg(const char* elfPath, bool* isCritical) {
applyMapRelo(elfFile, mapFds, cs); 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); if (ret) ALOGE("Failed to load programs, loadCodeSections ret=%d\n", ret);
return ret; return ret;

View file

@ -25,7 +25,7 @@ namespace android {
namespace bpf { namespace bpf {
// BPF loader implementation. Loads an eBPF ELF object // 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. // Wait for bpfloader to load BPF programs.
void waitForProgsLoaded(); void waitForProgsLoaded();