1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef NETD_SERVER_TRAFFIC_CONTROLLER_H 18 #define NETD_SERVER_TRAFFIC_CONTROLLER_H 19 20 #include <linux/bpf.h> 21 22 #include "BandwidthController.h" 23 #include "FirewallController.h" 24 #include "NetlinkListener.h" 25 #include "Network.h" 26 #include "android-base/thread_annotations.h" 27 #include "android-base/unique_fd.h" 28 #include "bpf/BpfMap.h" 29 #include "netdbpf/bpf_shared.h" 30 #include "netdutils/DumpWriter.h" 31 #include "netdutils/StatusOr.h" 32 #include "utils/String16.h" 33 34 using android::bpf::BpfMap; 35 36 namespace android { 37 namespace net { 38 39 class TrafficController { 40 public: 41 TrafficController(); 42 /* 43 * Initialize the whole controller 44 */ 45 netdutils::Status start(); 46 /* 47 * Tag the socket with the specified tag and uid. In the qtaguid module, the 48 * first tag request that grab the spinlock of rb_tree can update the tag 49 * information first and other request need to wait until it finish. All the 50 * tag request will be addressed in the order of they obtaining the spinlock. 51 * In the eBPF implementation, the kernel will try to update the eBPF map 52 * entry with the tag request. And the hashmap update process is protected by 53 * the spinlock initialized with the map. So the behavior of two modules 54 * should be the same. No additional lock needed. 55 */ 56 int tagSocket(int sockFd, uint32_t tag, uid_t uid, uid_t callingUid) EXCLUDES(mMutex); 57 58 /* 59 * The untag process is similiar to tag socket and both old qtaguid module and 60 * new eBPF module have spinlock inside the kernel for concurrent update. No 61 * external lock is required. 62 */ 63 int untagSocket(int sockFd); 64 65 /* 66 * Similiar as above, no external lock required. 67 */ 68 int setCounterSet(int counterSetNum, uid_t uid, uid_t callingUid) EXCLUDES(mMutex); 69 70 /* 71 * When deleting a tag data, the qtaguid module will grab the spinlock of each 72 * related rb_tree one by one and delete the tag information, counterSet 73 * information, iface stats information and uid stats information one by one. 74 * The new eBPF implementation is done similiarly by removing the entry on 75 * each map one by one. And deleting processes are also protected by the 76 * spinlock of the map. So no additional lock is required. 77 */ 78 int deleteTagData(uint32_t tag, uid_t uid, uid_t callingUid) EXCLUDES(mMutex); 79 80 /* 81 * Check if the current device have the bpf traffic stats accounting service 82 * running. 83 */ 84 bool getBpfEnabled(); 85 86 /* 87 * Swap the stats map config from current active stats map to the idle one. 88 */ 89 netdutils::Status swapActiveStatsMap() EXCLUDES(mMutex); 90 91 /* 92 * Add the interface name and index pair into the eBPF map. 93 */ 94 int addInterface(const char* name, uint32_t ifaceIndex); 95 96 int changeUidOwnerRule(ChildChain chain, const uid_t uid, FirewallRule rule, FirewallType type); 97 98 int removeUidOwnerRule(const uid_t uid); 99 100 int replaceUidOwnerMap(const std::string& name, bool isAllowlist, 101 const std::vector<int32_t>& uids); 102 103 netdutils::Status updateOwnerMapEntry(UidOwnerMatchType match, uid_t uid, FirewallRule rule, 104 FirewallType type) EXCLUDES(mMutex); 105 106 void dump(netdutils::DumpWriter& dw, bool verbose) EXCLUDES(mMutex); 107 108 netdutils::Status replaceRulesInMap(UidOwnerMatchType match, const std::vector<int32_t>& uids) 109 EXCLUDES(mMutex); 110 111 netdutils::Status addUidInterfaceRules(const int ifIndex, const std::vector<int32_t>& uids) 112 EXCLUDES(mMutex); 113 netdutils::Status removeUidInterfaceRules(const std::vector<int32_t>& uids) EXCLUDES(mMutex); 114 115 netdutils::Status updateUidOwnerMap(const std::vector<std::string>& appStrUids, 116 BandwidthController::IptJumpOp jumpHandling, 117 BandwidthController::IptOp op) EXCLUDES(mMutex); 118 static const String16 DUMP_KEYWORD; 119 120 int toggleUidOwnerMap(ChildChain chain, bool enable) EXCLUDES(mMutex); 121 122 static netdutils::StatusOr<std::unique_ptr<NetlinkListenerInterface>> makeSkDestroyListener(); 123 124 void setPermissionForUids(int permission, const std::vector<uid_t>& uids) EXCLUDES(mMutex); 125 126 private: 127 /* 128 * mCookieTagMap: Store the corresponding tag and uid for a specific socket. 129 * DO NOT hold any locks when modifying this map, otherwise when the untag 130 * operation is waiting for a lock hold by other process and there are more 131 * sockets being closed than can fit in the socket buffer of the netlink socket 132 * that receives them, then the kernel will drop some of these sockets and we 133 * won't delete their tags. 134 * Map Key: uint64_t socket cookie 135 * Map Value: UidTagValue, contains a uint32 uid and a uint32 tag. 136 */ 137 BpfMap<uint64_t, UidTagValue> mCookieTagMap GUARDED_BY(mMutex); 138 139 /* 140 * mUidCounterSetMap: Store the counterSet of a specific uid. 141 * Map Key: uint32 uid. 142 * Map Value: uint32 counterSet specifies if the traffic is a background 143 * or foreground traffic. 144 */ 145 BpfMap<uint32_t, uint8_t> mUidCounterSetMap GUARDED_BY(mMutex); 146 147 /* 148 * mAppUidStatsMap: Store the total traffic stats for a uid regardless of 149 * tag, counterSet and iface. The stats is used by TrafficStats.getUidStats 150 * API to return persistent stats for a specific uid since device boot. 151 */ 152 BpfMap<uint32_t, StatsValue> mAppUidStatsMap; 153 154 /* 155 * mStatsMapA/mStatsMapB: Store the traffic statistics for a specific 156 * combination of uid, tag, iface and counterSet. These two maps contain 157 * both tagged and untagged traffic. 158 * Map Key: StatsKey contains the uid, tag, counterSet and ifaceIndex 159 * information. 160 * Map Value: Stats, contains packet count and byte count of each 161 * transport protocol on egress and ingress direction. 162 */ 163 BpfMap<StatsKey, StatsValue> mStatsMapA GUARDED_BY(mMutex); 164 165 BpfMap<StatsKey, StatsValue> mStatsMapB GUARDED_BY(mMutex); 166 167 /* 168 * mIfaceIndexNameMap: Store the index name pair of each interface show up 169 * on the device since boot. The interface index is used by the eBPF program 170 * to correctly match the iface name when receiving a packet. 171 */ 172 BpfMap<uint32_t, IfaceValue> mIfaceIndexNameMap; 173 174 /* 175 * mIfaceStataMap: Store per iface traffic stats gathered from xt_bpf 176 * filter. 177 */ 178 BpfMap<uint32_t, StatsValue> mIfaceStatsMap; 179 180 /* 181 * mConfigurationMap: Store the current network policy about uid filtering 182 * and the current stats map in use. There are two configuration entries in 183 * the map right now: 184 * - Entry with UID_RULES_CONFIGURATION_KEY: 185 * Store the configuration for the current uid rules. It indicates the device 186 * is in doze/powersave/standby mode. 187 * - Entry with CURRENT_STATS_MAP_CONFIGURATION_KEY: 188 * Stores the current live stats map that kernel program is writing to. 189 * Userspace can do scraping and cleaning job on the other one depending on the 190 * current configs. 191 */ 192 BpfMap<uint32_t, uint8_t> mConfigurationMap GUARDED_BY(mMutex); 193 194 /* 195 * mUidOwnerMap: Store uids that are used for bandwidth control uid match. 196 */ 197 BpfMap<uint32_t, UidOwnerValue> mUidOwnerMap GUARDED_BY(mMutex); 198 199 /* 200 * mUidOwnerMap: Store uids that are used for INTERNET permission check. 201 */ 202 BpfMap<uint32_t, uint8_t> mUidPermissionMap GUARDED_BY(mMutex); 203 204 std::unique_ptr<NetlinkListenerInterface> mSkDestroyListener; 205 206 netdutils::Status removeRule(uint32_t uid, UidOwnerMatchType match) REQUIRES(mMutex); 207 208 netdutils::Status addRule(uint32_t uid, UidOwnerMatchType match, uint32_t iif = 0) 209 REQUIRES(mMutex); 210 211 bool mBpfEnabled; 212 213 // mMutex guards all accesses to mConfigurationMap, mUidOwnerMap, mUidPermissionMap, 214 // mStatsMapA, mStatsMapB and mPrivilegedUser. It is designed to solve the following 215 // problems: 216 // 1. Prevent concurrent access and modification to mConfigurationMap, mUidOwnerMap, 217 // mUidPermissionMap, and mPrivilegedUser. These data members are controlled by netd but can 218 // be modified from different threads. TrafficController provides several APIs directly 219 // called by the binder RPC, and different binder threads can concurrently access these data 220 // members mentioned above. Some of the data members such as mUidPermissionMap and 221 // mPrivilegedUsers are also accessed from a different thread when tagging sockets or 222 // setting the counterSet through FwmarkServer 223 // 2. Coordinate the deletion of uid stats in mStatsMapA and mStatsMapB. The system server 224 // always call into netd to ask for a live stats map change before it pull and clean up the 225 // stats from the inactive map. The mMutex will block netd from accessing the stats map when 226 // the mConfigurationMap is updating the current stats map so netd will not accidentally 227 // read the map that system_server is cleaning up. 228 std::mutex mMutex; 229 230 // The limit on the number of stats entries a uid can have in the per uid stats map. 231 // TrafficController will block that specific uid from tagging new sockets after the limit is 232 // reached. 233 const uint32_t mPerUidStatsEntriesLimit; 234 235 // The limit on the total number of stats entries in the per uid stats map. TrafficController 236 // will block all tagging requests after the limit is reached. 237 const uint32_t mTotalUidStatsEntriesLimit; 238 239 netdutils::Status loadAndAttachProgram(bpf_attach_type type, const char* path, const char* name, 240 base::unique_fd& cg_fd); 241 242 netdutils::Status initMaps() EXCLUDES(mMutex); 243 244 // Keep track of uids that have permission UPDATE_DEVICE_STATS so we don't 245 // need to call back to system server for permission check. 246 std::set<uid_t> mPrivilegedUser GUARDED_BY(mMutex); 247 248 UidOwnerMatchType jumpOpToMatch(BandwidthController::IptJumpOp jumpHandling); 249 250 bool hasUpdateDeviceStatsPermission(uid_t uid) REQUIRES(mMutex); 251 252 // For testing 253 TrafficController(uint32_t perUidLimit, uint32_t totalLimit); 254 255 // For testing 256 friend class TrafficControllerTest; 257 }; 258 259 } // namespace net 260 } // namespace android 261 262 #endif // NETD_SERVER_TRAFFIC_CONTROLLER_H 263