1 /*
2  * Copyright (c) 2024 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_EXT_BPF_NET_FIREWALL_H
17 #define NETMANAGER_EXT_BPF_NET_FIREWALL_H
18 
19 #include <netdb.h>
20 #include <string>
21 #include <thread>
22 #include <unordered_map>
23 #include <chrono>
24 #include <functional>
25 
26 #include "bitmap_manager.h"
27 #include "bpf_mapper.h"
28 #include "i_netfirewall_callback.h"
29 #include "netfirewall/netfirewall_def.h"
30 #include "netfirewall_parcel.h"
31 #include "system_ability.h"
32 #include "system_ability_load_callback_stub.h"
33 
34 namespace OHOS::NetManagerStandard {
35 // Only used for unittest code currently
36 static constexpr const char *FIREWALL_BPF_PATH = "/system/etc/bpf/netsys.o";
37 
38 static constexpr const int CONNTRACK_GC_INTTERVAL_MS = 60000;
39 static constexpr const int RING_BUFFER_POLL_TIME_OUT_MS = -1;
40 
41 // convert ebpf types from unix style style to CPP's
42 using Ip4Key = ip4_key;
43 using Ip6Key = ip6_key;
44 using Ipv4LpmKey = struct ipv4_lpm_key;
45 using Ipv6LpmKey = struct ipv6_lpm_key;
46 using PortKey = port_key;
47 using ProtoKey = proto_key;
48 using AppUidKey = appuid_key;
49 using DefaultActionKey = default_action_key;
50 using CurrentUserIdKey = current_user_id_key;
51 using ActionKey = action_key;
52 using ActionValue = action_val;
53 using RuleCode = struct bitmap;
54 using StreamDir = enum stream_dir;
55 using EventType = enum event_type;
56 using Event = struct event;
57 using InterceptEvent = struct intercept_event;
58 using DebugEvent = struct debug_event;
59 using TupleEvent = struct match_tuple;
60 using DebugType = enum debug_type;
61 
62 using CtKey = struct ct_tuple;
63 using CtVaule = struct ct_entry;
64 
65 struct NetAddrInfo {
66     uint32_t aiFamily;
67     union {
68         struct in_addr sin;
69         struct in6_addr sin6;
70     } aiAddr;
71 };
72 
73 /**
74  * @brief Callback impl for LoadSystemAbility
75  */
76 class OnDemandLoadManagerCallback : public SystemAbilityLoadCallbackStub {
77 public:
78     /**
79      * called when load SA success
80      *
81      * @param systemAbilityId id of SA which was loaded
82      * @param remoteObject poniter of IRemoteObject
83      */
84     void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject) override;
85 
86     /**
87      * called when load SA fail
88      *
89      * @param systemAbilityId id of SA which was loaded
90      */
91     void OnLoadSystemAbilityFail(int32_t systemAbilityId) override;
92 };
93 
94 /**
95  * Class for setup bpf maps and poll event from bpf ring buffer
96  */
97 class NetsysBpfNetFirewall : public NoCopyable {
98 public:
99     static std::shared_ptr<NetsysBpfNetFirewall> GetInstance();
100 
101     /**
102      * start to listen bpf ring buffer
103      *
104      * @return 0 if success or -1 if an error occurred
105      */
106     int32_t StartListener();
107 
108     /* *
109      * @brief stop listen bpf ring buffer
110      *
111      * @return 0 if success or -1 if an error occurred
112      */
113     int32_t StopListener();
114 
115     /**
116      * Set firewall rules to native
117      *
118      * @param ruleList list of NetFirewallIpRule
119      * @param isFinish transmit finish or not
120      * @return 0 if success or -1 if an error occurred
121      */
122     int32_t SetFirewallRules(const std::vector<sptr<NetFirewallBaseRule>> &ruleList, bool isFinish);
123 
124     /**
125      * Set firewall default action
126      *
127      * @param inDefault  Default action of NetFirewallRuleDirection:RULE_IN
128      * @param outDefault Default action of NetFirewallRuleDirection:RULE_OUT
129      * @return  0 if success or -1 if an error occurred
130      */
131     int32_t SetFirewallDefaultAction(FirewallRuleAction inDefault, FirewallRuleAction outDefault);
132 
133     /**
134      * Set firewall current user id
135      *
136      * @param userId current user id
137      * @return 0 if success or -1 if an error occurred
138      */
139     int32_t SetFirewallCurrentUserId(int32_t userId);
140 
141     /**
142      * Clear all bpf maps
143      *
144      * @return  0 if success or -1 if an error occurred
145      */
146     int32_t ClearFirewallRules();
147 
148     /**
149      * Register callback for recevie intercept event
150      *
151      * @param callback implement of INetFirewallCallback
152      * @return 0 if success or -1 if an error occurred
153      */
154     int32_t RegisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback);
155 
156     /**
157      * Unregister callback for recevie intercept event
158      *
159      * @param callback register callback for recevie intercept event
160      * @return 0 if success or -1 if an error occurred
161      */
162     int32_t UnregisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback);
163 
164     /**
165      * Load SA on demand
166      *
167      * @param systemAbilityId id of SA want to load
168      * @return 0 if success or -1 if an error occurred
169      */
170     int32_t LoadSystemAbility(int32_t systemAbilityId);
171 
172     /**
173      * Set bpf prog load state
174      *
175      * @param load true if load success or false if an error occurred
176      */
177     void SetBpfLoaded(bool load);
178 
179     /**
180      * Get bpf prog load state
181      */
IsBpfLoaded()182     bool IsBpfLoaded()
183     {
184         return isBpfLoaded_;
185     }
186 
187     void AddDomainCache(const NetAddrInfo &addrInfo);
188     void ClearDomainCache();
189 
190 private:
ClearBpfMap(const char *path, const Key &key, Value &val)191     template <typename Key, typename Value> int ClearBpfMap(const char *path, const Key &key, Value &val)
192     {
193         (void)key;
194         (void)val;
195         BpfMapper<Key, Value> rdMap(path, BPF_F_RDONLY);
196         if (!rdMap.IsValid()) {
197             return -1;
198         }
199         std::vector<Key> keys = rdMap.GetAllKeys();
200         if (keys.empty()) {
201             return 0;
202         }
203         BpfMapper<Key, Value> wrMap(path, BPF_F_WRONLY);
204         if (!wrMap.IsValid()) {
205             NETNATIVE_LOGE("ClearBpfMap: wrMap is invalid");
206             return -1;
207         }
208         if (wrMap.Clear(keys) != 0) {
209             NETNATIVE_LOGE("ClearBpfMap: clear failed");
210             return -1;
211         }
212 
213         return 0;
214     }
215 
WriteBpfMap(const char *path, const Key &key, Value &val)216     template <typename Key, typename Value> int WriteBpfMap(const char *path, const Key &key, Value &val)
217     {
218         BpfMapper<Key, Value> map(path, BPF_F_WRONLY);
219         if (!map.IsValid()) {
220             NETNATIVE_LOGE("WriteBpfMap: map invalid: %{public}s", path);
221             return -1;
222         }
223 
224         if (map.Write(key, val, BPF_ANY) != 0) {
225             NETNATIVE_LOGE("WriteBpfMap: map write failed");
226             return -1;
227         }
228 
229         return 0;
230     }
231 
232     NetsysBpfNetFirewall();
233 
234     static void StartConntrackGcThread(void);
235 
236     static void RingBufferListenThread(void);
237 
238     void StopConntrackGc();
239 
240     static int HandleEvent(void *ctx, void *data, size_t len);
241 
242     static void HandleTupleEvent(TupleEvent *ev);
243 
244     static void HandleInterceptEvent(InterceptEvent *ev);
245 
246     static void HandleDebugEvent(DebugEvent *ev);
247 
248     bool ShouldSkipNotify(sptr<InterceptRecord> record);
249 
250     void NotifyInterceptEvent(InterceptEvent *info);
251 
252     static void ConntrackGcTask();
253 
254     void ClearBpfFirewallRules(NetFirewallRuleDirection direction);
255 
256     void WriteSrcIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
257 
258     void WriteSrcIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
259 
260     void WriteDstIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
261 
262     void WriteDstIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
263 
264     void WriteSrcPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
265 
266     void WriteDstPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
267 
268     void WriteProtoBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
269 
270     void WriteAppUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
271 
272     void WriteUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
273 
274     void WriteActionBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
275 
276     int32_t SetBpfFirewallRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList,
277         NetFirewallRuleDirection direction);
278 
279     int32_t SetFirewallIpRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList);
280 
281     static std::shared_ptr<NetsysBpfNetFirewall> instance_;
282     static bool isBpfLoaded_;
283     static bool keepListen_;
284     std::unique_ptr<std::thread> thread_;
285     std::vector<sptr<NetsysNative::INetFirewallCallback>> callbacks_;
286     sptr<InterceptRecord> oldRecord_ = nullptr;
287     static bool keepGc_;
288     std::unique_ptr<std::thread> gcThread_;
289     static std::unique_ptr<BpfMapper<CtKey, CtVaule>> ctRdMap_, ctWrMap_;
290     std::vector<sptr<NetFirewallIpRule>> firewallIpRules_;
291 };
292 } // namespace OHOS::NetManagerStandard
293 #endif /* NETMANAGER_EXT_BPF_NET_FIREWALL_H */
294