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