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 /** 66 * @brief Callback impl for LoadSystemAbility 67 */ 68 class OnDemandLoadManagerCallback : public SystemAbilityLoadCallbackStub { 69 public: 70 /** 71 * called when load SA success 72 * 73 * @param systemAbilityId id of SA which was loaded 74 * @param remoteObject poniter of IRemoteObject 75 */ 76 void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject) override; 77 78 /** 79 * called when load SA fail 80 * 81 * @param systemAbilityId id of SA which was loaded 82 */ 83 void OnLoadSystemAbilityFail(int32_t systemAbilityId) override; 84 }; 85 86 /** 87 * Class for setup bpf maps and poll event from bpf ring buffer 88 */ 89 class NetsysBpfNetFirewall : public NoCopyable { 90 public: 91 static std::shared_ptr<NetsysBpfNetFirewall> GetInstance(); 92 93 /** 94 * start to listen bpf ring buffer 95 * 96 * @return 0 if success or -1 if an error occurred 97 */ 98 int32_t StartListener(); 99 100 /* * 101 * @brief stop listen bpf ring buffer 102 * 103 * @return 0 if success or -1 if an error occurred 104 */ 105 int32_t StopListener(); 106 107 /** 108 * Set firewall rules to native 109 * 110 * @param ruleList list of NetFirewallIpRule 111 * @param isFinish transmit finish or not 112 * @return 0 if success or -1 if an error occurred 113 */ 114 int32_t SetFirewallRules(const std::vector<sptr<NetFirewallBaseRule>> &ruleList, bool isFinish); 115 116 /** 117 * Set firewall default action 118 * 119 * @param inDefault Default action of NetFirewallRuleDirection:RULE_IN 120 * @param outDefault Default action of NetFirewallRuleDirection:RULE_OUT 121 * @return 0 if success or -1 if an error occurred 122 */ 123 int32_t SetFirewallDefaultAction(FirewallRuleAction inDefault, FirewallRuleAction outDefault); 124 125 /** 126 * Set firewall current user id 127 * 128 * @param userId current user id 129 * @return 0 if success or -1 if an error occurred 130 */ 131 int32_t SetFirewallCurrentUserId(int32_t userId); 132 133 /** 134 * Clear all bpf maps 135 * 136 * @return 0 if success or -1 if an error occurred 137 */ 138 int32_t ClearFirewallRules(); 139 140 /** 141 * Register callback for recevie intercept event 142 * 143 * @param callback implement of INetFirewallCallback 144 * @return 0 if success or -1 if an error occurred 145 */ 146 int32_t RegisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback); 147 148 /** 149 * Unregister callback for recevie intercept event 150 * 151 * @param callback register callback for recevie intercept event 152 * @return 0 if success or -1 if an error occurred 153 */ 154 int32_t UnregisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback); 155 156 /** 157 * Load SA on demand 158 * 159 * @param systemAbilityId id of SA want to load 160 * @return 0 if success or -1 if an error occurred 161 */ 162 int32_t LoadSystemAbility(int32_t systemAbilityId); 163 164 /** 165 * Set bpf prog load state 166 * 167 * @param load true if load success or false if an error occurred 168 */ 169 void SetBpfLoaded(bool load); 170 171 /** 172 * Get bpf prog load state 173 */ IsBpfLoaded()174 bool IsBpfLoaded() 175 { 176 return isBpfLoaded_; 177 } 178 179 private: ClearBpfMap(const char * path,const Key & key,Value & val)180 template <typename Key, typename Value> int ClearBpfMap(const char *path, const Key &key, Value &val) 181 { 182 (void)key; 183 (void)val; 184 BpfMapper<Key, Value> rdMap(path, BPF_F_RDONLY); 185 if (!rdMap.IsValid()) { 186 return -1; 187 } 188 std::vector<Key> keys = rdMap.GetAllKeys(); 189 if (keys.empty()) { 190 NETNATIVE_LOG_D("ClearBpfMap: key is empty"); 191 return 0; 192 } 193 BpfMapper<Key, Value> wrMap(path, BPF_F_WRONLY); 194 if (!wrMap.IsValid()) { 195 NETNATIVE_LOGE("ClearBpfMap: wrMap is invalid"); 196 return -1; 197 } 198 if (wrMap.Clear(keys) != 0) { 199 NETNATIVE_LOGE("ClearBpfMap: clear failed"); 200 return -1; 201 } 202 203 return 0; 204 } 205 WriteBpfMap(const char * path,const Key & key,Value & val)206 template <typename Key, typename Value> int WriteBpfMap(const char *path, const Key &key, Value &val) 207 { 208 BpfMapper<Key, Value> map(path, BPF_F_WRONLY); 209 if (!map.IsValid()) { 210 NETNATIVE_LOGE("WriteBpfMap: map invalid: %{public}s", path); 211 return -1; 212 } 213 214 if (map.Write(key, val, BPF_ANY) != 0) { 215 NETNATIVE_LOGE("WriteBpfMap: map write failed"); 216 return -1; 217 } 218 219 return 0; 220 } 221 222 NetsysBpfNetFirewall(); 223 224 static void StartConntrackGcThread(void); 225 226 static void RingBufferListenThread(void); 227 228 void StopConntrackGc(); 229 230 static int HandleEvent(void *ctx, void *data, size_t len); 231 232 static void HandleTupleEvent(TupleEvent *ev); 233 234 static void HandleInterceptEvent(InterceptEvent *ev); 235 236 static void HandleDebugEvent(DebugEvent *ev); 237 238 bool ShouldSkipNotify(sptr<InterceptRecord> record); 239 240 void NotifyInterceptEvent(InterceptEvent *info); 241 242 static void ConntrackGcTask(); 243 244 void ClearBpfFirewallRules(NetFirewallRuleDirection direction); 245 246 void WriteSrcIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 247 248 void WriteSrcIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 249 250 void WriteDstIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 251 252 void WriteDstIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 253 254 void WriteSrcPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 255 256 void WriteDstPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 257 258 void WriteProtoBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 259 260 void WriteAppUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 261 262 void WriteUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 263 264 void WriteActionBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction); 265 266 int32_t SetBpfFirewallRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList, 267 NetFirewallRuleDirection direction); 268 269 int32_t SetFirewallIpRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList); 270 271 static std::shared_ptr<NetsysBpfNetFirewall> instance_; 272 static bool isBpfLoaded_; 273 static bool keepListen_; 274 std::unique_ptr<std::thread> thread_; 275 std::vector<sptr<NetsysNative::INetFirewallCallback>> callbacks_; 276 sptr<InterceptRecord> oldRecord_ = nullptr; 277 static bool keepGc_; 278 std::unique_ptr<std::thread> gcThread_; 279 static std::unique_ptr<BpfMapper<CtKey, CtVaule>> ctRdMap_, ctWrMap_; 280 std::vector<sptr<NetFirewallIpRule>> firewallIpRules_; 281 }; 282 } // namespace OHOS::NetManagerStandard 283 #endif /* NETMANAGER_EXT_BPF_NET_FIREWALL_H */ 284