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
45namespace OHOS {
46namespace Bpf {
47static 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
52static 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
61enum 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
75struct 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
85struct BpfMapData {
86    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
96class BpfLoader {
97public:
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
110private:
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