1a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak/* 2a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * Copyright (C) 2014 The Android Open Source Project 3a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * 4a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * Licensed under the Apache License, Version 2.0 (the "License"); 5a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * you may not use this file except in compliance with the License. 6a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * You may obtain a copy of the License at 7a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * 8a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * http://www.apache.org/licenses/LICENSE-2.0 9a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * 10a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * Unless required by applicable law or agreed to in writing, software 11a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * distributed under the License is distributed on an "AS IS" BASIS, 12a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * See the License for the specific language governing permissions and 14a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak * limitations under the License. 15a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak */ 16a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 1772604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// THREAD-SAFETY 1872604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// ------------- 1972604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// The methods in this file are called from multiple threads (from CommandListener, FwmarkServer 2072604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// and DnsProxyListener). So, all accesses to shared state are guarded by a lock. 2172604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 2272604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// In some cases, a single non-const method acquires and releases the lock several times, like so: 2372604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// if (isValidNetwork(...)) { // isValidNetwork() acquires and releases the lock. 2472604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// setDefaultNetwork(...); // setDefaultNetwork() also acquires and releases the lock. 2572604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 2672604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// It might seem that this allows races where the state changes between the two statements, but in 2772604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// fact there are no races because: 2872604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 1. This pattern only occurs in non-const methods (i.e., those that mutate state). 2972604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 2. Only CommandListener calls these non-const methods. The others call only const methods. 3072604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// 3. CommandListener only processes one command at a time. I.e., it's serialized. 3172604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran// Thus, no other mutation can occur in between the two statements above. 32a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 33a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak#include "NetworkController.h" 34a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 351011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran#include "Fwmark.h" 366a773534e7f8541f221f27fb8063af079b1a5936Sreeram Ramachandran#include "LocalNetwork.h" 37f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran#include "PhysicalNetwork.h" 385c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "RouteController.h" 394043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran#include "VirtualNetwork.h" 405c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 41ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran#include "cutils/misc.h" 42f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran#define LOG_TAG "Netd" 43f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran#include "log/log.h" 4472604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran#include "resolv_netid.h" 4572604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran 465c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandrannamespace { 475c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 485c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran// Keep these in sync with ConnectivityService.java. 49bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned MIN_NET_ID = 100; 50f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranconst unsigned MAX_NET_ID = 65535; 515c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} // namespace 535c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 54bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MIN_OEM_ID = 1; 55bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::MAX_OEM_ID = 50; 56bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran// NetIds 51..98 are reserved for future use. 57bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NetworkController::LOCAL_NET_ID = 99; 58bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran 5948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran// All calls to methods here are made while holding a write lock on mRWLock. 6048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranclass NetworkController::DelegateImpl : public PhysicalNetwork::Delegate { 6148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranpublic: 6248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran explicit DelegateImpl(NetworkController* networkController); 6348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran virtual ~DelegateImpl(); 6448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 6548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(unsigned vpnNetId, const std::string& physicalInterface, 6648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) WARN_UNUSED_RESULT; 6748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 6848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranprivate: 6948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int addFallthrough(const std::string& physicalInterface, 7048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 7148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int removeFallthrough(const std::string& physicalInterface, 7248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) override WARN_UNUSED_RESULT; 7348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran int modifyFallthrough(const std::string& physicalInterface, Permission permission, 7548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran bool add) WARN_UNUSED_RESULT; 7648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 7748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran NetworkController* const mNetworkController; 7848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran}; 7948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8048e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::DelegateImpl(NetworkController* networkController) : 8148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran mNetworkController(networkController) { 8248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 8348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8448e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::DelegateImpl::~DelegateImpl() { 8548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 8648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 8748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(unsigned vpnNetId, 8848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran const std::string& physicalInterface, 8948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 9048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (add) { 9148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::addVirtualNetworkFallthrough(vpnNetId, 9248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 9348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 9448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to add fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 9548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 9648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 9748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 9848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else { 9948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = RouteController::removeVirtualNetworkFallthrough(vpnNetId, 10048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran physicalInterface.c_str(), 10148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran permission)) { 10248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("failed to remove fallthrough to %s for VPN netId %u", physicalInterface.c_str(), 10348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran vpnNetId); 10448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 10548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 10648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 10748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 10848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 10948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 11048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::addFallthrough(const std::string& physicalInterface, 11148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 11248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, true); 11348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 11448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 11548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::removeFallthrough(const std::string& physicalInterface, 11648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission) { 11748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return modifyFallthrough(physicalInterface, permission, false); 11848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 11948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 12048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::DelegateImpl::modifyFallthrough(const std::string& physicalInterface, 12148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission, bool add) { 12248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& entry : mNetworkController->mNetworks) { 12348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 12448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthrough(entry.first, physicalInterface, permission, add)) { 12548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 12648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 12748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 12848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 12948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 13048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 13148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 13248e19b037e7e20674048ef76bf31ce65c741347cSreeram RamachandranNetworkController::NetworkController() : 13348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran mDelegateImpl(new NetworkController::DelegateImpl(this)), mDefaultNetId(NETID_UNSET) { 13487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran mNetworks[LOCAL_NET_ID] = new LocalNetwork(LOCAL_NET_ID); 135a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 136a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 137a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczakunsigned NetworkController::getDefaultNetwork() const { 1389c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 139a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak return mDefaultNetId; 140a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 141a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 142f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setDefaultNetwork(unsigned netId) { 143f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 1449c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 145f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId == mDefaultNetId) { 146f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 1479c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1489c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 149f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (netId != NETID_UNSET) { 15036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 151738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 152738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 153738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 154738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 155738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 156738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set default to non-physical network with netId %u", netId); 157f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EINVAL; 158f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 15936ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) { 160f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1619c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1629c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1639c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 164f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId != NETID_UNSET) { 16536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 16636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (!network || network->getType() != Network::PHYSICAL) { 167f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 168f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -ESRCH; 169f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 17036ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 171f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 1729c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1739c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran } 1749c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran 175f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = netId; 176f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return 0; 177a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 178a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 1791011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranuint32_t NetworkController::getNetworkForDns(unsigned* netId, uid_t uid) const { 1801011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 1811011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Fwmark fwmark; 1821011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.protectedFromVpn = true; 1831011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.permission = PERMISSION_SYSTEM; 184a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (checkUserNetworkAccessLocked(uid, *netId) == 0) { 1851011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If a non-zero NetId was explicitly specified, and the user has permission for that 1861011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // network, use that network's DNS servers. Do not fall through to the default network even 1871011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // if the explicitly selected network is a split tunnel VPN or a VPN without DNS servers. 1881011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.explicitlySelected = true; 1891011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 1901011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If the user is subject to a VPN and the VPN provides DNS servers, use those servers 1911011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (possibly falling through to the default network if the VPN doesn't provide a route to 1921011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // them). Otherwise, use the default network's DNS servers. 1931011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 1941011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->getHasDns()) { 1951011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = virtualNetwork->getNetId(); 1961011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } else { 1971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran *netId = mDefaultNetId; 1981011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 1991011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2001011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran fwmark.netId = *netId; 2011011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return fwmark.intValue; 2021011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 2031011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 2041011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that a given UID would use if no network is explicitly selected. Specifically, 2051011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the VPN that applies to the UID if any; otherwise, the default network. 2061011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForUser(uid_t uid) const { 2071011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 2081011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid)) { 2091011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return virtualNetwork->getNetId(); 2101011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 2111011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 2121011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 2131011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 2141011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// Returns the NetId that will be set when a socket connect()s. This is the bypassable VPN that 2151011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// applies to the user if any; otherwise, the default network. 2161011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2171011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// In general, we prefer to always set the default network's NetId in connect(), so that if the VPN 2181011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// is a split-tunnel and disappears later, the socket continues working (since the default network's 2191011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// NetId is still valid). Secure VPNs will correctly grab the socket's traffic since they have a 2201011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// high-priority routing rule that doesn't care what NetId the socket has. 2211011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// 2221011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// But bypassable VPNs have a very low priority rule, so we need to mark the socket with the 2231011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// bypassable VPN's NetId if we expect it to get any traffic at all. If the bypassable VPN is a 2241011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// split-tunnel, that's okay, because we have fallthrough rules that will direct the fallthrough 2251011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// traffic to the default network. But it does mean that if the bypassable VPN goes away (and thus 2261011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// the fallthrough rules also go away), the socket that used to fallthrough to the default network 2271011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran// will stop working. 2281011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandranunsigned NetworkController::getNetworkForConnect(uid_t uid) const { 229a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak android::RWLock::AutoRLock lock(mRWLock); 230e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 2311011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && !virtualNetwork->isSecure()) { 232e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork->getNetId(); 233a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak } 2341011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran return mDefaultNetId; 235a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 236a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 237e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranunsigned NetworkController::getNetworkForInterface(const char* interface) const { 238f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 23936ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran for (const auto& entry : mNetworks) { 2404043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (entry.second->hasInterface(interface)) { 2414043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return entry.first; 2424043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 2434043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 24435c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen return NETID_UNSET; 245a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak} 246a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak 247070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandranbool NetworkController::isVirtualNetwork(unsigned netId) const { 248070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 249070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran Network* network = getNetworkLocked(netId); 250070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran return network && network->getType() == Network::VIRTUAL; 251070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran} 252070b2d296de30e3dbc68c21f542acb1f2914d870Sreeram Ramachandran 253e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranint NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) { 254bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran if (!((MIN_NET_ID <= netId && netId <= MAX_NET_ID) || 255bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran (MIN_OEM_ID <= netId && netId <= MAX_OEM_ID))) { 256f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("invalid netId %u", netId); 25796f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 2585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 2595c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 260f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (isValidNetwork(netId)) { 261f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 262f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EEXIST; 2635c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 2645c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 26548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId, mDelegateImpl); 266f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (int ret = physicalNetwork->setPermission(permission)) { 267f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! setPermission cannot fail on an empty network"); 268f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete physicalNetwork; 26996f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return ret; 270ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 271ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 272f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 27336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks[netId] = physicalNetwork; 27496f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 2755c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 2765c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 27795684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandranint NetworkController::createVirtualNetwork(unsigned netId, bool hasDns, bool secure) { 278bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran if (!(MIN_NET_ID <= netId && netId <= MAX_NET_ID)) { 2794043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("invalid netId %u", netId); 2804043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EINVAL; 2814043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 2824043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 2834043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran if (isValidNetwork(netId)) { 2844043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran ALOGE("duplicate netId %u", netId); 2854043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return -EEXIST; 2864043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran } 2874043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 2884043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 28948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = modifyFallthroughLocked(netId, true)) { 29048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 29148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 29295684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran mNetworks[netId] = new VirtualNetwork(netId, hasDns, secure); 2934043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran return 0; 2944043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran} 2954043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran 296f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::destroyNetwork(unsigned netId) { 297738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (netId == LOCAL_NET_ID) { 298738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot destroy local network"); 29996f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 300ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 301738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 302738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 303738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 304738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 305ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 306f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network. 30796f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti 308f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 309f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran Network* network = getNetworkLocked(netId); 31099286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti 31199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // If we fail to destroy a network, things will get stuck badly. Therefore, unlike most of the 31299286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // other network code, ignore failures and attempt to clear out as much state as possible, even 31399286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti // if we hit an error on the way. Return the first error that we see. 31499286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti int ret = network->clearInterfaces(); 31599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti 316f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (mDefaultNetId == netId) { 31799286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (int err = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) { 318f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("inconceivable! removeAsDefault cannot fail on an empty network"); 31999286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (!ret) { 32099286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti ret = err; 32199286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti } 322f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 323f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran mDefaultNetId = NETID_UNSET; 32448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } else if (network->getType() == Network::VIRTUAL) { 32599286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (int err = modifyFallthroughLocked(netId, false)) { 32699286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti if (!ret) { 32799286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti ret = err; 32899286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti } 32948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 330f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran } 33136ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran mNetworks.erase(netId); 332f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran delete network; 333f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran _resolv_delete_cache_for_net(netId); 33499286fe1ef6fc325c28dd10b651b5adedd549495Lorenzo Colitti return ret; 335f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 336ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 337f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) { 338f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (!isValidNetwork(netId)) { 339738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 340738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 341ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen } 342ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 343e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 344f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran if (existingNetId != NETID_UNSET && existingNetId != netId) { 345f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s already assigned to netId %u", interface, existingNetId); 346f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return -EBUSY; 347a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen } 348a561e121c724e9163b2e256e15eef660e3a326daPaul Jensen 349f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 350f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->addInterface(interface); 351ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen} 352ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen 353f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) { 35472604075e74af459fb4637404fbf030422c6b6b6Sreeram Ramachandran if (!isValidNetwork(netId)) { 355738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 356738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 3575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 359f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 360f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return getNetworkLocked(netId)->removeInterface(interface); 361f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 3625c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 363f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranPermission NetworkController::getPermissionForUser(uid_t uid) const { 364f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 365ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return getPermissionForUserLocked(uid); 366f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran} 3675c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 368f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranvoid NetworkController::setPermissionForUsers(Permission permission, 369f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<uid_t>& uids) { 370f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 371f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (uid_t uid : uids) { 372ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran mUsers[uid] = permission; 3735c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran } 3745c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran} 3755c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran 376a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccess(uid_t uid, unsigned netId) const { 377f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 378a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return checkUserNetworkAccessLocked(uid, netId); 379379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 380379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 381f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint NetworkController::setPermissionForNetworks(Permission permission, 382f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const std::vector<unsigned>& netIds) { 383f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 384f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran for (unsigned netId : netIds) { 38536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 386738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 387738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 388738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 389738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 390738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 391738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot set permissions on non-physical network with netId %u", netId); 39296f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return -EINVAL; 393379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 394379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 395f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission. 396379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 39736ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) { 398f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran return ret; 399379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 400379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran } 40196f261e8b28048b8cb48f5a4e81822c73bb813f4Lorenzo Colitti return 0; 402379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran} 403379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran 404b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) { 405b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 40636ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 407738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 408738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 409738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 410738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 411738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 412738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot add users to non-virtual network with netId %u", netId); 413b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 414b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 41536ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges)) { 416b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 417b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 418b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 419b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 420b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 421b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandranint NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) { 422b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 42336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran Network* network = getNetworkLocked(netId); 424738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 425738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 426738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 427738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 428738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::VIRTUAL) { 429738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("cannot remove users from non-virtual network with netId %u", netId); 430b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return -EINVAL; 431b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 43236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges)) { 433b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return ret; 434b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran } 435b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran return 0; 436b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran} 437b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran 438f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::addRoute(unsigned netId, const char* interface, const char* destination, 439f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 44038b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid); 4417619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 4427619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 443f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination, 444f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool legacy, uid_t uid) { 44538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid); 4467619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 4477619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 448e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::canProtect(uid_t uid) const { 449e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 450e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) || 451e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran mProtectableUsers.find(uid) != mProtectableUsers.end(); 452e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 453e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 45489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::allowProtect(const std::vector<uid_t>& uids) { 45589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 45689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.insert(uids.begin(), uids.end()); 45789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 45889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 45989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandranvoid NetworkController::denyProtect(const std::vector<uid_t>& uids) { 46089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran android::RWLock::AutoWLock lock(mRWLock); 46189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran for (uid_t uid : uids) { 46289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran mProtectableUsers.erase(uid); 46389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran } 46489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran} 46589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran 466e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandranbool NetworkController::isValidNetwork(unsigned netId) const { 467e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran android::RWLock::AutoRLock lock(mRWLock); 468e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return getNetworkLocked(netId); 469e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 470e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 471f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram RamachandranNetwork* NetworkController::getNetworkLocked(unsigned netId) const { 47236ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran auto iter = mNetworks.find(netId); 47336ed53e37b2639681055b2d3d8777241e7dd6982Sreeram Ramachandran return iter == mNetworks.end() ? NULL : iter->second; 4747619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 4757619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 476e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram RamachandranVirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const { 477e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran for (const auto& entry : mNetworks) { 478e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (entry.second->getType() == Network::VIRTUAL) { 479e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second); 480e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran if (virtualNetwork->appliesToUser(uid)) { 481e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return virtualNetwork; 482e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 483e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 484e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran } 485e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran return NULL; 486e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran} 487e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran 488ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram RamachandranPermission NetworkController::getPermissionForUserLocked(uid_t uid) const { 489ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran auto iter = mUsers.find(uid); 490ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if (iter != mUsers.end()) { 491ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return iter->second; 492ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran } 493ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE; 494ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran} 495ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran 496a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colittiint NetworkController::checkUserNetworkAccessLocked(uid_t uid, unsigned netId) const { 4971011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Network* network = getNetworkLocked(netId); 498a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (!network) { 499a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -ENONET; 500a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti } 501a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti 5021011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // If uid is INVALID_UID, this likely means that we were unable to retrieve the UID of the peer 5031011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran // (using SO_PEERCRED). Be safe and deny access to the network, even if it's valid. 504a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti if (uid == INVALID_UID) { 505a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -EREMOTEIO; 5061011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 5071011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission userPermission = getPermissionForUserLocked(uid); 5081011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 509a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return 0; 5101011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 5111011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (network->getType() == Network::VIRTUAL) { 512a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return static_cast<VirtualNetwork*>(network)->appliesToUser(uid) ? 0 : -EPERM; 5131011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 5141011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid); 5151011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran if (virtualNetwork && virtualNetwork->isSecure() && 5161011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran mProtectableUsers.find(uid) == mProtectableUsers.end()) { 517a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return -EPERM; 5181011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran } 5191011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission(); 520a1067c8d2b2165f1058a3a8216bed4efacfa1c80Lorenzo Colitti return ((userPermission & networkPermission) == networkPermission) ? 0 : -EACCES; 5211011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran} 5221011b4941d96d9fd90bc7243be387b63ec775936Sreeram Ramachandran 523f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colittiint NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination, 524f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran const char* nexthop, bool add, bool legacy, uid_t uid) { 525738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!isValidNetwork(netId)) { 526738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("no such netId %u", netId); 527738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENONET; 528738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 529e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran unsigned existingNetId = getNetworkForInterface(interface); 530738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId == NETID_UNSET) { 531738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("interface %s not assigned to any netId", interface); 532738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -ENODEV; 533738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 534738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (existingNetId != netId) { 535f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId); 536f7fc8eccb0a6a4fbca4cafdf53f5c167c8f1d755Lorenzo Colitti return -ENOENT; 5377619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran } 5387619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran 53938b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran RouteController::TableType tableType; 54087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran if (netId == LOCAL_NET_ID) { 54187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran tableType = RouteController::LOCAL_NETWORK; 54287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran } else if (legacy) { 543ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) { 5445009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_SYSTEM; 54538b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 5465009d5ef3fbcdc69d772b528fd22184b7d605afaSreeram Ramachandran tableType = RouteController::LEGACY_NETWORK; 54738b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 54838b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } else { 54938b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran tableType = RouteController::INTERFACE; 55038b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran } 55138b7af1f2cb9579895465fabc37865f5dadcac25Sreeram Ramachandran 552eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran return add ? RouteController::addRoute(interface, destination, nexthop, tableType) : 553eb27b7ec10faf47a93fbc2863092cc667b05e252Sreeram Ramachandran RouteController::removeRoute(interface, destination, nexthop, tableType); 5547619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran} 55548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran 55648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandranint NetworkController::modifyFallthroughLocked(unsigned vpnNetId, bool add) { 55748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (mDefaultNetId == NETID_UNSET) { 55848e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 55948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 56048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Network* network = getNetworkLocked(mDefaultNetId); 561738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (!network) { 56248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran ALOGE("cannot find previously set default network with netId %u", mDefaultNetId); 56348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return -ESRCH; 56448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 565738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti if (network->getType() != Network::PHYSICAL) { 566738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti ALOGE("inconceivable! default network must be a physical network"); 567738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti return -EINVAL; 568738c93ee075354ffafb3a8ceef76e9aa711f057bLorenzo Colitti } 56948e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran Permission permission = static_cast<PhysicalNetwork*>(network)->getPermission(); 57048e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran for (const auto& physicalInterface : network->getInterfaces()) { 57148e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran if (int ret = mDelegateImpl->modifyFallthrough(vpnNetId, physicalInterface, permission, 57248e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran add)) { 57348e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return ret; 57448e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 57548e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran } 57648e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran return 0; 57748e19b037e7e20674048ef76bf31ce65c741347cSreeram Ramachandran} 578