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 * Swap the stats map config from current active stats map to the idle one. 82 */ 83 netdutils::Status swapActiveStatsMap() EXCLUDES(mMutex); 84 85 /* 86 * Add the interface name and index pair into the eBPF map. 87 */ 88 int addInterface(const char* name, uint32_t ifaceIndex); 89 90 int changeUidOwnerRule(ChildChain chain, const uid_t uid, FirewallRule rule, FirewallType type); 91 92 int removeUidOwnerRule(const uid_t uid); 93 94 int replaceUidOwnerMap(const std::string& name, bool isAllowlist, 95 const std::vector<int32_t>& uids); 96 97 netdutils::Status updateOwnerMapEntry(UidOwnerMatchType match, uid_t uid, FirewallRule rule, 98 FirewallType type) EXCLUDES(mMutex); 99 100 void dump(netdutils::DumpWriter& dw, bool verbose) EXCLUDES(mMutex); 101 102 netdutils::Status replaceRulesInMap(UidOwnerMatchType match, const std::vector<int32_t>& uids) 103 EXCLUDES(mMutex); 104 105 netdutils::Status addUidInterfaceRules(const int ifIndex, const std::vector<int32_t>& uids) 106 EXCLUDES(mMutex); 107 netdutils::Status removeUidInterfaceRules(const std::vector<int32_t>& uids) EXCLUDES(mMutex); 108 109 netdutils::Status updateUidOwnerMap(const std::vector<uint32_t>& appStrUids, 110 UidOwnerMatchType matchType, BandwidthController::IptOp op) 111 EXCLUDES(mMutex); 112 static const String16 DUMP_KEYWORD; 113 114 int toggleUidOwnerMap(ChildChain chain, bool enable) EXCLUDES(mMutex); 115 116 static netdutils::StatusOr<std::unique_ptr<NetlinkListenerInterface>> makeSkDestroyListener(); 117 118 void setPermissionForUids(int permission, const std::vector<uid_t>& uids) EXCLUDES(mMutex); 119 120 private: 121 /* 122 * mCookieTagMap: Store the corresponding tag and uid for a specific socket. 123 * DO NOT hold any locks when modifying this map, otherwise when the untag 124 * operation is waiting for a lock hold by other process and there are more 125 * sockets being closed than can fit in the socket buffer of the netlink socket 126 * that receives them, then the kernel will drop some of these sockets and we 127 * won't delete their tags. 128 * Map Key: uint64_t socket cookie 129 * Map Value: UidTagValue, contains a uint32 uid and a uint32 tag. 130 */ 131 BpfMap<uint64_t, UidTagValue> mCookieTagMap GUARDED_BY(mMutex); 132 133 /* 134 * mUidCounterSetMap: Store the counterSet of a specific uid. 135 * Map Key: uint32 uid. 136 * Map Value: uint32 counterSet specifies if the traffic is a background 137 * or foreground traffic. 138 */ 139 BpfMap<uint32_t, uint8_t> mUidCounterSetMap GUARDED_BY(mMutex); 140 141 /* 142 * mAppUidStatsMap: Store the total traffic stats for a uid regardless of 143 * tag, counterSet and iface. The stats is used by TrafficStats.getUidStats 144 * API to return persistent stats for a specific uid since device boot. 145 */ 146 BpfMap<uint32_t, StatsValue> mAppUidStatsMap; 147 148 /* 149 * mStatsMapA/mStatsMapB: Store the traffic statistics for a specific 150 * combination of uid, tag, iface and counterSet. These two maps contain 151 * both tagged and untagged traffic. 152 * Map Key: StatsKey contains the uid, tag, counterSet and ifaceIndex 153 * information. 154 * Map Value: Stats, contains packet count and byte count of each 155 * transport protocol on egress and ingress direction. 156 */ 157 BpfMap<StatsKey, StatsValue> mStatsMapA GUARDED_BY(mMutex); 158 159 BpfMap<StatsKey, StatsValue> mStatsMapB GUARDED_BY(mMutex); 160 161 /* 162 * mIfaceIndexNameMap: Store the index name pair of each interface show up 163 * on the device since boot. The interface index is used by the eBPF program 164 * to correctly match the iface name when receiving a packet. 165 */ 166 BpfMap<uint32_t, IfaceValue> mIfaceIndexNameMap; 167 168 /* 169 * mIfaceStataMap: Store per iface traffic stats gathered from xt_bpf 170 * filter. 171 */ 172 BpfMap<uint32_t, StatsValue> mIfaceStatsMap; 173 174 /* 175 * mConfigurationMap: Store the current network policy about uid filtering 176 * and the current stats map in use. There are two configuration entries in 177 * the map right now: 178 * - Entry with UID_RULES_CONFIGURATION_KEY: 179 * Store the configuration for the current uid rules. It indicates the device 180 * is in doze/powersave/standby/restricted mode. 181 * - Entry with CURRENT_STATS_MAP_CONFIGURATION_KEY: 182 * Stores the current live stats map that kernel program is writing to. 183 * Userspace can do scraping and cleaning job on the other one depending on the 184 * current configs. 185 */ 186 BpfMap<uint32_t, uint8_t> mConfigurationMap GUARDED_BY(mMutex); 187 188 /* 189 * mUidOwnerMap: Store uids that are used for bandwidth control uid match. 190 */ 191 BpfMap<uint32_t, UidOwnerValue> mUidOwnerMap GUARDED_BY(mMutex); 192 193 /* 194 * mUidOwnerMap: Store uids that are used for INTERNET permission check. 195 */ 196 BpfMap<uint32_t, uint8_t> mUidPermissionMap GUARDED_BY(mMutex); 197 198 std::unique_ptr<NetlinkListenerInterface> mSkDestroyListener; 199 200 netdutils::Status removeRule(uint32_t uid, UidOwnerMatchType match) REQUIRES(mMutex); 201 202 netdutils::Status addRule(uint32_t uid, UidOwnerMatchType match, uint32_t iif = 0) 203 REQUIRES(mMutex); 204 205 // mMutex guards all accesses to mConfigurationMap, mUidOwnerMap, mUidPermissionMap, 206 // mStatsMapA, mStatsMapB and mPrivilegedUser. It is designed to solve the following 207 // problems: 208 // 1. Prevent concurrent access and modification to mConfigurationMap, mUidOwnerMap, 209 // mUidPermissionMap, and mPrivilegedUser. These data members are controlled by netd but can 210 // be modified from different threads. TrafficController provides several APIs directly 211 // called by the binder RPC, and different binder threads can concurrently access these data 212 // members mentioned above. Some of the data members such as mUidPermissionMap and 213 // mPrivilegedUsers are also accessed from a different thread when tagging sockets or 214 // setting the counterSet through FwmarkServer 215 // 2. Coordinate the deletion of uid stats in mStatsMapA and mStatsMapB. The system server 216 // always call into netd to ask for a live stats map change before it pull and clean up the 217 // stats from the inactive map. The mMutex will block netd from accessing the stats map when 218 // the mConfigurationMap is updating the current stats map so netd will not accidentally 219 // read the map that system_server is cleaning up. 220 std::mutex mMutex; 221 222 // The limit on the number of stats entries a uid can have in the per uid stats map. 223 // TrafficController will block that specific uid from tagging new sockets after the limit is 224 // reached. 225 const uint32_t mPerUidStatsEntriesLimit; 226 227 // The limit on the total number of stats entries in the per uid stats map. TrafficController 228 // will block all tagging requests after the limit is reached. 229 const uint32_t mTotalUidStatsEntriesLimit; 230 231 netdutils::Status loadAndAttachProgram(bpf_attach_type type, const char* path, const char* name, 232 base::unique_fd& cg_fd); 233 234 netdutils::Status initMaps() EXCLUDES(mMutex); 235 236 // Keep track of uids that have permission UPDATE_DEVICE_STATS so we don't 237 // need to call back to system server for permission check. 238 std::set<uid_t> mPrivilegedUser GUARDED_BY(mMutex); 239 240 UidOwnerMatchType jumpOpToMatch(BandwidthController::IptJumpOp jumpHandling); 241 242 bool hasUpdateDeviceStatsPermission(uid_t uid) REQUIRES(mMutex); 243 244 // For testing 245 TrafficController(uint32_t perUidLimit, uint32_t totalLimit); 246 247 // For testing 248 friend class TrafficControllerTest; 249 }; 250 251 } // namespace net 252 } // namespace android 253 254 #endif // NETD_SERVER_TRAFFIC_CONTROLLER_H 255