From 681f604b2ef769737eef16b48e3a53967fa1d6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Tue, 21 Apr 2020 15:34:18 -0700 Subject: [PATCH] bpf loader - finish support for kernel version conditional loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bpf program section names must be unique to prevent programs from appending to each other, so instead the bpf loader will strip everything past the final $ symbol when actually pinning the program into the filesystem. While at it add a little bit more logging. Example on aosp cuttlefish 5.4.30 virtual device: D LibBpfLoader: bpf_prog_load lib call for /system/etc/bpf/offload.o (schedcls_ingress_tether_ether) returned fd: 8 (no error) D LibBpfLoader: cs[1].name:schedcls_ingress_tether_rawip$stub min_kver:0 .max_kver:40e00 (kvers:5041e) D LibBpfLoader: cs[2].name:schedcls_ingress_tether_rawip$4_14 min_kver:40e00 .max_kver:ffffffff (kvers:5041e) D LibBpfLoader: bpf_prog_load lib call for /system/etc/bpf/offload.o (schedcls_ingress_tether_rawip$4_14) returned fd: 9 (no error) I bpfloader: Attempted load object: /system/etc/bpf/offload.o, ret: Success $ adb shell ls -l /sys/fs/bpf | egrep offload -rw-rw---- 1 root network_stack 0 2020-04-22 01:27 map_offload_tether_ingress_map -rw-rw---- 1 root network_stack 0 2020-04-22 01:27 map_offload_tether_stats_map -r--r----- 1 root root 0 2020-04-22 01:27 prog_offload_schedcls_ingress_tether_ether -r--r----- 1 root root 0 2020-04-22 01:27 prog_offload_schedcls_ingress_tether_rawip Test: builds, atest, proper program loaded on 5.4.30 aosp cuttlefish Signed-off-by: Maciej Żenczykowski Change-Id: Id3fcb8e2a6b0087f704e77726e9961efc6145739 --- libbpf_android/Loader.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp index ce710a4..d2a502d 100644 --- a/libbpf_android/Loader.cpp +++ b/libbpf_android/Loader.cpp @@ -540,27 +540,36 @@ static int loadCodeSections(const char* elfPath, vector& cs, const string fname = pathToFilename(string(elfPath), true); for (int i = 0; i < (int)cs.size(); i++) { - string progPinLoc; - bool reuse = false; + string name = cs[i].name; 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; + unsigned min_kver = cs[i].prog_def->min_kver; + unsigned max_kver = cs[i].prog_def->max_kver; + ALOGD("cs[%d].name:%s min_kver:%x .max_kver:%x (kvers:%x)\n", i, name.c_str(), min_kver, + max_kver, kvers); + if (kvers < min_kver) continue; + if (kvers >= max_kver) continue; } + // strip any potential $foo suffix + // this can be used to provide duplicate programs + // conditionally loaded based on running kernel version + name = name.substr(0, name.find_last_of("$")); + + bool reuse = false; // Format of pin location is // /sys/fs/bpf/prog__ - progPinLoc = string(BPF_FS_PATH) + "prog_" + fname + "_" + cs[i].name; + string progPinLoc = string(BPF_FS_PATH) + "prog_" + fname + "_" + name; if (access(progPinLoc.c_str(), F_OK) == 0) { fd = bpf_obj_get(progPinLoc.c_str()); - ALOGD("New bpf prog load reusing prog %s, ret: %d\n", cs[i].name.c_str(), fd); + ALOGD("New bpf prog load reusing prog %s, ret: %d\n", progPinLoc.c_str(), fd); reuse = true; } else { vector log_buf(BPF_LOAD_LOG_SZ, 0); - fd = bpf_prog_load(cs[i].type, cs[i].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()); + fd = bpf_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()); 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"));