• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /**
2   * Copyright (c) 2016, 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  #define LOG_TAG "Netd"
18  
19  #include <vector>
20  
21  #include <android-base/stringprintf.h>
22  #include <cutils/log.h>
23  #include <utils/Errors.h>
24  #include <utils/String16.h>
25  
26  #include <binder/IPCThreadState.h>
27  #include <binder/IServiceManager.h>
28  #include "android/net/BnNetd.h"
29  
30  #include "Controllers.h"
31  #include "DumpWriter.h"
32  #include "NetdConstants.h"
33  #include "NetdNativeService.h"
34  #include "RouteController.h"
35  #include "SockDiag.h"
36  #include "UidRanges.h"
37  
38  using android::base::StringPrintf;
39  
40  namespace android {
41  namespace net {
42  
43  namespace {
44  
45  const char CONNECTIVITY_INTERNAL[] = "android.permission.CONNECTIVITY_INTERNAL";
46  const char DUMP[] = "android.permission.DUMP";
47  
checkPermission(const char * permission)48  binder::Status checkPermission(const char *permission) {
49      pid_t pid;
50      uid_t uid;
51  
52      if (checkCallingPermission(String16(permission), (int32_t *) &pid, (int32_t *) &uid)) {
53          return binder::Status::ok();
54      } else {
55          auto err = StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission);
56          return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(err.c_str()));
57      }
58  }
59  
60  #define ENFORCE_PERMISSION(permission) {                    \
61      binder::Status status = checkPermission((permission));  \
62      if (!status.isOk()) {                                   \
63          return status;                                      \
64      }                                                       \
65  }
66  
67  #define NETD_LOCKING_RPC(permission, lock)                  \
68      ENFORCE_PERMISSION(permission);                         \
69      android::RWLock::AutoWLock _lock(lock);
70  
71  #define NETD_BIG_LOCK_RPC(permission) NETD_LOCKING_RPC((permission), gBigNetdLock)
72  }  // namespace
73  
74  
start()75  status_t NetdNativeService::start() {
76      IPCThreadState::self()->disableBackgroundScheduling(true);
77      status_t ret = BinderService<NetdNativeService>::publish();
78      if (ret != android::OK) {
79          return ret;
80      }
81      sp<ProcessState> ps(ProcessState::self());
82      ps->startThreadPool();
83      ps->giveThreadPoolName();
84      return android::OK;
85  }
86  
dump(int fd,const Vector<String16> &)87  status_t NetdNativeService::dump(int fd, const Vector<String16> & /* args */) {
88      const binder::Status dump_permission = checkPermission(DUMP);
89      if (!dump_permission.isOk()) {
90          const String8 msg(dump_permission.toString8());
91          write(fd, msg.string(), msg.size());
92          return PERMISSION_DENIED;
93      }
94  
95      // This method does not grab any locks. If individual classes need locking
96      // their dump() methods MUST handle locking appropriately.
97      DumpWriter dw(fd);
98      dw.blankline();
99      gCtls->netCtrl.dump(dw);
100      dw.blankline();
101  
102      return NO_ERROR;
103  }
104  
isAlive(bool * alive)105  binder::Status NetdNativeService::isAlive(bool *alive) {
106      NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
107  
108      *alive = true;
109      return binder::Status::ok();
110  }
111  
firewallReplaceUidChain(const android::String16 & chainName,bool isWhitelist,const std::vector<int32_t> & uids,bool * ret)112  binder::Status NetdNativeService::firewallReplaceUidChain(const android::String16& chainName,
113          bool isWhitelist, const std::vector<int32_t>& uids, bool *ret) {
114      NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->firewallCtrl.lock);
115  
116      android::String8 name = android::String8(chainName);
117      int err = gCtls->firewallCtrl.replaceUidChain(name.string(), isWhitelist, uids);
118      *ret = (err == 0);
119      return binder::Status::ok();
120  }
121  
bandwidthEnableDataSaver(bool enable,bool * ret)122  binder::Status NetdNativeService::bandwidthEnableDataSaver(bool enable, bool *ret) {
123      NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->bandwidthCtrl.lock);
124  
125      int err = gCtls->bandwidthCtrl.enableDataSaver(enable);
126      *ret = (err == 0);
127      return binder::Status::ok();
128  }
129  
networkRejectNonSecureVpn(bool add,const std::vector<UidRange> & uidRangeArray)130  binder::Status NetdNativeService::networkRejectNonSecureVpn(bool add,
131          const std::vector<UidRange>& uidRangeArray) {
132      // TODO: elsewhere RouteController is only used from the tethering and network controllers, so
133      // it should be possible to use the same lock as NetworkController. However, every call through
134      // the CommandListener "network" command will need to hold this lock too, not just the ones that
135      // read/modify network internal state (that is sufficient for ::dump() because it doesn't
136      // look at routes, but it's not enough here).
137      NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
138  
139      UidRanges uidRanges(uidRangeArray);
140  
141      int err;
142      if (add) {
143          err = RouteController::addUsersToRejectNonSecureNetworkRule(uidRanges);
144      } else {
145          err = RouteController::removeUsersFromRejectNonSecureNetworkRule(uidRanges);
146      }
147  
148      if (err != 0) {
149          return binder::Status::fromServiceSpecificError(-err,
150                  String8::format("RouteController error: %s", strerror(-err)));
151      }
152      return binder::Status::ok();
153  }
154  
socketDestroy(const std::vector<UidRange> & uids,const std::vector<int32_t> & skipUids)155  binder::Status NetdNativeService::socketDestroy(const std::vector<UidRange>& uids,
156          const std::vector<int32_t>& skipUids) {
157  
158      ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
159  
160      SockDiag sd;
161      if (!sd.open()) {
162          return binder::Status::fromServiceSpecificError(EIO,
163                  String8("Could not open SOCK_DIAG socket"));
164      }
165  
166      UidRanges uidRanges(uids);
167      int err = sd.destroySockets(uidRanges, std::set<uid_t>(skipUids.begin(), skipUids.end()));
168  
169      if (err) {
170          return binder::Status::fromServiceSpecificError(-err,
171                  String8::format("destroySockets: %s", strerror(-err)));
172      }
173      return binder::Status::ok();
174  }
175  
setResolverConfiguration(int32_t netId,const std::vector<std::string> & servers,const std::vector<std::string> & domains,const std::vector<int32_t> & params)176  binder::Status NetdNativeService::setResolverConfiguration(int32_t netId,
177          const std::vector<std::string>& servers, const std::vector<std::string>& domains,
178          const std::vector<int32_t>& params) {
179      // This function intentionally does not lock within Netd, as Bionic is thread-safe.
180      ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
181  
182      int err = gCtls->resolverCtrl.setResolverConfiguration(netId, servers, domains, params);
183      if (err != 0) {
184          return binder::Status::fromServiceSpecificError(-err,
185                  String8::format("ResolverController error: %s", strerror(-err)));
186      }
187      return binder::Status::ok();
188  }
189  
getResolverInfo(int32_t netId,std::vector<std::string> * servers,std::vector<std::string> * domains,std::vector<int32_t> * params,std::vector<int32_t> * stats)190  binder::Status NetdNativeService::getResolverInfo(int32_t netId,
191          std::vector<std::string>* servers, std::vector<std::string>* domains,
192          std::vector<int32_t>* params, std::vector<int32_t>* stats) {
193      // This function intentionally does not lock within Netd, as Bionic is thread-safe.
194      ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
195  
196      int err = gCtls->resolverCtrl.getResolverInfo(netId, servers, domains, params, stats);
197      if (err != 0) {
198          return binder::Status::fromServiceSpecificError(-err,
199                  String8::format("ResolverController error: %s", strerror(-err)));
200      }
201      return binder::Status::ok();
202  }
203  
204  }  // namespace net
205  }  // namespace android
206