1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef NETMANAGER_BASE_BPF_LOADER_H
17 #define NETMANAGER_BASE_BPF_LOADER_H
18 
19 #include <cerrno>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <fcntl.h>
23 #include <filesystem>
24 #include <fstream>
25 #include <functional>
26 #include <linux/bpf.h>
27 #include <linux/rtnetlink.h>
28 #include <linux/types.h>
29 #include <memory.h>
30 #include <net/if.h>
31 #include <string>
32 #include <sys/mount.h>
33 #include <sys/resource.h>
34 #include <sys/socket.h>
35 #include <sys/syscall.h>
36 #include <unistd.h>
37 #include <vector>
38 
39 #include "securec.h"
40 
41 #include "elf_types.hpp"
42 #include "elfio.hpp"
43 #include "elfio_relocation.hpp"
44 
45 namespace OHOS {
46 namespace Bpf {
47 static constexpr const char *SECTION_NAMES[] = {
48     "kprobe/", "kretprobe/", "tracepoint/", "raw_tracepoint/", "xdp",        "perf_event/",       "socket",
49     "cgroup/", "sockops",    "sk_skb",      "sk_msg",          "cgroup_skb", "xdp_packet_parser",
50 };
51 
52 static constexpr struct {
53     const char *event;
54     bpf_prog_type progType;
55 } PROG_TYPES[] = {
56     {"socket", BPF_PROG_TYPE_SOCKET_FILTER},
57     {"cgroup_skb", BPF_PROG_TYPE_CGROUP_SKB},
58     {"xdp_packet_parser", BPF_PROG_TYPE_XDP},
59 };
60 
61 enum ELfLoadError {
62     ELF_LOAD_ERR_NONE = 0,
63     ELF_LOAD_ERR_PATH_INVALID,
64     ELF_LOAD_ERR_MOUNT_FAIL,
65     ELF_LOAD_ERR_LOAD_FILE_FAIL,
66     ELF_LOAD_ERR_GET_VERSION_FAIL,
67     ELF_LOAD_ERR_SELECT_LICENSE_AND_VERSION_FAIL,
68     ELF_LOAD_ERR_LOAD_MAP_SECTION_FAIL,
69     ELF_LOAD_ERR_SET_RLIMIT_FAIL,
70     ELF_LOAD_ERR_CREATE_MAP_FAIL,
71     ELF_LOAD_ERR_PARSE_RELOCATION_FAIL,
72     ELF_LOAD_ERR_LOAD_PROGS_FAIL,
73 };
74 
75 struct BpfLoadMapDef {
76     unsigned int type; // actual type is bpf_map_type
77     unsigned int keySize;
78     unsigned int valueSize;
79     unsigned int maxEntries;
80     unsigned int mapFlags;
81     unsigned int innerMapIdx;
82     unsigned int numaNode;
83 };
84 
85 struct BpfMapData {
BpfMapDataBpfMapData86     BpfMapData() : fd(0)
87     {
88         (void)memset_s(&def, sizeof(def), 0, sizeof(def));
89     }
90 
91     int32_t fd;
92     std::string name;
93     BpfLoadMapDef def{};
94 };
95 
96 class BpfLoader {
97 public:
98     /**
99      * Construct a BpfLoader object
100      * @param path the .o file which is need to be loaded
101      */
102     explicit BpfLoader(std::string path);
103 
104     /**
105      * Load the file specified in path_.
106      * @return return ELF_LOAD_ERR_NONE if no error.
107      */
108     ELfLoadError Load();
109 
110 private:
111     bool CheckPath();
112 
113     bool IsPathValid();
114 
115     bool LoadElfFile();
116 
117     bool IsVersionValid();
118 
119     bool SetRlimit();
120 
121     bool IsMouted(const std::string &dir);
122 
123     bool MountFs();
124 
125     bool SetLicenseAndVersion();
126 
127     bool LoadElfMapsSection();
128 
129     bool CreateMaps();
130 
131     bool ApplyRelocation(bpf_insn *insn, ELFIO::section *section);
132 
133     bool LoadProg(const std::string &event, const bpf_insn *insn, size_t insnCnt);
134 
135     bool ParseRelocation();
136 
137     bool LoadProgs();
138 
139     int32_t BpfCreateMapNode(const BpfMapData &map);
140 
141     int32_t BpfLoadProgram(bpf_prog_type type, const bpf_insn *insns, size_t insnsCnt);
142 
143     bpf_prog_type ConvertEventToProgType(const std::string &event);
144 
145     std::string path_;
146     ELFIO::elfio elfIo_;
147     std::string license_;
148     int32_t kernVersion_;
149     std::vector<BpfMapData> maps_;
150     std::function<ELfLoadError()> isPathValid_;
151     std::function<ELfLoadError()> mountFs_;
152     std::function<ELfLoadError()> loadElfFile_;
153     std::function<ELfLoadError()> isVersionValid_;
154     std::function<ELfLoadError()> setLicenseAndVersion_;
155     std::function<ELfLoadError()> loadElfMapsSection_;
156     std::function<ELfLoadError()> setRlimit_;
157     std::function<ELfLoadError()> createMaps_;
158     std::function<ELfLoadError()> parseRelocation_;
159     std::function<ELfLoadError()> loadProgs_;
160 };
161 } // namespace Bpf
162 } // namespace OHOS
163 #endif /* NETMANAGER_BASE_BPF_LOADER_H */
164