NetdNativeService.cpp revision dedd271d9961dbe8b99ffa7d54ffd63ac326f866
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
25#include <binder/IPCThreadState.h>
26#include <binder/IServiceManager.h>
27#include "android/net/BnNetd.h"
28
29#include "Controllers.h"
30#include "DumpWriter.h"
31#include "NetdConstants.h"
32#include "NetdNativeService.h"
33
34using android::base::StringPrintf;
35
36namespace android {
37namespace net {
38
39namespace {
40
41const char CONNECTIVITY_INTERNAL[] = "android.permission.CONNECTIVITY_INTERNAL";
42const char DUMP[] = "android.permission.DUMP";
43
44binder::Status checkPermission(const char *permission) {
45    pid_t pid;
46    uid_t uid;
47
48    if (checkCallingPermission(String16(permission), (int32_t *) &pid, (int32_t *) &uid)) {
49        return binder::Status::ok();
50    } else {
51        auto err = StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission);
52        return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(err.c_str()));
53    }
54}
55
56#define ENFORCE_PERMISSION(permission) {                    \
57    binder::Status status = checkPermission((permission));  \
58    if (!status.isOk()) {                                   \
59        return status;                                      \
60    }                                                       \
61}
62
63#define NETD_LOCKING_RPC(permission, lock)                  \
64    ENFORCE_PERMISSION(permission);                         \
65    android::RWLock::AutoWLock _lock(lock);
66
67#define NETD_BIG_LOCK_RPC(permission) NETD_LOCKING_RPC((permission), gBigNetdLock)
68
69}  // namespace
70
71
72status_t NetdNativeService::start() {
73    IPCThreadState::self()->disableBackgroundScheduling(true);
74    status_t ret = BinderService<NetdNativeService>::publish();
75    if (ret != android::OK) {
76        return ret;
77    }
78    sp<ProcessState> ps(ProcessState::self());
79    ps->startThreadPool();
80    ps->giveThreadPoolName();
81    return android::OK;
82}
83
84status_t NetdNativeService::dump(int fd, const Vector<String16> & /* args */) {
85    const binder::Status dump_permission = checkPermission(DUMP);
86    if (!dump_permission.isOk()) {
87        const String8 msg(dump_permission.toString8());
88        write(fd, msg.string(), msg.size());
89        return PERMISSION_DENIED;
90    }
91
92    // This method does not grab any locks. If individual classes need locking
93    // their dump() methods MUST handle locking appropriately.
94    DumpWriter dw(fd);
95    dw.blankline();
96    gCtls->netCtrl.dump(dw);
97    dw.blankline();
98
99    return NO_ERROR;
100}
101
102binder::Status NetdNativeService::isAlive(bool *alive) {
103    NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
104
105    *alive = true;
106    return binder::Status::ok();
107}
108
109binder::Status NetdNativeService::firewallReplaceUidChain(const android::String16& chainName,
110        bool isWhitelist, const std::vector<int32_t>& uids, bool *ret) {
111    NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->firewallCtrl.lock);
112
113    android::String8 name = android::String8(chainName);
114    int err = gCtls->firewallCtrl.replaceUidChain(name.string(), isWhitelist, uids);
115    *ret = (err == 0);
116    return binder::Status::ok();
117}
118
119binder::Status NetdNativeService::bandwidthEnableDataSaver(bool enable, bool *ret) {
120    NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->bandwidthCtrl.lock);
121
122    int err = gCtls->bandwidthCtrl.enableDataSaver(enable);
123    *ret = (err == 0);
124    return binder::Status::ok();
125}
126
127}  // namespace net
128}  // namespace android
129