NetworkController.cpp revision 6a773534e7f8541f221f27fb8063af079b1a5936
1/*
2 * Copyright (C) 2014 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// THREAD-SAFETY
18// -------------
19// The methods in this file are called from multiple threads (from CommandListener, FwmarkServer
20// and DnsProxyListener). So, all accesses to shared state are guarded by a lock.
21//
22// In some cases, a single non-const method acquires and releases the lock several times, like so:
23//     if (isValidNetwork(...)) {  // isValidNetwork() acquires and releases the lock.
24//        setDefaultNetwork(...);  // setDefaultNetwork() also acquires and releases the lock.
25//
26// It might seem that this allows races where the state changes between the two statements, but in
27// fact there are no races because:
28//     1. This pattern only occurs in non-const methods (i.e., those that mutate state).
29//     2. Only CommandListener calls these non-const methods. The others call only const methods.
30//     3. CommandListener only processes one command at a time. I.e., it's serialized.
31// Thus, no other mutation can occur in between the two statements above.
32
33#include "NetworkController.h"
34
35#include "LocalNetwork.h"
36#include "PhysicalNetwork.h"
37#include "RouteController.h"
38#include "VirtualNetwork.h"
39
40#include "cutils/misc.h"
41#define LOG_TAG "Netd"
42#include "log/log.h"
43#include "resolv_netid.h"
44
45namespace {
46
47// Keep these in sync with ConnectivityService.java.
48const unsigned MIN_NET_ID = 10;
49const unsigned MAX_NET_ID = 65535;
50
51}  // namespace
52
53NetworkController::NetworkController() : mDefaultNetId(NETID_UNSET) {
54}
55
56unsigned NetworkController::getDefaultNetwork() const {
57    android::RWLock::AutoRLock lock(mRWLock);
58    return mDefaultNetId;
59}
60
61int NetworkController::setDefaultNetwork(unsigned netId) {
62    android::RWLock::AutoWLock lock(mRWLock);
63
64    if (netId == mDefaultNetId) {
65        return 0;
66    }
67
68    if (netId != NETID_UNSET) {
69        Network* network = getNetworkLocked(netId);
70        if (!network || network->getType() != Network::PHYSICAL) {
71            ALOGE("invalid netId %u", netId);
72            return -EINVAL;
73        }
74        if (int ret = static_cast<PhysicalNetwork*>(network)->addAsDefault()) {
75            return ret;
76        }
77    }
78
79    if (mDefaultNetId != NETID_UNSET) {
80        Network* network = getNetworkLocked(mDefaultNetId);
81        if (!network || network->getType() != Network::PHYSICAL) {
82            ALOGE("cannot find previously set default network with netId %u", mDefaultNetId);
83            return -ESRCH;
84        }
85        if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
86            return ret;
87        }
88    }
89
90    mDefaultNetId = netId;
91    return 0;
92}
93
94unsigned NetworkController::getNetworkForUser(uid_t uid, unsigned requestedNetId,
95                                              bool forDns) const {
96    android::RWLock::AutoRLock lock(mRWLock);
97    VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
98    if (virtualNetwork && (!forDns || virtualNetwork->getHasDns())) {
99        return virtualNetwork->getNetId();
100    }
101    return getNetworkLocked(requestedNetId) ? requestedNetId : mDefaultNetId;
102}
103
104unsigned NetworkController::getNetworkForInterface(const char* interface) const {
105    android::RWLock::AutoRLock lock(mRWLock);
106    for (const auto& entry : mNetworks) {
107        if (entry.second->hasInterface(interface)) {
108            return entry.first;
109        }
110    }
111    return NETID_UNSET;
112}
113
114unsigned NetworkController::getNetIdForLocalNetwork() const {
115    return MIN_NET_ID - 1;
116}
117
118int NetworkController::createLocalNetwork(unsigned netId) {
119    // TODO: Enable this check after removing the getNetIdForLocalNetwork() hack.
120    if (false) {
121        if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
122            ALOGE("invalid netId %u", netId);
123            return -EINVAL;
124        }
125    }
126
127    if (isValidNetwork(netId)) {
128        ALOGE("duplicate netId %u", netId);
129        return -EEXIST;
130    }
131
132    android::RWLock::AutoWLock lock(mRWLock);
133    mNetworks[netId] = new LocalNetwork(netId);
134    return 0;
135}
136
137int NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) {
138    if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
139        ALOGE("invalid netId %u", netId);
140        return -EINVAL;
141    }
142
143    if (isValidNetwork(netId)) {
144        ALOGE("duplicate netId %u", netId);
145        return -EEXIST;
146    }
147
148    PhysicalNetwork* physicalNetwork = new PhysicalNetwork(netId);
149    if (int ret = physicalNetwork->setPermission(permission)) {
150        ALOGE("inconceivable! setPermission cannot fail on an empty network");
151        delete physicalNetwork;
152        return ret;
153    }
154
155    android::RWLock::AutoWLock lock(mRWLock);
156    mNetworks[netId] = physicalNetwork;
157    return 0;
158}
159
160int NetworkController::createVirtualNetwork(unsigned netId, bool hasDns) {
161    if (netId < MIN_NET_ID || netId > MAX_NET_ID) {
162        ALOGE("invalid netId %u", netId);
163        return -EINVAL;
164    }
165
166    if (isValidNetwork(netId)) {
167        ALOGE("duplicate netId %u", netId);
168        return -EEXIST;
169    }
170
171    android::RWLock::AutoWLock lock(mRWLock);
172    mNetworks[netId] = new VirtualNetwork(netId, hasDns);
173    return 0;
174}
175
176int NetworkController::destroyNetwork(unsigned netId) {
177    if (!isValidNetwork(netId)) {
178        ALOGE("invalid netId %u", netId);
179        return -EINVAL;
180    }
181
182    // TODO: ioctl(SIOCKILLADDR, ...) to kill all sockets on the old network.
183
184    android::RWLock::AutoWLock lock(mRWLock);
185    Network* network = getNetworkLocked(netId);
186    if (int ret = network->clearInterfaces()) {
187        return ret;
188    }
189    if (mDefaultNetId == netId) {
190        if (int ret = static_cast<PhysicalNetwork*>(network)->removeAsDefault()) {
191            ALOGE("inconceivable! removeAsDefault cannot fail on an empty network");
192            return ret;
193        }
194        mDefaultNetId = NETID_UNSET;
195    }
196    mNetworks.erase(netId);
197    delete network;
198    _resolv_delete_cache_for_net(netId);
199    return 0;
200}
201
202int NetworkController::addInterfaceToNetwork(unsigned netId, const char* interface) {
203    if (!isValidNetwork(netId)) {
204        ALOGE("invalid netId %u", netId);
205        return -EINVAL;
206    }
207
208    unsigned existingNetId = getNetworkForInterface(interface);
209    if (existingNetId != NETID_UNSET && existingNetId != netId) {
210        ALOGE("interface %s already assigned to netId %u", interface, existingNetId);
211        return -EBUSY;
212    }
213
214    android::RWLock::AutoWLock lock(mRWLock);
215    return getNetworkLocked(netId)->addInterface(interface);
216}
217
218int NetworkController::removeInterfaceFromNetwork(unsigned netId, const char* interface) {
219    if (!isValidNetwork(netId)) {
220        ALOGE("invalid netId %u", netId);
221        return -EINVAL;
222    }
223
224    android::RWLock::AutoWLock lock(mRWLock);
225    return getNetworkLocked(netId)->removeInterface(interface);
226}
227
228Permission NetworkController::getPermissionForUser(uid_t uid) const {
229    android::RWLock::AutoRLock lock(mRWLock);
230    return getPermissionForUserLocked(uid);
231}
232
233void NetworkController::setPermissionForUsers(Permission permission,
234                                              const std::vector<uid_t>& uids) {
235    android::RWLock::AutoWLock lock(mRWLock);
236    for (uid_t uid : uids) {
237        mUsers[uid] = permission;
238    }
239}
240
241bool NetworkController::canUserSelectNetwork(uid_t uid, unsigned netId) const {
242    android::RWLock::AutoRLock lock(mRWLock);
243    Network* network = getNetworkLocked(netId);
244    if (!network || uid == INVALID_UID) {
245        return false;
246    }
247    Permission userPermission = getPermissionForUserLocked(uid);
248    if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
249        return true;
250    }
251    if (network->getType() == Network::VIRTUAL) {
252        return static_cast<VirtualNetwork*>(network)->appliesToUser(uid);
253    }
254    VirtualNetwork* virtualNetwork = getVirtualNetworkForUserLocked(uid);
255    if (virtualNetwork && mProtectableUsers.find(uid) == mProtectableUsers.end()) {
256        return false;
257    }
258    Permission networkPermission = static_cast<PhysicalNetwork*>(network)->getPermission();
259    return (userPermission & networkPermission) == networkPermission;
260}
261
262int NetworkController::setPermissionForNetworks(Permission permission,
263                                                const std::vector<unsigned>& netIds) {
264    android::RWLock::AutoWLock lock(mRWLock);
265    for (unsigned netId : netIds) {
266        Network* network = getNetworkLocked(netId);
267        if (!network || network->getType() != Network::PHYSICAL) {
268            ALOGE("invalid netId %u", netId);
269            return -EINVAL;
270        }
271
272        // TODO: ioctl(SIOCKILLADDR, ...) to kill socets on the network that don't have permission.
273
274        if (int ret = static_cast<PhysicalNetwork*>(network)->setPermission(permission)) {
275            return ret;
276        }
277    }
278    return 0;
279}
280
281int NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) {
282    android::RWLock::AutoWLock lock(mRWLock);
283    Network* network = getNetworkLocked(netId);
284    if (!network || network->getType() != Network::VIRTUAL) {
285        ALOGE("invalid netId %u", netId);
286        return -EINVAL;
287    }
288    if (int ret = static_cast<VirtualNetwork*>(network)->addUsers(uidRanges)) {
289        return ret;
290    }
291    return 0;
292}
293
294int NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) {
295    android::RWLock::AutoWLock lock(mRWLock);
296    Network* network = getNetworkLocked(netId);
297    if (!network || network->getType() != Network::VIRTUAL) {
298        ALOGE("invalid netId %u", netId);
299        return -EINVAL;
300    }
301    if (int ret = static_cast<VirtualNetwork*>(network)->removeUsers(uidRanges)) {
302        return ret;
303    }
304    return 0;
305}
306
307int NetworkController::addRoute(unsigned netId, const char* interface, const char* destination,
308                                const char* nexthop, bool legacy, uid_t uid) {
309    return modifyRoute(netId, interface, destination, nexthop, true, legacy, uid);
310}
311
312int NetworkController::removeRoute(unsigned netId, const char* interface, const char* destination,
313                                   const char* nexthop, bool legacy, uid_t uid) {
314    return modifyRoute(netId, interface, destination, nexthop, false, legacy, uid);
315}
316
317bool NetworkController::canProtect(uid_t uid) const {
318    android::RWLock::AutoRLock lock(mRWLock);
319    return ((getPermissionForUserLocked(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) ||
320           mProtectableUsers.find(uid) != mProtectableUsers.end();
321}
322
323void NetworkController::allowProtect(const std::vector<uid_t>& uids) {
324    android::RWLock::AutoWLock lock(mRWLock);
325    mProtectableUsers.insert(uids.begin(), uids.end());
326}
327
328void NetworkController::denyProtect(const std::vector<uid_t>& uids) {
329    android::RWLock::AutoWLock lock(mRWLock);
330    for (uid_t uid : uids) {
331        mProtectableUsers.erase(uid);
332    }
333}
334
335bool NetworkController::isValidNetwork(unsigned netId) const {
336    android::RWLock::AutoRLock lock(mRWLock);
337    return getNetworkLocked(netId);
338}
339
340Network* NetworkController::getNetworkLocked(unsigned netId) const {
341    auto iter = mNetworks.find(netId);
342    return iter == mNetworks.end() ? NULL : iter->second;
343}
344
345VirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const {
346    for (const auto& entry : mNetworks) {
347        if (entry.second->getType() == Network::VIRTUAL) {
348            VirtualNetwork* virtualNetwork = static_cast<VirtualNetwork*>(entry.second);
349            if (virtualNetwork->appliesToUser(uid)) {
350                return virtualNetwork;
351            }
352        }
353    }
354    return NULL;
355}
356
357Permission NetworkController::getPermissionForUserLocked(uid_t uid) const {
358    auto iter = mUsers.find(uid);
359    if (iter != mUsers.end()) {
360        return iter->second;
361    }
362    return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE;
363}
364
365int NetworkController::modifyRoute(unsigned netId, const char* interface, const char* destination,
366                                   const char* nexthop, bool add, bool legacy, uid_t uid) {
367    unsigned existingNetId = getNetworkForInterface(interface);
368    if (netId == NETID_UNSET || existingNetId != netId) {
369        ALOGE("interface %s assigned to netId %u, not %u", interface, existingNetId, netId);
370        return -ENOENT;
371    }
372
373    RouteController::TableType tableType;
374    if (legacy) {
375        if ((getPermissionForUser(uid) & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
376            tableType = RouteController::LEGACY_SYSTEM;
377        } else {
378            tableType = RouteController::LEGACY_NETWORK;
379        }
380    } else {
381        tableType = RouteController::INTERFACE;
382    }
383
384    return add ? RouteController::addRoute(interface, destination, nexthop, tableType) :
385                 RouteController::removeRoute(interface, destination, nexthop, tableType);
386}
387