1b1b8bc3fSopenharmony_ci/* 2b1b8bc3fSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3b1b8bc3fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1b8bc3fSopenharmony_ci * you may not use this file except in compliance with the License. 5b1b8bc3fSopenharmony_ci * You may obtain a copy of the License at 6b1b8bc3fSopenharmony_ci * 7b1b8bc3fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1b8bc3fSopenharmony_ci * 9b1b8bc3fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1b8bc3fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1b8bc3fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1b8bc3fSopenharmony_ci * See the License for the specific language governing permissions and 13b1b8bc3fSopenharmony_ci * limitations under the License. 14b1b8bc3fSopenharmony_ci */ 15b1b8bc3fSopenharmony_ci 16b1b8bc3fSopenharmony_ci#include <cerrno> 17b1b8bc3fSopenharmony_ci#include <fcntl.h> 18b1b8bc3fSopenharmony_ci#include <filesystem> 19b1b8bc3fSopenharmony_ci#include <functional> 20b1b8bc3fSopenharmony_ci#include <iostream> 21b1b8bc3fSopenharmony_ci#include <linux/bpf.h> 22b1b8bc3fSopenharmony_ci#include <linux/if_ether.h> 23b1b8bc3fSopenharmony_ci#include <arpa/inet.h> 24b1b8bc3fSopenharmony_ci#include <map> 25b1b8bc3fSopenharmony_ci#include <memory.h> 26b1b8bc3fSopenharmony_ci#include <string> 27b1b8bc3fSopenharmony_ci#include <sys/mount.h> 28b1b8bc3fSopenharmony_ci#include <sys/resource.h> 29b1b8bc3fSopenharmony_ci#include <sys/syscall.h> 30b1b8bc3fSopenharmony_ci#include <unistd.h> 31b1b8bc3fSopenharmony_ci#include <vector> 32b1b8bc3fSopenharmony_ci 33b1b8bc3fSopenharmony_ci#include "bpf_def.h" 34b1b8bc3fSopenharmony_ci#include "bpf_loader.h" 35b1b8bc3fSopenharmony_ci#include "elf_types.hpp" 36b1b8bc3fSopenharmony_ci#include "elfio.hpp" 37b1b8bc3fSopenharmony_ci#include "elfio_relocation.hpp" 38b1b8bc3fSopenharmony_ci#include "net_manager_constants.h" 39b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h" 40b1b8bc3fSopenharmony_ci#include "securec.h" 41b1b8bc3fSopenharmony_ci 42b1b8bc3fSopenharmony_ci#define DEFINE_SECTION_NAME(name) \ 43b1b8bc3fSopenharmony_ci { \ 44b1b8bc3fSopenharmony_ci name, strlen(name) \ 45b1b8bc3fSopenharmony_ci } 46b1b8bc3fSopenharmony_ci 47b1b8bc3fSopenharmony_ci#define DEFINE_PROG_TYPE(progName, progType) \ 48b1b8bc3fSopenharmony_ci { \ 49b1b8bc3fSopenharmony_ci progName, progType \ 50b1b8bc3fSopenharmony_ci } 51b1b8bc3fSopenharmony_ci#define DEFINE_ATTACH_TYPE(progName, attachType, needExpectedAttach) \ 52b1b8bc3fSopenharmony_ci { \ 53b1b8bc3fSopenharmony_ci progName, attachType, needExpectedAttach \ 54b1b8bc3fSopenharmony_ci } 55b1b8bc3fSopenharmony_ci 56b1b8bc3fSopenharmony_cinamespace OHOS::NetManagerStandard { 57b1b8bc3fSopenharmony_cistatic constexpr const char *BPF_DIR = "/sys/fs/bpf"; 58b1b8bc3fSopenharmony_cistatic constexpr const char *CGROUP_DIR = "/sys/fs/cgroup"; 59b1b8bc3fSopenharmony_cistatic constexpr const char *MAPS_DIR = "/sys/fs/bpf/netsys/maps"; 60b1b8bc3fSopenharmony_cistatic constexpr const char *PROGS_DIR = "/sys/fs/bpf/netsys/progs"; 61b1b8bc3fSopenharmony_ci 62b1b8bc3fSopenharmony_ci// There is no limit to the size of SECTION_NAMES. 63b1b8bc3fSopenharmony_cistatic const struct SectionName { 64b1b8bc3fSopenharmony_ci const char *sectionName; 65b1b8bc3fSopenharmony_ci size_t sectionNameLength; 66b1b8bc3fSopenharmony_ci} SECTION_NAMES[] = { 67b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("kprobe/"), 68b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("kretprobe/"), 69b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("tracepoint/"), 70b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("raw_tracepoint/"), 71b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("xdp"), 72b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("perf_event/"), 73b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("socket"), 74b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("cgroup/"), 75b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("sockops"), 76b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("sk_skb"), 77b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("sk_msg"), 78b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("cgroup_skb"), 79b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("xdp_packet_parser"), 80b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("schedcls"), 81b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("classifier"), 82b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("cgroup_sock"), 83b1b8bc3fSopenharmony_ci DEFINE_SECTION_NAME("cgroup_addr"), 84b1b8bc3fSopenharmony_ci}; 85b1b8bc3fSopenharmony_ci 86b1b8bc3fSopenharmony_cistatic const constexpr struct { 87b1b8bc3fSopenharmony_ci const char *event; 88b1b8bc3fSopenharmony_ci bpf_prog_type progType; 89b1b8bc3fSopenharmony_ci} PROG_TYPES[] = { 90b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("socket", BPF_PROG_TYPE_SOCKET_FILTER), 91b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("cgroup_skb", BPF_PROG_TYPE_CGROUP_SKB), 92b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("xdp", BPF_PROG_TYPE_XDP), 93b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("xdp_packet_parser", BPF_PROG_TYPE_XDP), 94b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("schedcls", BPF_PROG_TYPE_SCHED_CLS), 95b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("classifier", BPF_PROG_TYPE_SCHED_CLS), 96b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("cgroup_sock", BPF_PROG_TYPE_CGROUP_SOCK), 97b1b8bc3fSopenharmony_ci DEFINE_PROG_TYPE("cgroup_addr", BPF_PROG_TYPE_CGROUP_SOCK_ADDR), 98b1b8bc3fSopenharmony_ci}; 99b1b8bc3fSopenharmony_ci 100b1b8bc3fSopenharmony_cistatic const constexpr struct { 101b1b8bc3fSopenharmony_ci const char *progName; 102b1b8bc3fSopenharmony_ci bpf_attach_type attachType; 103b1b8bc3fSopenharmony_ci bool needExpectedAttach; 104b1b8bc3fSopenharmony_ci} PROG_ATTACH_TYPES[] = { 105b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_sock_inet_create_socket", BPF_CGROUP_INET_SOCK_CREATE, false), 106b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_sock_inet_release_socket", BPF_CGROUP_INET_SOCK_RELEASE, true), 107b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_skb_uid_ingress", BPF_CGROUP_INET_INGRESS, false), 108b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_skb_uid_egress", BPF_CGROUP_INET_EGRESS, false), 109b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_addr_bind4", BPF_CGROUP_INET4_BIND, true), 110b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_addr_bind6", BPF_CGROUP_INET6_BIND, true), 111b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_addr_connect4", BPF_CGROUP_INET4_CONNECT, true), 112b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_addr_connect6", BPF_CGROUP_INET6_CONNECT, true), 113b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_addr_sendmsg4", BPF_CGROUP_UDP4_SENDMSG, true), 114b1b8bc3fSopenharmony_ci DEFINE_ATTACH_TYPE("cgroup_addr_sendmsg6", BPF_CGROUP_UDP6_SENDMSG, true), 115b1b8bc3fSopenharmony_ci}; 116b1b8bc3fSopenharmony_ci 117b1b8bc3fSopenharmony_ciint32_t g_sockFd = -1; 118b1b8bc3fSopenharmony_ci 119b1b8bc3fSopenharmony_cistruct BpfMapData { 120b1b8bc3fSopenharmony_ci BpfMapData() : fd(0) 121b1b8bc3fSopenharmony_ci { 122b1b8bc3fSopenharmony_ci if (memset_s(&def, sizeof(def), 0, sizeof(def)) != EOK) { 123b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("memset_s error"); 124b1b8bc3fSopenharmony_ci } 125b1b8bc3fSopenharmony_ci } 126b1b8bc3fSopenharmony_ci 127b1b8bc3fSopenharmony_ci int32_t fd; 128b1b8bc3fSopenharmony_ci std::string name; 129b1b8bc3fSopenharmony_ci bpf_map_def def{}; 130b1b8bc3fSopenharmony_ci}; 131b1b8bc3fSopenharmony_ci 132b1b8bc3fSopenharmony_citemplate <typename type> inline uint64_t PtrToU64(const type ptr) 133b1b8bc3fSopenharmony_ci{ 134b1b8bc3fSopenharmony_ci return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr)); 135b1b8bc3fSopenharmony_ci} 136b1b8bc3fSopenharmony_ci 137b1b8bc3fSopenharmony_ciinline bool EndsWith(const std::string &str, const std::string &searchFor) 138b1b8bc3fSopenharmony_ci{ 139b1b8bc3fSopenharmony_ci if (searchFor.size() > str.size()) { 140b1b8bc3fSopenharmony_ci return false; 141b1b8bc3fSopenharmony_ci } 142b1b8bc3fSopenharmony_ci 143b1b8bc3fSopenharmony_ci std::string source = str.substr(str.size() - searchFor.size(), searchFor.size()); 144b1b8bc3fSopenharmony_ci return source == searchFor; 145b1b8bc3fSopenharmony_ci} 146b1b8bc3fSopenharmony_ci 147b1b8bc3fSopenharmony_ciinline int32_t SysBpf(bpf_cmd cmd, bpf_attr *attr, uint32_t size) 148b1b8bc3fSopenharmony_ci{ 149b1b8bc3fSopenharmony_ci return static_cast<int32_t>(syscall(__NR_bpf, cmd, attr, size)); 150b1b8bc3fSopenharmony_ci} 151b1b8bc3fSopenharmony_ci 152b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjGet(const std::string &pathName, uint32_t fileFlags) 153b1b8bc3fSopenharmony_ci{ 154b1b8bc3fSopenharmony_ci bpf_attr attr = {}; 155b1b8bc3fSopenharmony_ci if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) { 156b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 157b1b8bc3fSopenharmony_ci } 158b1b8bc3fSopenharmony_ci attr.pathname = PtrToU64(pathName.c_str()); 159b1b8bc3fSopenharmony_ci attr.file_flags = fileFlags; 160b1b8bc3fSopenharmony_ci return SysBpf(BPF_OBJ_GET, &attr, sizeof(attr)); 161b1b8bc3fSopenharmony_ci} 162b1b8bc3fSopenharmony_ci 163b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjPin(int32_t fd, const std::string &pathName) 164b1b8bc3fSopenharmony_ci{ 165b1b8bc3fSopenharmony_ci bpf_attr attr = {}; 166b1b8bc3fSopenharmony_ci 167b1b8bc3fSopenharmony_ci if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) { 168b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 169b1b8bc3fSopenharmony_ci } 170b1b8bc3fSopenharmony_ci attr.pathname = PtrToU64(pathName.c_str()); 171b1b8bc3fSopenharmony_ci if (fd < 0) { 172b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 173b1b8bc3fSopenharmony_ci } 174b1b8bc3fSopenharmony_ci attr.bpf_fd = static_cast<uint32_t>(fd); 175b1b8bc3fSopenharmony_ci 176b1b8bc3fSopenharmony_ci return SysBpf(BPF_OBJ_PIN, &attr, sizeof(attr)); 177b1b8bc3fSopenharmony_ci} 178b1b8bc3fSopenharmony_ci 179b1b8bc3fSopenharmony_ciinline int32_t SysBpfProgLoad(bpf_attr *attr, uint32_t size) 180b1b8bc3fSopenharmony_ci{ 181b1b8bc3fSopenharmony_ci int32_t fd = SysBpf(BPF_PROG_LOAD, attr, size); 182b1b8bc3fSopenharmony_ci while (fd < 0 && errno == EAGAIN) { 183b1b8bc3fSopenharmony_ci fd = SysBpf(BPF_PROG_LOAD, attr, size); 184b1b8bc3fSopenharmony_ci } 185b1b8bc3fSopenharmony_ci 186b1b8bc3fSopenharmony_ci return fd; 187b1b8bc3fSopenharmony_ci} 188b1b8bc3fSopenharmony_ci 189b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjDetach(bpf_attach_type type, const int progFd, const int cgFd) 190b1b8bc3fSopenharmony_ci{ 191b1b8bc3fSopenharmony_ci bpf_attr attr = {}; 192b1b8bc3fSopenharmony_ci 193b1b8bc3fSopenharmony_ci if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) { 194b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 195b1b8bc3fSopenharmony_ci } 196b1b8bc3fSopenharmony_ci attr.target_fd = cgFd; 197b1b8bc3fSopenharmony_ci attr.attach_bpf_fd = progFd; 198b1b8bc3fSopenharmony_ci attr.attach_type = type; 199b1b8bc3fSopenharmony_ci 200b1b8bc3fSopenharmony_ci return SysBpf(BPF_PROG_DETACH, &attr, sizeof(attr)); 201b1b8bc3fSopenharmony_ci} 202b1b8bc3fSopenharmony_ci 203b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjAttach(bpf_attach_type type, const int progFd, const int cgFd) 204b1b8bc3fSopenharmony_ci{ 205b1b8bc3fSopenharmony_ci bpf_attr attr = {}; 206b1b8bc3fSopenharmony_ci 207b1b8bc3fSopenharmony_ci if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) { 208b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 209b1b8bc3fSopenharmony_ci } 210b1b8bc3fSopenharmony_ci attr.target_fd = cgFd; 211b1b8bc3fSopenharmony_ci attr.attach_bpf_fd = progFd; 212b1b8bc3fSopenharmony_ci attr.attach_type = type; 213b1b8bc3fSopenharmony_ci attr.attach_flags = BPF_F_ALLOW_MULTI; 214b1b8bc3fSopenharmony_ci 215b1b8bc3fSopenharmony_ci return SysBpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); 216b1b8bc3fSopenharmony_ci} 217b1b8bc3fSopenharmony_ci 218b1b8bc3fSopenharmony_ciinline bool MatchSecName(const std::string &name) 219b1b8bc3fSopenharmony_ci{ 220b1b8bc3fSopenharmony_ci auto matchFunc = [name](const SectionName &sec) -> bool { 221b1b8bc3fSopenharmony_ci if (name.size() < sec.sectionNameLength) { 222b1b8bc3fSopenharmony_ci return false; 223b1b8bc3fSopenharmony_ci } 224b1b8bc3fSopenharmony_ci return memcmp(name.c_str(), sec.sectionName, sec.sectionNameLength) == 0; 225b1b8bc3fSopenharmony_ci }; 226b1b8bc3fSopenharmony_ci auto size = sizeof(SECTION_NAMES) / sizeof(SectionName); 227b1b8bc3fSopenharmony_ci return std::any_of(SECTION_NAMES, SECTION_NAMES + size, matchFunc); 228b1b8bc3fSopenharmony_ci} 229b1b8bc3fSopenharmony_ci 230b1b8bc3fSopenharmony_ciinline int32_t UnPin(const std::string &path) 231b1b8bc3fSopenharmony_ci{ 232b1b8bc3fSopenharmony_ci return unlink(path.c_str()); 233b1b8bc3fSopenharmony_ci} 234b1b8bc3fSopenharmony_ci 235b1b8bc3fSopenharmony_ciclass ElfLoader { 236b1b8bc3fSopenharmony_cipublic: 237b1b8bc3fSopenharmony_ci explicit ElfLoader(std::string path) : path_(std::move(path)), kernVersion_(0) {} 238b1b8bc3fSopenharmony_ci 239b1b8bc3fSopenharmony_ci ElfLoadError Unload() const 240b1b8bc3fSopenharmony_ci { 241b1b8bc3fSopenharmony_ci const struct { 242b1b8bc3fSopenharmony_ci uint32_t index; 243b1b8bc3fSopenharmony_ci const char *infoMsg; 244b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> fun; 245b1b8bc3fSopenharmony_ci const char *errorMsg; 246b1b8bc3fSopenharmony_ci } funList[]{ 247b1b8bc3fSopenharmony_ci {1, "path is valid", isPathValid_, "path is not valid"}, 248b1b8bc3fSopenharmony_ci {2, "load elf file ok", loadElfFile_, "load elf file failed"}, 249b1b8bc3fSopenharmony_ci {3, "load elf map section ok", loadElfMapsSection_, "load elf map section failed"}, 250b1b8bc3fSopenharmony_ci {4, "delete maps ok", deleteMaps_, "delete maps failed"}, 251b1b8bc3fSopenharmony_ci {5, "unload progs ok", unloadProgs_, "unload progs ok"}, 252b1b8bc3fSopenharmony_ci }; 253b1b8bc3fSopenharmony_ci 254b1b8bc3fSopenharmony_ci for (const auto &fun : funList) { 255b1b8bc3fSopenharmony_ci auto ret = fun.fun(); 256b1b8bc3fSopenharmony_ci if (ret != ELF_LOAD_ERR_NONE) { 257b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("error msg is %{public}s", fun.errorMsg); 258b1b8bc3fSopenharmony_ci return static_cast<ElfLoadError>(ret); 259b1b8bc3fSopenharmony_ci } 260b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("the %{public}u step: %{public}s", fun.index, fun.infoMsg); 261b1b8bc3fSopenharmony_ci } 262b1b8bc3fSopenharmony_ci 263b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 264b1b8bc3fSopenharmony_ci } 265b1b8bc3fSopenharmony_ci 266b1b8bc3fSopenharmony_ci ElfLoadError Load() const 267b1b8bc3fSopenharmony_ci { 268b1b8bc3fSopenharmony_ci const struct { 269b1b8bc3fSopenharmony_ci uint32_t index; 270b1b8bc3fSopenharmony_ci const char *infoMsg; 271b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> fun; 272b1b8bc3fSopenharmony_ci const char *errorMsg; 273b1b8bc3fSopenharmony_ci } funList[]{ 274b1b8bc3fSopenharmony_ci {1, "path is valid", isPathValid_, "path is not valid"}, 275b1b8bc3fSopenharmony_ci {2, "make directories fs ok", makeDirectories, "make directories fs failed"}, 276b1b8bc3fSopenharmony_ci {3, "load elf file ok", loadElfFile_, "load elf file failed"}, 277b1b8bc3fSopenharmony_ci {4, "version is valid", isVersionValid_, "version is not valid"}, 278b1b8bc3fSopenharmony_ci {5, "set license and version ok", setLicenseAndVersion_, "set license and version failed"}, 279b1b8bc3fSopenharmony_ci {6, "load elf map section ok", loadElfMapsSection_, "load elf map section failed"}, 280b1b8bc3fSopenharmony_ci {7, "set rlimit ok", setRlimit_, "set rlimit failed"}, 281b1b8bc3fSopenharmony_ci {8, "create maps ok", createMaps_, "create maps failed"}, 282b1b8bc3fSopenharmony_ci {9, "parse relocation ok", parseRelocation_, "parse relocation failed"}, 283b1b8bc3fSopenharmony_ci {10, "load progs ok", loadProgs_, "load progs failed"}, 284b1b8bc3fSopenharmony_ci }; 285b1b8bc3fSopenharmony_ci for (const auto &fun : funList) { 286b1b8bc3fSopenharmony_ci auto ret = fun.fun(); 287b1b8bc3fSopenharmony_ci if (ret != ELF_LOAD_ERR_NONE) { 288b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("error msg is %{public}s", fun.errorMsg); 289b1b8bc3fSopenharmony_ci return static_cast<ElfLoadError>(ret); 290b1b8bc3fSopenharmony_ci } 291b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("the %{public}u step: %{public}s", fun.index, fun.infoMsg); 292b1b8bc3fSopenharmony_ci } 293b1b8bc3fSopenharmony_ci 294b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 295b1b8bc3fSopenharmony_ci } 296b1b8bc3fSopenharmony_ci 297b1b8bc3fSopenharmony_ciprivate: 298b1b8bc3fSopenharmony_ci bool CheckPath() 299b1b8bc3fSopenharmony_ci { 300b1b8bc3fSopenharmony_ci if (path_.empty() || !std::filesystem::exists(path_) || std::filesystem::is_directory(path_)) { 301b1b8bc3fSopenharmony_ci return false; 302b1b8bc3fSopenharmony_ci } 303b1b8bc3fSopenharmony_ci 304b1b8bc3fSopenharmony_ci return true; 305b1b8bc3fSopenharmony_ci } 306b1b8bc3fSopenharmony_ci 307b1b8bc3fSopenharmony_ci bool IsPathValid() 308b1b8bc3fSopenharmony_ci { 309b1b8bc3fSopenharmony_ci if (!CheckPath()) { 310b1b8bc3fSopenharmony_ci return false; 311b1b8bc3fSopenharmony_ci } 312b1b8bc3fSopenharmony_ci return EndsWith(path_, ".o"); 313b1b8bc3fSopenharmony_ci } 314b1b8bc3fSopenharmony_ci 315b1b8bc3fSopenharmony_ci bool LoadElfFile() 316b1b8bc3fSopenharmony_ci { 317b1b8bc3fSopenharmony_ci return elfIo_.load(path_); 318b1b8bc3fSopenharmony_ci } 319b1b8bc3fSopenharmony_ci 320b1b8bc3fSopenharmony_ci bool IsVersionValid() 321b1b8bc3fSopenharmony_ci { 322b1b8bc3fSopenharmony_ci return elfIo_.get_version() == ELFIO::EV_CURRENT; 323b1b8bc3fSopenharmony_ci } 324b1b8bc3fSopenharmony_ci 325b1b8bc3fSopenharmony_ci static bool SetRlimit() 326b1b8bc3fSopenharmony_ci { 327b1b8bc3fSopenharmony_ci rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 328b1b8bc3fSopenharmony_ci return setrlimit(RLIMIT_MEMLOCK, &r) >= 0; 329b1b8bc3fSopenharmony_ci } 330b1b8bc3fSopenharmony_ci 331b1b8bc3fSopenharmony_ci static bool IsMounted(const std::string &dir) 332b1b8bc3fSopenharmony_ci { 333b1b8bc3fSopenharmony_ci std::ifstream ifs("/proc/mounts", std::ios::in); 334b1b8bc3fSopenharmony_ci if (!ifs.is_open()) { 335b1b8bc3fSopenharmony_ci return false; 336b1b8bc3fSopenharmony_ci } 337b1b8bc3fSopenharmony_ci 338b1b8bc3fSopenharmony_ci std::string s; 339b1b8bc3fSopenharmony_ci while (std::getline(ifs, s)) { 340b1b8bc3fSopenharmony_ci if (s.find(dir) != std::string::npos) { 341b1b8bc3fSopenharmony_ci ifs.close(); 342b1b8bc3fSopenharmony_ci return true; 343b1b8bc3fSopenharmony_ci } 344b1b8bc3fSopenharmony_ci } 345b1b8bc3fSopenharmony_ci ifs.close(); 346b1b8bc3fSopenharmony_ci return false; 347b1b8bc3fSopenharmony_ci } 348b1b8bc3fSopenharmony_ci 349b1b8bc3fSopenharmony_ci static bool MakeDir(const std::string &dir) 350b1b8bc3fSopenharmony_ci { 351b1b8bc3fSopenharmony_ci if (std::filesystem::exists(dir) && std::filesystem::is_directory(dir)) { 352b1b8bc3fSopenharmony_ci return true; 353b1b8bc3fSopenharmony_ci } 354b1b8bc3fSopenharmony_ci if (!std::filesystem::exists(dir)) { 355b1b8bc3fSopenharmony_ci if (!std::filesystem::create_directories(std::filesystem::path(dir))) { 356b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("filesystem make dir err %{public}d", errno); 357b1b8bc3fSopenharmony_ci return false; 358b1b8bc3fSopenharmony_ci } 359b1b8bc3fSopenharmony_ci return true; 360b1b8bc3fSopenharmony_ci } 361b1b8bc3fSopenharmony_ci if (!std::filesystem::is_directory(dir)) { 362b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("%{public}s is a file", dir.c_str()); 363b1b8bc3fSopenharmony_ci return false; 364b1b8bc3fSopenharmony_ci } 365b1b8bc3fSopenharmony_ci return true; 366b1b8bc3fSopenharmony_ci } 367b1b8bc3fSopenharmony_ci 368b1b8bc3fSopenharmony_ci static bool MakeDirectories() 369b1b8bc3fSopenharmony_ci { 370b1b8bc3fSopenharmony_ci if (IsMounted(BPF_DIR) && std::filesystem::exists(MAPS_DIR) && std::filesystem::is_directory(MAPS_DIR) && 371b1b8bc3fSopenharmony_ci std::filesystem::exists(PROGS_DIR) && std::filesystem::is_directory(PROGS_DIR)) { 372b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("%{public}s", "bpf directories are exists"); 373b1b8bc3fSopenharmony_ci return true; 374b1b8bc3fSopenharmony_ci } 375b1b8bc3fSopenharmony_ci if (!IsMounted(BPF_DIR) && mount(BPF_DIR, BPF_DIR, "bpf", MS_RELATIME, nullptr) < 0) { 376b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("mount bpf fs failed: errno = %{public}d", errno); 377b1b8bc3fSopenharmony_ci return false; 378b1b8bc3fSopenharmony_ci } 379b1b8bc3fSopenharmony_ci if (!MakeDir(MAPS_DIR)) { 380b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("can not make dir: %{public}s", MAPS_DIR); 381b1b8bc3fSopenharmony_ci return false; 382b1b8bc3fSopenharmony_ci } 383b1b8bc3fSopenharmony_ci if (!MakeDir(PROGS_DIR)) { 384b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("can not make dir: %{public}s", PROGS_DIR); 385b1b8bc3fSopenharmony_ci return false; 386b1b8bc3fSopenharmony_ci } 387b1b8bc3fSopenharmony_ci 388b1b8bc3fSopenharmony_ci if (!IsMounted(CGROUP_DIR) && mount(CGROUP_DIR, CGROUP_DIR, "cgroup2", MS_RELATIME, nullptr) < 0) { 389b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("mount cgroup fs failed: errno = %{public}d", errno); 390b1b8bc3fSopenharmony_ci return false; 391b1b8bc3fSopenharmony_ci } 392b1b8bc3fSopenharmony_ci return true; 393b1b8bc3fSopenharmony_ci } 394b1b8bc3fSopenharmony_ci 395b1b8bc3fSopenharmony_ci bool SetLicenseAndVersion() 396b1b8bc3fSopenharmony_ci { 397b1b8bc3fSopenharmony_ci return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](const auto §ion) { 398b1b8bc3fSopenharmony_ci if (section->get_name() == "license") { 399b1b8bc3fSopenharmony_ci license_ = section->get_data(); 400b1b8bc3fSopenharmony_ci if (license_.empty()) { 401b1b8bc3fSopenharmony_ci return false; 402b1b8bc3fSopenharmony_ci } 403b1b8bc3fSopenharmony_ci } else if (section->get_name() == "version") { 404b1b8bc3fSopenharmony_ci try { 405b1b8bc3fSopenharmony_ci kernVersion_ = std::stoi(section->get_data()); 406b1b8bc3fSopenharmony_ci } catch (const std::invalid_argument& e) { 407b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("invalid_argument"); 408b1b8bc3fSopenharmony_ci return false; 409b1b8bc3fSopenharmony_ci } catch (const std::out_of_range& e) { 410b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("out_of_range"); 411b1b8bc3fSopenharmony_ci return false; 412b1b8bc3fSopenharmony_ci } 413b1b8bc3fSopenharmony_ci if (kernVersion_ == 0) { 414b1b8bc3fSopenharmony_ci return false; 415b1b8bc3fSopenharmony_ci } 416b1b8bc3fSopenharmony_ci } 417b1b8bc3fSopenharmony_ci 418b1b8bc3fSopenharmony_ci return true; 419b1b8bc3fSopenharmony_ci }); 420b1b8bc3fSopenharmony_ci } 421b1b8bc3fSopenharmony_ci 422b1b8bc3fSopenharmony_ci std::map<ELFIO::Elf64_Addr, std::string> LoadElfMapSectionCore() 423b1b8bc3fSopenharmony_ci { 424b1b8bc3fSopenharmony_ci std::map<ELFIO::Elf64_Addr, std::string> mapName; 425b1b8bc3fSopenharmony_ci for (const auto §ion : elfIo_.sections) { 426b1b8bc3fSopenharmony_ci if (section->get_type() != ELFIO::SHT_SYMTAB && section->get_type() != ELFIO::SHT_DYNSYM) { 427b1b8bc3fSopenharmony_ci continue; 428b1b8bc3fSopenharmony_ci } 429b1b8bc3fSopenharmony_ci ELFIO::symbol_section_accessor symbols(elfIo_, section.get()); 430b1b8bc3fSopenharmony_ci for (ELFIO::Elf_Xword i = 0; i < symbols.get_symbols_num(); i++) { 431b1b8bc3fSopenharmony_ci std::string name; 432b1b8bc3fSopenharmony_ci ELFIO::Elf64_Addr value = 0; 433b1b8bc3fSopenharmony_ci ELFIO::Elf_Xword size = 0; 434b1b8bc3fSopenharmony_ci unsigned char bind = 0; 435b1b8bc3fSopenharmony_ci unsigned char type = 0; 436b1b8bc3fSopenharmony_ci ELFIO::Elf_Half elfSection = 0; 437b1b8bc3fSopenharmony_ci unsigned char other = 0; 438b1b8bc3fSopenharmony_ci symbols.get_symbol(i, name, value, size, bind, type, elfSection, other); 439b1b8bc3fSopenharmony_ci if (type != ELFIO::STT_OBJECT || !EndsWith(name, "_map")) { 440b1b8bc3fSopenharmony_ci continue; 441b1b8bc3fSopenharmony_ci } 442b1b8bc3fSopenharmony_ci if (mapName.find(value) != mapName.end()) { 443b1b8bc3fSopenharmony_ci return {}; 444b1b8bc3fSopenharmony_ci } 445b1b8bc3fSopenharmony_ci mapName[value] = name; 446b1b8bc3fSopenharmony_ci } 447b1b8bc3fSopenharmony_ci } 448b1b8bc3fSopenharmony_ci return mapName; 449b1b8bc3fSopenharmony_ci } 450b1b8bc3fSopenharmony_ci 451b1b8bc3fSopenharmony_ci bool LoadElfMapsSection() 452b1b8bc3fSopenharmony_ci { 453b1b8bc3fSopenharmony_ci if (elfIo_.sections.size() == 0) { 454b1b8bc3fSopenharmony_ci return false; 455b1b8bc3fSopenharmony_ci } 456b1b8bc3fSopenharmony_ci 457b1b8bc3fSopenharmony_ci auto it = std::find_if(elfIo_.sections.begin(), elfIo_.sections.end(), 458b1b8bc3fSopenharmony_ci [](const auto §ion) { return section->get_name() == "maps"; }); 459b1b8bc3fSopenharmony_ci if (it == elfIo_.sections.end()) { 460b1b8bc3fSopenharmony_ci return true; 461b1b8bc3fSopenharmony_ci } 462b1b8bc3fSopenharmony_ci 463b1b8bc3fSopenharmony_ci ELFIO::section *mapsSection = it->get(); 464b1b8bc3fSopenharmony_ci auto defs = reinterpret_cast<const bpf_map_def *>(mapsSection->get_data()); 465b1b8bc3fSopenharmony_ci auto mapNum = mapsSection->get_size() / sizeof(bpf_map_def); 466b1b8bc3fSopenharmony_ci for (size_t i = 0; i < static_cast<size_t>(mapNum); i++) { 467b1b8bc3fSopenharmony_ci BpfMapData map; 468b1b8bc3fSopenharmony_ci map.def = defs[i]; 469b1b8bc3fSopenharmony_ci maps_.emplace_back(map); 470b1b8bc3fSopenharmony_ci } 471b1b8bc3fSopenharmony_ci auto mapName = LoadElfMapSectionCore(); 472b1b8bc3fSopenharmony_ci if (mapName.size() != maps_.size()) { 473b1b8bc3fSopenharmony_ci return false; 474b1b8bc3fSopenharmony_ci } 475b1b8bc3fSopenharmony_ci size_t mapIndex = 0; 476b1b8bc3fSopenharmony_ci for (const auto &[addr, name] : mapName) { 477b1b8bc3fSopenharmony_ci maps_[mapIndex].name = name; 478b1b8bc3fSopenharmony_ci ++mapIndex; 479b1b8bc3fSopenharmony_ci } 480b1b8bc3fSopenharmony_ci 481b1b8bc3fSopenharmony_ci return true; 482b1b8bc3fSopenharmony_ci } 483b1b8bc3fSopenharmony_ci 484b1b8bc3fSopenharmony_ci static void PrintMapAttr(const bpf_attr &attr) 485b1b8bc3fSopenharmony_ci { 486b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("%{public}s", "BPF_MAP_CREATE:"); 487b1b8bc3fSopenharmony_ci NETNATIVE_LOGI(" .map_type = %{public}u", attr.map_type); 488b1b8bc3fSopenharmony_ci NETNATIVE_LOGI(" .key_size = %{public}u", attr.key_size); 489b1b8bc3fSopenharmony_ci NETNATIVE_LOGI(" .value_size = %{public}u", attr.value_size); 490b1b8bc3fSopenharmony_ci NETNATIVE_LOGI(" .max_entries = %{public}u", attr.max_entries); 491b1b8bc3fSopenharmony_ci NETNATIVE_LOGI(" .map_flags = %{public}u", attr.map_flags); 492b1b8bc3fSopenharmony_ci NETNATIVE_LOGI(" .map_name = %{public}s", attr.map_name); 493b1b8bc3fSopenharmony_ci } 494b1b8bc3fSopenharmony_ci 495b1b8bc3fSopenharmony_ci static int32_t BpfCreateMapNode(const BpfMapData &map) 496b1b8bc3fSopenharmony_ci { 497b1b8bc3fSopenharmony_ci bpf_attr attr = {}; 498b1b8bc3fSopenharmony_ci if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) { 499b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 500b1b8bc3fSopenharmony_ci } 501b1b8bc3fSopenharmony_ci attr.map_type = map.def.type; 502b1b8bc3fSopenharmony_ci attr.key_size = map.def.key_size; 503b1b8bc3fSopenharmony_ci attr.value_size = map.def.value_size; 504b1b8bc3fSopenharmony_ci attr.max_entries = map.def.max_entries; 505b1b8bc3fSopenharmony_ci attr.map_flags = map.def.map_flags; 506b1b8bc3fSopenharmony_ci if (!map.name.empty()) { 507b1b8bc3fSopenharmony_ci if (memcpy_s(attr.map_name, sizeof(attr.map_name) - 1, map.name.c_str(), 508b1b8bc3fSopenharmony_ci std::min<size_t>(map.name.size(), sizeof(attr.map_name) - 1)) != EOK) { 509b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Failed copy map name %{public}s", map.name.c_str()); 510b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 511b1b8bc3fSopenharmony_ci } 512b1b8bc3fSopenharmony_ci } 513b1b8bc3fSopenharmony_ci attr.numa_node = (map.def.map_flags & static_cast<unsigned int>(BPF_F_NUMA_NODE)) ? map.def.numa_node : 0; 514b1b8bc3fSopenharmony_ci PrintMapAttr(attr); 515b1b8bc3fSopenharmony_ci 516b1b8bc3fSopenharmony_ci auto fd = SysBpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 517b1b8bc3fSopenharmony_ci if (fd < 0) { 518b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("__NR_bpf, BPF_MAP_CREATE failed %{public}d %{public}d %{public}d", __NR_bpf, fd, errno); 519b1b8bc3fSopenharmony_ci } 520b1b8bc3fSopenharmony_ci return fd; 521b1b8bc3fSopenharmony_ci } 522b1b8bc3fSopenharmony_ci 523b1b8bc3fSopenharmony_ci bool CreateMaps() 524b1b8bc3fSopenharmony_ci { 525b1b8bc3fSopenharmony_ci for (auto &map : maps_) { 526b1b8bc3fSopenharmony_ci auto fd = BpfCreateMapNode(map); 527b1b8bc3fSopenharmony_ci if (fd < 0) { 528b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Failed create map (%{public}s): %{public}d", map.name.c_str(), fd); 529b1b8bc3fSopenharmony_ci return false; 530b1b8bc3fSopenharmony_ci } 531b1b8bc3fSopenharmony_ci 532b1b8bc3fSopenharmony_ci map.fd = fd; 533b1b8bc3fSopenharmony_ci std::string mapPinLocation = std::string(MAPS_DIR) + "/" + map.name; 534b1b8bc3fSopenharmony_ci if (access(mapPinLocation.c_str(), F_OK) == 0) { 535b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("map: %{public}s has already been pinned", mapPinLocation.c_str()); 536b1b8bc3fSopenharmony_ci } else { 537b1b8bc3fSopenharmony_ci if (SysBpfObjPin(fd, mapPinLocation) < 0) { 538b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Failed to pin map: %{public}s, errno = %{public}d", mapPinLocation.c_str(), errno); 539b1b8bc3fSopenharmony_ci return false; 540b1b8bc3fSopenharmony_ci } 541b1b8bc3fSopenharmony_ci } 542b1b8bc3fSopenharmony_ci } 543b1b8bc3fSopenharmony_ci return true; 544b1b8bc3fSopenharmony_ci } 545b1b8bc3fSopenharmony_ci 546b1b8bc3fSopenharmony_ci bool DeleteMaps() 547b1b8bc3fSopenharmony_ci { 548b1b8bc3fSopenharmony_ci return std::all_of(maps_.begin(), maps_.end(), [](const auto &map) { 549b1b8bc3fSopenharmony_ci std::string mapPinLocation = std::string(MAPS_DIR) + "/" + map.name; 550b1b8bc3fSopenharmony_ci if (access(mapPinLocation.c_str(), F_OK) == 0) { 551b1b8bc3fSopenharmony_ci auto ret = UnPin(mapPinLocation); 552b1b8bc3fSopenharmony_ci return ret >= 0; 553b1b8bc3fSopenharmony_ci } 554b1b8bc3fSopenharmony_ci return true; 555b1b8bc3fSopenharmony_ci }); 556b1b8bc3fSopenharmony_ci } 557b1b8bc3fSopenharmony_ci 558b1b8bc3fSopenharmony_ci bool ApplyRelocation(bpf_insn *insn, ELFIO::section *section) const 559b1b8bc3fSopenharmony_ci { 560b1b8bc3fSopenharmony_ci if (insn == nullptr || section == nullptr || section->get_entry_size() == 0) { 561b1b8bc3fSopenharmony_ci return false; 562b1b8bc3fSopenharmony_ci } 563b1b8bc3fSopenharmony_ci 564b1b8bc3fSopenharmony_ci auto size = section->get_size() / section->get_entry_size(); 565b1b8bc3fSopenharmony_ci if (size == 0) { 566b1b8bc3fSopenharmony_ci return false; 567b1b8bc3fSopenharmony_ci } 568b1b8bc3fSopenharmony_ci 569b1b8bc3fSopenharmony_ci ELFIO::Elf64_Addr offset = 0; 570b1b8bc3fSopenharmony_ci ELFIO::Elf64_Addr symbolValue = 0; 571b1b8bc3fSopenharmony_ci std::string symbolName; 572b1b8bc3fSopenharmony_ci ELFIO::Elf_Word type = 0; 573b1b8bc3fSopenharmony_ci ELFIO::Elf_Sxword addend = 0; 574b1b8bc3fSopenharmony_ci ELFIO::Elf_Sxword calcValue = 0; 575b1b8bc3fSopenharmony_ci ELFIO::relocation_section_accessor relocation(elfIo_, section); 576b1b8bc3fSopenharmony_ci for (size_t i = 0; i < size; i++) { 577b1b8bc3fSopenharmony_ci relocation.get_entry(i, offset, symbolValue, symbolName, type, addend, calcValue); 578b1b8bc3fSopenharmony_ci uint32_t index = offset / sizeof(bpf_insn); 579b1b8bc3fSopenharmony_ci if (insn[index].code != (BPF_LD | BPF_IMM | BPF_DW)) { 580b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Invalid relo for insn[%{public}u].code 0x%{public}x 0x%{public}x", index, 581b1b8bc3fSopenharmony_ci insn[index].code, (BPF_LD | BPF_IMM | BPF_DW)); 582b1b8bc3fSopenharmony_ci continue; 583b1b8bc3fSopenharmony_ci } 584b1b8bc3fSopenharmony_ci 585b1b8bc3fSopenharmony_ci size_t mapIdx; 586b1b8bc3fSopenharmony_ci bool match = false; 587b1b8bc3fSopenharmony_ci for (mapIdx = 0; mapIdx < maps_.size(); mapIdx++) { 588b1b8bc3fSopenharmony_ci if (maps_[mapIdx].name == symbolName) { 589b1b8bc3fSopenharmony_ci match = true; 590b1b8bc3fSopenharmony_ci break; 591b1b8bc3fSopenharmony_ci } 592b1b8bc3fSopenharmony_ci } 593b1b8bc3fSopenharmony_ci if (!match) { 594b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Invalid relo for insn[%{public}u] no map_data match %{public}s index %{public}zu", 595b1b8bc3fSopenharmony_ci index, section->get_name().c_str(), i); 596b1b8bc3fSopenharmony_ci continue; 597b1b8bc3fSopenharmony_ci } 598b1b8bc3fSopenharmony_ci insn[index].src_reg = BPF_PSEUDO_MAP_FD; 599b1b8bc3fSopenharmony_ci insn[index].imm = maps_[mapIdx].fd; 600b1b8bc3fSopenharmony_ci } 601b1b8bc3fSopenharmony_ci return true; 602b1b8bc3fSopenharmony_ci } 603b1b8bc3fSopenharmony_ci 604b1b8bc3fSopenharmony_ci int32_t BpfLoadProgram(std::string &progName, bpf_prog_type type, const bpf_insn *insns, size_t insnsCnt) 605b1b8bc3fSopenharmony_ci { 606b1b8bc3fSopenharmony_ci if (insns == nullptr) { 607b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 608b1b8bc3fSopenharmony_ci } 609b1b8bc3fSopenharmony_ci 610b1b8bc3fSopenharmony_ci bpf_attr attr = {}; 611b1b8bc3fSopenharmony_ci if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) { 612b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 613b1b8bc3fSopenharmony_ci } 614b1b8bc3fSopenharmony_ci attr.prog_type = type; 615b1b8bc3fSopenharmony_ci if (kernVersion_ < 0) { 616b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 617b1b8bc3fSopenharmony_ci } 618b1b8bc3fSopenharmony_ci attr.kern_version = static_cast<uint32_t>(kernVersion_); 619b1b8bc3fSopenharmony_ci attr.insn_cnt = static_cast<uint32_t>(insnsCnt); 620b1b8bc3fSopenharmony_ci attr.insns = PtrToU64(insns); 621b1b8bc3fSopenharmony_ci attr.license = PtrToU64(license_.c_str()); 622b1b8bc3fSopenharmony_ci for (const auto &prog : PROG_ATTACH_TYPES) { 623b1b8bc3fSopenharmony_ci if (prog.progName != nullptr && progName == prog.progName) { 624b1b8bc3fSopenharmony_ci if (prog.needExpectedAttach) { 625b1b8bc3fSopenharmony_ci attr.expected_attach_type = prog.attachType; 626b1b8bc3fSopenharmony_ci } 627b1b8bc3fSopenharmony_ci break; 628b1b8bc3fSopenharmony_ci } 629b1b8bc3fSopenharmony_ci } 630b1b8bc3fSopenharmony_ci 631b1b8bc3fSopenharmony_ci return SysBpfProgLoad(&attr, sizeof(attr)); 632b1b8bc3fSopenharmony_ci } 633b1b8bc3fSopenharmony_ci 634b1b8bc3fSopenharmony_ci static bpf_prog_type ConvertEventToProgType(const std::string &event) 635b1b8bc3fSopenharmony_ci { 636b1b8bc3fSopenharmony_ci for (const auto &prog : PROG_TYPES) { 637b1b8bc3fSopenharmony_ci size_t size = strlen(prog.event); 638b1b8bc3fSopenharmony_ci if (event.size() < size) { 639b1b8bc3fSopenharmony_ci continue; 640b1b8bc3fSopenharmony_ci } 641b1b8bc3fSopenharmony_ci if (memcmp(event.c_str(), prog.event, size) == 0) { 642b1b8bc3fSopenharmony_ci return prog.progType; 643b1b8bc3fSopenharmony_ci } 644b1b8bc3fSopenharmony_ci } 645b1b8bc3fSopenharmony_ci return static_cast<bpf_prog_type>(NETMANAGER_ERROR); 646b1b8bc3fSopenharmony_ci } 647b1b8bc3fSopenharmony_ci 648b1b8bc3fSopenharmony_ci static bool DoAttach(int32_t progFd, const std::string &progName) 649b1b8bc3fSopenharmony_ci { 650b1b8bc3fSopenharmony_ci if (progName.size() < 1) { 651b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("progName is null"); 652b1b8bc3fSopenharmony_ci return false; 653b1b8bc3fSopenharmony_ci } 654b1b8bc3fSopenharmony_ci NETNATIVE_LOG_D("The progName = %{public}s", progName.c_str()); 655b1b8bc3fSopenharmony_ci 656b1b8bc3fSopenharmony_ci for (const auto &prog : PROG_ATTACH_TYPES) { 657b1b8bc3fSopenharmony_ci if (prog.progName != nullptr && progName == prog.progName) { 658b1b8bc3fSopenharmony_ci int cgroupFd = open(CGROUP_DIR, O_DIRECTORY | O_RDONLY | O_CLOEXEC); 659b1b8bc3fSopenharmony_ci if (cgroupFd < 0) { 660b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("open CGROUP_DIR failed: errno = %{public}d", errno); 661b1b8bc3fSopenharmony_ci return false; 662b1b8bc3fSopenharmony_ci } 663b1b8bc3fSopenharmony_ci 664b1b8bc3fSopenharmony_ci if (SysBpfObjAttach(prog.attachType, progFd, cgroupFd) < NETSYS_SUCCESS) { 665b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("attach %{pubic}s failed: errno = %{public}d", progName.c_str(), errno); 666b1b8bc3fSopenharmony_ci close(cgroupFd); 667b1b8bc3fSopenharmony_ci return false; 668b1b8bc3fSopenharmony_ci } 669b1b8bc3fSopenharmony_ci 670b1b8bc3fSopenharmony_ci close(cgroupFd); 671b1b8bc3fSopenharmony_ci return true; 672b1b8bc3fSopenharmony_ci } 673b1b8bc3fSopenharmony_ci } 674b1b8bc3fSopenharmony_ci 675b1b8bc3fSopenharmony_ci return true; 676b1b8bc3fSopenharmony_ci } 677b1b8bc3fSopenharmony_ci 678b1b8bc3fSopenharmony_ci static void DoDetach(const std::string &progPinLocation, const std::string &progName) 679b1b8bc3fSopenharmony_ci { 680b1b8bc3fSopenharmony_ci if (progName.size() < 1) { 681b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("progName is null"); 682b1b8bc3fSopenharmony_ci return; 683b1b8bc3fSopenharmony_ci } 684b1b8bc3fSopenharmony_ci NETNATIVE_LOG_D("The progName = %{public}s", progName.c_str()); 685b1b8bc3fSopenharmony_ci 686b1b8bc3fSopenharmony_ci for (const auto &prog : PROG_ATTACH_TYPES) { 687b1b8bc3fSopenharmony_ci if (prog.progName != nullptr && progName == prog.progName) { 688b1b8bc3fSopenharmony_ci int cgroupFd = open(CGROUP_DIR, O_DIRECTORY | O_RDONLY | O_CLOEXEC); 689b1b8bc3fSopenharmony_ci if (cgroupFd < NETSYS_SUCCESS) { 690b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("open CGROUP_DIR failed: errno = %{public}d", errno); 691b1b8bc3fSopenharmony_ci return; 692b1b8bc3fSopenharmony_ci } 693b1b8bc3fSopenharmony_ci 694b1b8bc3fSopenharmony_ci auto progFd = SysBpfObjGet(progPinLocation, 0); 695b1b8bc3fSopenharmony_ci if (progFd < NETSYS_SUCCESS) { 696b1b8bc3fSopenharmony_ci close(cgroupFd); 697b1b8bc3fSopenharmony_ci return; 698b1b8bc3fSopenharmony_ci } 699b1b8bc3fSopenharmony_ci 700b1b8bc3fSopenharmony_ci if (SysBpfObjDetach(prog.attachType, progFd, cgroupFd) < NETSYS_SUCCESS) { 701b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("detach %{pubic}s failed: errno = %{public}d", progName.c_str(), errno); 702b1b8bc3fSopenharmony_ci close(cgroupFd); 703b1b8bc3fSopenharmony_ci return; 704b1b8bc3fSopenharmony_ci } 705b1b8bc3fSopenharmony_ci 706b1b8bc3fSopenharmony_ci close(cgroupFd); 707b1b8bc3fSopenharmony_ci return; 708b1b8bc3fSopenharmony_ci } 709b1b8bc3fSopenharmony_ci } 710b1b8bc3fSopenharmony_ci } 711b1b8bc3fSopenharmony_ci 712b1b8bc3fSopenharmony_ci bool LoadProg(const std::string &event, const bpf_insn *insn, size_t insnCnt) 713b1b8bc3fSopenharmony_ci { 714b1b8bc3fSopenharmony_ci auto progType = ConvertEventToProgType(event); 715b1b8bc3fSopenharmony_ci if (progType < NETSYS_SUCCESS) { 716b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("unsupported program type: %{public}s", event.c_str()); 717b1b8bc3fSopenharmony_ci return false; 718b1b8bc3fSopenharmony_ci } 719b1b8bc3fSopenharmony_ci 720b1b8bc3fSopenharmony_ci if (insn == nullptr) { 721b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("insn is null"); 722b1b8bc3fSopenharmony_ci return false; 723b1b8bc3fSopenharmony_ci } 724b1b8bc3fSopenharmony_ci 725b1b8bc3fSopenharmony_ci std::string progName = event; 726b1b8bc3fSopenharmony_ci std::replace(progName.begin(), progName.end(), '/', '_'); 727b1b8bc3fSopenharmony_ci int32_t progFd = BpfLoadProgram(progName, progType, insn, insnCnt); 728b1b8bc3fSopenharmony_ci if (progFd < NETSYS_SUCCESS) { 729b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Failed to load bpf prog, error = %{public}d", errno); 730b1b8bc3fSopenharmony_ci return false; 731b1b8bc3fSopenharmony_ci } 732b1b8bc3fSopenharmony_ci 733b1b8bc3fSopenharmony_ci std::string progPinLocation = std::string(PROGS_DIR) + "/" + progName; 734b1b8bc3fSopenharmony_ci if (access(progPinLocation.c_str(), F_OK) == 0) { 735b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("prog: %{public}s has already been pinned", progPinLocation.c_str()); 736b1b8bc3fSopenharmony_ci } else { 737b1b8bc3fSopenharmony_ci if (SysBpfObjPin(progFd, progPinLocation) < NETSYS_SUCCESS) { 738b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Failed to pin prog: %{public}s, errno = %{public}d", progPinLocation.c_str(), errno); 739b1b8bc3fSopenharmony_ci close(progFd); 740b1b8bc3fSopenharmony_ci return false; 741b1b8bc3fSopenharmony_ci } 742b1b8bc3fSopenharmony_ci } 743b1b8bc3fSopenharmony_ci 744b1b8bc3fSopenharmony_ci /* attach socket filter */ 745b1b8bc3fSopenharmony_ci if (progType == BPF_PROG_TYPE_SOCKET_FILTER) { 746b1b8bc3fSopenharmony_ci if (g_sockFd < 0) { 747b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("create socket failed, %{public}d, err: %{public}d", g_sockFd, errno); 748b1b8bc3fSopenharmony_ci close(progFd); 749b1b8bc3fSopenharmony_ci /* return true to ignore this prog */ 750b1b8bc3fSopenharmony_ci return true; 751b1b8bc3fSopenharmony_ci } 752b1b8bc3fSopenharmony_ci if (setsockopt(g_sockFd, SOL_SOCKET, SO_ATTACH_BPF, &progFd, sizeof(progFd)) < 0) { 753b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("attach socket failed, err: %{public}d", errno); 754b1b8bc3fSopenharmony_ci close(g_sockFd); 755b1b8bc3fSopenharmony_ci g_sockFd = -1; 756b1b8bc3fSopenharmony_ci } 757b1b8bc3fSopenharmony_ci close(progFd); 758b1b8bc3fSopenharmony_ci return true; 759b1b8bc3fSopenharmony_ci } else { 760b1b8bc3fSopenharmony_ci auto ret = DoAttach(progFd, progName); 761b1b8bc3fSopenharmony_ci close(progFd); 762b1b8bc3fSopenharmony_ci return ret; 763b1b8bc3fSopenharmony_ci } 764b1b8bc3fSopenharmony_ci } 765b1b8bc3fSopenharmony_ci 766b1b8bc3fSopenharmony_ci bool ParseRelocation() 767b1b8bc3fSopenharmony_ci { 768b1b8bc3fSopenharmony_ci return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](auto §ion) -> bool { 769b1b8bc3fSopenharmony_ci if (section->get_type() != ELFIO::SHT_REL) { 770b1b8bc3fSopenharmony_ci return true; 771b1b8bc3fSopenharmony_ci } 772b1b8bc3fSopenharmony_ci 773b1b8bc3fSopenharmony_ci auto info = section->get_info(); 774b1b8bc3fSopenharmony_ci auto progSec = elfIo_.sections[info]; 775b1b8bc3fSopenharmony_ci if (progSec == nullptr) { 776b1b8bc3fSopenharmony_ci return true; 777b1b8bc3fSopenharmony_ci } 778b1b8bc3fSopenharmony_ci 779b1b8bc3fSopenharmony_ci if (progSec->get_type() != ELFIO::SHT_PROGBITS || ((progSec->get_flags() & ELFIO::SHF_EXECINSTR) == 0)) { 780b1b8bc3fSopenharmony_ci return true; 781b1b8bc3fSopenharmony_ci } 782b1b8bc3fSopenharmony_ci 783b1b8bc3fSopenharmony_ci auto insn = reinterpret_cast<bpf_insn *>(const_cast<char *>(progSec->get_data())); 784b1b8bc3fSopenharmony_ci if (insn == nullptr) { 785b1b8bc3fSopenharmony_ci return false; 786b1b8bc3fSopenharmony_ci } 787b1b8bc3fSopenharmony_ci if (!ApplyRelocation(insn, section.get())) { 788b1b8bc3fSopenharmony_ci return false; 789b1b8bc3fSopenharmony_ci } 790b1b8bc3fSopenharmony_ci return true; 791b1b8bc3fSopenharmony_ci }); 792b1b8bc3fSopenharmony_ci } 793b1b8bc3fSopenharmony_ci 794b1b8bc3fSopenharmony_ci bool UnloadProgs() 795b1b8bc3fSopenharmony_ci { 796b1b8bc3fSopenharmony_ci if (g_sockFd > 0) { 797b1b8bc3fSopenharmony_ci close(g_sockFd); 798b1b8bc3fSopenharmony_ci g_sockFd = -1; 799b1b8bc3fSopenharmony_ci } 800b1b8bc3fSopenharmony_ci return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](const auto §ion) -> bool { 801b1b8bc3fSopenharmony_ci if (!MatchSecName(section->get_name())) { 802b1b8bc3fSopenharmony_ci return true; 803b1b8bc3fSopenharmony_ci } 804b1b8bc3fSopenharmony_ci 805b1b8bc3fSopenharmony_ci std::string progName = section->get_name(); 806b1b8bc3fSopenharmony_ci std::replace(progName.begin(), progName.end(), '/', '_'); 807b1b8bc3fSopenharmony_ci std::string progPinLocation = std::string(PROGS_DIR) + "/" + progName; 808b1b8bc3fSopenharmony_ci if (access(progPinLocation.c_str(), F_OK) == 0) { 809b1b8bc3fSopenharmony_ci DoDetach(progPinLocation, progName); 810b1b8bc3fSopenharmony_ci 811b1b8bc3fSopenharmony_ci return UnPin(progPinLocation) < NETSYS_SUCCESS ? false : true; 812b1b8bc3fSopenharmony_ci } 813b1b8bc3fSopenharmony_ci return true; 814b1b8bc3fSopenharmony_ci }); 815b1b8bc3fSopenharmony_ci } 816b1b8bc3fSopenharmony_ci 817b1b8bc3fSopenharmony_ci bool LoadProgs() 818b1b8bc3fSopenharmony_ci { 819b1b8bc3fSopenharmony_ci if (g_sockFd > 0) { 820b1b8bc3fSopenharmony_ci close(g_sockFd); 821b1b8bc3fSopenharmony_ci } 822b1b8bc3fSopenharmony_ci g_sockFd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 823b1b8bc3fSopenharmony_ci return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](const auto §ion) -> bool { 824b1b8bc3fSopenharmony_ci if (!MatchSecName(section->get_name())) { 825b1b8bc3fSopenharmony_ci return true; 826b1b8bc3fSopenharmony_ci } 827b1b8bc3fSopenharmony_ci return LoadProg(section->get_name(), reinterpret_cast<const bpf_insn *>(section->get_data()), 828b1b8bc3fSopenharmony_ci section->get_size() / sizeof(bpf_insn)); 829b1b8bc3fSopenharmony_ci }); 830b1b8bc3fSopenharmony_ci } 831b1b8bc3fSopenharmony_ci 832b1b8bc3fSopenharmony_ci std::string path_; 833b1b8bc3fSopenharmony_ci ELFIO::elfio elfIo_; 834b1b8bc3fSopenharmony_ci std::string license_; 835b1b8bc3fSopenharmony_ci int32_t kernVersion_; 836b1b8bc3fSopenharmony_ci std::vector<BpfMapData> maps_; 837b1b8bc3fSopenharmony_ci 838b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> isPathValid_ = [this]() -> ElfLoadError { 839b1b8bc3fSopenharmony_ci if (!IsPathValid()) { 840b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_PATH_INVALID; 841b1b8bc3fSopenharmony_ci } 842b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 843b1b8bc3fSopenharmony_ci }; 844b1b8bc3fSopenharmony_ci 845b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> makeDirectories = []() -> ElfLoadError { 846b1b8bc3fSopenharmony_ci if (!MakeDirectories()) { 847b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_MAKE_DIR_FAIL; 848b1b8bc3fSopenharmony_ci } 849b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 850b1b8bc3fSopenharmony_ci }; 851b1b8bc3fSopenharmony_ci 852b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> loadElfFile_ = [this]() -> ElfLoadError { 853b1b8bc3fSopenharmony_ci if (!LoadElfFile()) { 854b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_LOAD_FILE_FAIL; 855b1b8bc3fSopenharmony_ci } 856b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 857b1b8bc3fSopenharmony_ci }; 858b1b8bc3fSopenharmony_ci 859b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> isVersionValid_ = [this]() -> ElfLoadError { 860b1b8bc3fSopenharmony_ci if (!IsVersionValid()) { 861b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_GET_VERSION_FAIL; 862b1b8bc3fSopenharmony_ci } 863b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 864b1b8bc3fSopenharmony_ci }; 865b1b8bc3fSopenharmony_ci 866b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> setLicenseAndVersion_ = [this]() -> ElfLoadError { 867b1b8bc3fSopenharmony_ci if (!SetLicenseAndVersion()) { 868b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_SELECT_LICENSE_AND_VERSION_FAIL; 869b1b8bc3fSopenharmony_ci } 870b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 871b1b8bc3fSopenharmony_ci }; 872b1b8bc3fSopenharmony_ci 873b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> loadElfMapsSection_ = [this]() -> ElfLoadError { 874b1b8bc3fSopenharmony_ci if (!LoadElfMapsSection()) { 875b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_LOAD_MAP_SECTION_FAIL; 876b1b8bc3fSopenharmony_ci } 877b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 878b1b8bc3fSopenharmony_ci }; 879b1b8bc3fSopenharmony_ci 880b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> setRlimit_ = []() -> ElfLoadError { 881b1b8bc3fSopenharmony_ci if (!SetRlimit()) { 882b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_SET_RLIMIT_FAIL; 883b1b8bc3fSopenharmony_ci } 884b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 885b1b8bc3fSopenharmony_ci }; 886b1b8bc3fSopenharmony_ci 887b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> createMaps_ = [this]() -> ElfLoadError { 888b1b8bc3fSopenharmony_ci if (!CreateMaps()) { 889b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_CREATE_MAP_FAIL; 890b1b8bc3fSopenharmony_ci } 891b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 892b1b8bc3fSopenharmony_ci }; 893b1b8bc3fSopenharmony_ci 894b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> parseRelocation_ = [this]() -> ElfLoadError { 895b1b8bc3fSopenharmony_ci if (!ParseRelocation()) { 896b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_PARSE_RELOCATION_FAIL; 897b1b8bc3fSopenharmony_ci } 898b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 899b1b8bc3fSopenharmony_ci }; 900b1b8bc3fSopenharmony_ci 901b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> loadProgs_ = [this]() -> ElfLoadError { 902b1b8bc3fSopenharmony_ci if (!LoadProgs()) { 903b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_LOAD_PROGS_FAIL; 904b1b8bc3fSopenharmony_ci } 905b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 906b1b8bc3fSopenharmony_ci }; 907b1b8bc3fSopenharmony_ci 908b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> deleteMaps_ = [this]() -> ElfLoadError { 909b1b8bc3fSopenharmony_ci if (!DeleteMaps()) { 910b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_DELETE_MAP_FAIL; 911b1b8bc3fSopenharmony_ci } 912b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 913b1b8bc3fSopenharmony_ci }; 914b1b8bc3fSopenharmony_ci 915b1b8bc3fSopenharmony_ci std::function<ElfLoadError()> unloadProgs_ = [this]() -> ElfLoadError { 916b1b8bc3fSopenharmony_ci if (!UnloadProgs()) { 917b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_UNLOAD_PROGS_FAIL; 918b1b8bc3fSopenharmony_ci } 919b1b8bc3fSopenharmony_ci return ELF_LOAD_ERR_NONE; 920b1b8bc3fSopenharmony_ci }; 921b1b8bc3fSopenharmony_ci}; 922b1b8bc3fSopenharmony_ci 923b1b8bc3fSopenharmony_ciElfLoadError LoadElf(const std::string &elfPath) 924b1b8bc3fSopenharmony_ci{ 925b1b8bc3fSopenharmony_ci ElfLoader loader(elfPath); 926b1b8bc3fSopenharmony_ci return loader.Load(); 927b1b8bc3fSopenharmony_ci} 928b1b8bc3fSopenharmony_ci 929b1b8bc3fSopenharmony_ciElfLoadError UnloadElf(const std::string &elfPath) 930b1b8bc3fSopenharmony_ci{ 931b1b8bc3fSopenharmony_ci ElfLoader loader(elfPath); 932b1b8bc3fSopenharmony_ci return loader.Unload(); 933b1b8bc3fSopenharmony_ci} 934b1b8bc3fSopenharmony_ci} // namespace OHOS::NetManagerStandard 935