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