add support for marking ebpf programs as being only for some kernel versions
Some ebpf code cannot be loaded on too old kernels. Sometimes we want a different - more advanced - version of an ebpf program to be loaded on a newer kernel. Test: build, atest Signed-off-by: Maciej Żenczykowski <maze@google.com> Change-Id: I9e93e7246951916e6d60544575337a7a19c82886
This commit is contained in:
parent
cd994cd637
commit
07375e26a3
6 changed files with 57 additions and 61 deletions
|
|
@ -96,6 +96,24 @@ int setrlimitForTest() {
|
|||
return res;
|
||||
}
|
||||
|
||||
#define KVER(a, b, c) ((a)*65536 + (b)*256 + (c))
|
||||
|
||||
unsigned kernelVersion() {
|
||||
struct utsname buf;
|
||||
int ret = uname(&buf);
|
||||
if (ret) return 0;
|
||||
|
||||
unsigned kver_major;
|
||||
unsigned kver_minor;
|
||||
unsigned kver_sub;
|
||||
char dummy;
|
||||
ret = sscanf(buf.release, "%u.%u.%u%c", &kver_major, &kver_minor, &kver_sub, &dummy);
|
||||
// Check the device kernel version
|
||||
if (ret < 3) return 0;
|
||||
|
||||
return KVER(kver_major, kver_minor, kver_sub);
|
||||
}
|
||||
|
||||
std::string BpfLevelToString(BpfLevel bpfLevel) {
|
||||
switch (bpfLevel) {
|
||||
case BpfLevel::NONE:
|
||||
|
|
@ -123,23 +141,12 @@ static BpfLevel getUncachedBpfSupportLevel() {
|
|||
// Check if the device is shipped originally with android P.
|
||||
if (api_level < MINIMUM_API_REQUIRED) return BpfLevel::NONE;
|
||||
|
||||
struct utsname buf;
|
||||
int ret = uname(&buf);
|
||||
if (ret) return BpfLevel::NONE;
|
||||
unsigned kver = kernelVersion();
|
||||
|
||||
int kernel_version_major;
|
||||
int kernel_version_minor;
|
||||
char dummy;
|
||||
ret = sscanf(buf.release, "%d.%d%c", &kernel_version_major, &kernel_version_minor, &dummy);
|
||||
// Check the device kernel version
|
||||
if (ret < 2) return BpfLevel::NONE;
|
||||
|
||||
if (kernel_version_major > 5) return BpfLevel::EXTENDED_5_4;
|
||||
if (kernel_version_major == 5 && kernel_version_minor >= 4) return BpfLevel::EXTENDED_5_4;
|
||||
if (kernel_version_major == 5) return BpfLevel::EXTENDED_4_19;
|
||||
if (kernel_version_major == 4 && kernel_version_minor >= 19) return BpfLevel::EXTENDED_4_19;
|
||||
if (kernel_version_major == 4 && kernel_version_minor >= 14) return BpfLevel::EXTENDED_4_14;
|
||||
if (kernel_version_major == 4 && kernel_version_minor >= 9) return BpfLevel::BASIC_4_9;
|
||||
if (kver >= KVER(5, 4, 0)) return BpfLevel::EXTENDED_5_4;
|
||||
if (kver >= KVER(4, 19, 0)) return BpfLevel::EXTENDED_4_19;
|
||||
if (kver >= KVER(4, 14, 0)) return BpfLevel::EXTENDED_4_14;
|
||||
if (kver >= KVER(4, 9, 0)) return BpfLevel::BASIC_4_9;
|
||||
|
||||
return BpfLevel::NONE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "../progs/include/bpf_map_def.h"
|
||||
#include "LoaderUtils.h"
|
||||
#include "bpf/BpfUtils.h"
|
||||
#include "include/libbpf_android.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
|
@ -531,9 +532,10 @@ static void applyMapRelo(ifstream& elfFile, vector<unique_fd> &mapFds, vector<co
|
|||
}
|
||||
|
||||
static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const string& license) {
|
||||
int ret, fd, kvers;
|
||||
unsigned kvers = kernelVersion();
|
||||
int ret, fd;
|
||||
|
||||
if ((kvers = getMachineKvers()) < 0) return -1;
|
||||
if (!kvers) return -1;
|
||||
|
||||
string fname = pathToFilename(string(elfPath), true);
|
||||
|
||||
|
|
@ -541,6 +543,11 @@ static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const
|
|||
string progPinLoc;
|
||||
bool reuse = false;
|
||||
|
||||
if (cs[i].prog_def.has_value()) {
|
||||
if (kvers < cs[i].prog_def->min_kver) continue;
|
||||
if (kvers >= cs[i].prog_def->max_kver) continue;
|
||||
}
|
||||
|
||||
// Format of pin location is
|
||||
// /sys/fs/bpf/prog_<filename>_<mapname>
|
||||
progPinLoc = string(BPF_FS_PATH) + "prog_" + fname + "_" + cs[i].name;
|
||||
|
|
|
|||
|
|
@ -32,43 +32,6 @@ static std::string pathToFilename(const std::string& path, bool noext = false) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int getMachineKvers(void) {
|
||||
struct utsname un;
|
||||
char* unameOut;
|
||||
int nums[3]; // maj, min, sub
|
||||
|
||||
if (uname(&un)) return -1;
|
||||
unameOut = un.release;
|
||||
|
||||
std::string s = unameOut;
|
||||
std::string token;
|
||||
size_t pos = 0;
|
||||
int cur_num = 0;
|
||||
|
||||
while ((pos = s.find('.')) != std::string::npos && cur_num < 3) {
|
||||
token = s.substr(0, pos);
|
||||
s.erase(0, pos + 1);
|
||||
|
||||
if ((pos = token.find('-')) != std::string::npos) token = token.substr(0, pos);
|
||||
|
||||
nums[cur_num++] = stoi(token);
|
||||
}
|
||||
|
||||
if ((pos = s.find('-')) != std::string::npos)
|
||||
token = s.substr(0, pos);
|
||||
else
|
||||
token = s;
|
||||
|
||||
if (token.length() > 0 && cur_num < 3) {
|
||||
nums[cur_num++] = stoi(token);
|
||||
}
|
||||
|
||||
if (cur_num != 3)
|
||||
return -1;
|
||||
else
|
||||
return (65536 * nums[0] + 256 * nums[1] + nums[2]);
|
||||
}
|
||||
|
||||
static void deslash(std::string& s) {
|
||||
std::replace(s.begin(), s.end(), '/', '_');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ inline int detachProgram(bpf_attach_type type, const base::unique_fd& cg_fd) {
|
|||
uint64_t getSocketCookie(int sockFd);
|
||||
int synchronizeKernelRCU();
|
||||
int setrlimitForTest();
|
||||
unsigned kernelVersion();
|
||||
std::string BpfLevelToString(BpfLevel BpfLevel);
|
||||
BpfLevel getBpfSupportLevel();
|
||||
|
||||
|
|
|
|||
|
|
@ -98,10 +98,25 @@ static unsigned long long (*bpf_get_current_pid_tgid)(void) = (void*) BPF_FUNC_g
|
|||
static unsigned long long (*bpf_get_current_uid_gid)(void) = (void*) BPF_FUNC_get_current_uid_gid;
|
||||
static unsigned long long (*bpf_get_smp_processor_id)(void) = (void*) BPF_FUNC_get_smp_processor_id;
|
||||
|
||||
#define DEFINE_BPF_PROG(SECTION_NAME, prog_uid, prog_gid, the_prog) \
|
||||
const struct bpf_prog_def SEC("progs") the_prog##_def = { \
|
||||
.uid = (prog_uid), \
|
||||
.gid = (prog_gid), \
|
||||
}; \
|
||||
SEC(SECTION_NAME) \
|
||||
#define KVER_NONE 0
|
||||
#define KVER(a, b, c) ((a)*65536 + (b)*256 + (c))
|
||||
#define KVER_INF 0xFFFFFFFF
|
||||
|
||||
// programs requiring a kernel version >= min_kv && < max_kv
|
||||
#define DEFINE_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv) \
|
||||
const struct bpf_prog_def SEC("progs") the_prog##_def = { \
|
||||
.uid = (prog_uid), \
|
||||
.gid = (prog_gid), \
|
||||
.min_kver = (min_kv), \
|
||||
.max_kver = (max_kv), \
|
||||
}; \
|
||||
SEC(SECTION_NAME) \
|
||||
int the_prog
|
||||
|
||||
// programs requiring a kernel version >= min_kv
|
||||
#define DEFINE_BPF_PROG_KVER(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv) \
|
||||
DEFINE_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, KVER_INF)
|
||||
|
||||
// programs with no kernel version requirements
|
||||
#define DEFINE_BPF_PROG(SECTION_NAME, prog_uid, prog_gid, the_prog) \
|
||||
DEFINE_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, 0, KVER_INF)
|
||||
|
|
|
|||
|
|
@ -57,4 +57,7 @@ struct bpf_map_def {
|
|||
struct bpf_prog_def {
|
||||
unsigned int uid;
|
||||
unsigned int gid;
|
||||
|
||||
unsigned int min_kver; // KERNEL_MAJOR * 65536 + KERNEL_MINOR * 256 + KERNEL_SUB
|
||||
unsigned int max_kver; // ie. 0x40900 for Linux 4.9 - but beware of hexadecimal for >= 10
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue