Initial netd binder interface.
In this change:
1. AIDL files for a new, android.net.INetd service, and
corresponding implementation using generated code. For now the
interface is just a prototype: it only has one trivial method.
2. Permission checking code to check for CONNECTIVITY_INTERNAL.
3. Add a Big Netd Lock and provide a wrapper that makes it easy
to ensure that it is taken by every CommandListener command.
Bug: 27239233
Change-Id: I448d0ac233edd0e351a7fe7f13901fb6871683a2
diff --git a/server/Android.mk b/server/Android.mk
index b713b4f..dbbc5a1 100644
--- a/server/Android.mk
+++ b/server/Android.mk
@@ -16,6 +16,20 @@
include $(CLEAR_VARS)
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_CLANG := true
+LOCAL_MODULE := libnetdaidl
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libutils
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder
+LOCAL_SRC_FILES := binder/android/net/INetd.aidl
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+include $(CLEAR_VARS)
+
LOCAL_C_INCLUDES := \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
bionic/libc/dns/include \
@@ -29,6 +43,7 @@
LOCAL_INIT_RC := netd.rc
LOCAL_SHARED_LIBRARIES := \
+ libbinder \
libcrypto \
libcutils \
libdl \
@@ -36,6 +51,7 @@
liblog \
liblogwrap \
libmdnssd \
+ libnetdaidl \
libnetutils \
libnl \
libsysutils \
@@ -60,6 +76,7 @@
NatController.cpp \
NetdCommand.cpp \
NetdConstants.cpp \
+ NetdNativeService.cpp \
NetlinkHandler.cpp \
NetlinkManager.cpp \
Network.cpp \
diff --git a/server/CommandListener.cpp b/server/CommandListener.cpp
index af757c9..6f34752 100644
--- a/server/CommandListener.cpp
+++ b/server/CommandListener.cpp
@@ -171,20 +171,20 @@
CommandListener::CommandListener() :
FrameworkListener("netd", true) {
- registerCmd(new InterfaceCmd());
- registerCmd(new IpFwdCmd());
- registerCmd(new TetherCmd());
- registerCmd(new NatCmd());
- registerCmd(new ListTtysCmd());
- registerCmd(new PppdCmd());
- registerCmd(new SoftapCmd());
- registerCmd(new BandwidthControlCmd());
- registerCmd(new IdletimerControlCmd());
- registerCmd(new ResolverCmd());
- registerCmd(new FirewallCmd());
- registerCmd(new ClatdCmd());
- registerCmd(new NetworkCommand());
- registerCmd(new StrictCmd());
+ registerLockingCmd(new InterfaceCmd());
+ registerLockingCmd(new IpFwdCmd());
+ registerLockingCmd(new TetherCmd());
+ registerLockingCmd(new NatCmd());
+ registerLockingCmd(new ListTtysCmd());
+ registerLockingCmd(new PppdCmd());
+ registerLockingCmd(new SoftapCmd());
+ registerLockingCmd(new BandwidthControlCmd());
+ registerLockingCmd(new IdletimerControlCmd());
+ registerLockingCmd(new ResolverCmd());
+ registerLockingCmd(new FirewallCmd());
+ registerLockingCmd(new ClatdCmd());
+ registerLockingCmd(new NetworkCommand());
+ registerLockingCmd(new StrictCmd());
if (!sNetCtrl)
sNetCtrl = new NetworkController();
diff --git a/server/CommandListener.h b/server/CommandListener.h
index 72f4da1..77fbb1e 100644
--- a/server/CommandListener.h
+++ b/server/CommandListener.h
@@ -18,8 +18,10 @@
#define _COMMANDLISTENER_H__
#include <sysutils/FrameworkListener.h>
+#include "utils/RWLock.h"
#include "NetdCommand.h"
+#include "NetdConstants.h"
#include "NetworkController.h"
#include "TetherController.h"
#include "NatController.h"
@@ -33,6 +35,22 @@
#include "ClatdController.h"
#include "StrictController.h"
+
+class LockingFrameworkCommand : public FrameworkCommand {
+public:
+ LockingFrameworkCommand(FrameworkCommand *wrappedCmd) :
+ FrameworkCommand(wrappedCmd->getCommand()),
+ mWrappedCmd(wrappedCmd) {}
+
+ int runCommand(SocketClient *c, int argc, char **argv) {
+ android::RWLock::AutoWLock lock(android::net::gBigNetdLock);
+ return mWrappedCmd->runCommand(c, argc, argv);
+ }
+
+private:
+ FrameworkCommand *mWrappedCmd;
+};
+
class CommandListener : public FrameworkListener {
static TetherController *sTetherCtrl;
static NatController *sNatCtrl;
@@ -54,6 +72,10 @@
private:
+ void registerLockingCmd(FrameworkCommand *cmd) {
+ registerCmd(new LockingFrameworkCommand(cmd));
+ }
+
class SoftapCmd : public NetdCommand {
public:
SoftapCmd();
diff --git a/server/NetdConstants.h b/server/NetdConstants.h
index 296661d..5c3fde0 100644
--- a/server/NetdConstants.h
+++ b/server/NetdConstants.h
@@ -21,6 +21,8 @@
#include <list>
#include <stdarg.h>
+#include "utils/RWLock.h"
+
const int PROTECT_MARK = 0x1;
extern const char * const IPTABLES_PATH;
@@ -49,4 +51,18 @@
const uid_t INVALID_UID = static_cast<uid_t>(-1);
-#endif
+namespace android {
+namespace net {
+
+/**
+ * This lock exists to make NetdNativeService RPCs (which come in on multiple Binder threads)
+ * coexist with the commands in CommandListener.cpp. These are presumed not thread-safe because
+ * CommandListener has only one user (NetworkManagementService), which is connected through a
+ * FrameworkListener that passes in commands one at a time.
+ */
+extern android::RWLock gBigNetdLock;
+
+} // namespace net
+} // namespace android
+
+#endif // _NETD_CONSTANTS_H
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
new file mode 100644
index 0000000..f4b5a10
--- /dev/null
+++ b/server/NetdNativeService.cpp
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Netd"
+
+#include <android-base/stringprintf.h>
+#include <cutils/log.h>
+#include <utils/Errors.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include "android/net/BnNetd.h"
+
+#include "NetdConstants.h"
+#include "NetdNativeService.h"
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace net {
+
+namespace {
+
+const char CONNECTIVITY_INTERNAL[] = "android.permission.CONNECTIVITY_INTERNAL";
+
+binder::Status checkPermission(const char *permission) {
+ pid_t pid;
+ uid_t uid;
+
+ if (checkCallingPermission(String16(permission), (int32_t *) &pid, (int32_t *) &uid)) {
+ return binder::Status::ok();
+ } else {
+ auto err = StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission);
+ return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(err.c_str()));
+ }
+}
+
+#define ENFORCE_PERMISSION(permission) { \
+ binder::Status status = checkPermission((permission)); \
+ if (!status.isOk()) { \
+ return status; \
+ } \
+}
+
+#define NETD_LOCKING_RPC(permission) \
+ ENFORCE_PERMISSION(permission); \
+ android::RWLock::AutoWLock lock(gBigNetdLock);
+
+} // namespace
+
+
+binder::Status NetdNativeService::isAlive(bool *alive) {
+ NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL);
+
+ *alive = true;
+ return binder::Status::ok();
+}
+
+} // namespace net
+} // namespace android
diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h
new file mode 100644
index 0000000..6ca4432
--- /dev/null
+++ b/server/NetdNativeService.h
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _NETD_NATIVE_SERVICE_H_
+#define _NETD_NATIVE_SERVICE_H_
+
+#include <binder/BinderService.h>
+
+#include "android/net/BnNetd.h"
+
+namespace android {
+namespace net {
+
+class NetdNativeService : public BinderService<NetdNativeService>, public BnNetd {
+ public:
+ static char const* getServiceName() { return "android.net.INetd"; }
+ binder::Status isAlive(bool *alive) override;
+};
+
+} // namespace net
+} // namespace android
+
+#endif // _NETD_NATIVE_SERVICE_H_
diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
new file mode 100644
index 0000000..8242034
--- /dev/null
+++ b/server/binder/android/net/INetd.aidl
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/** {@hide} */
+interface INetd {
+ boolean isAlive();
+}
diff --git a/server/main.cpp b/server/main.cpp
index 5e189cc..2de0091 100644
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -29,13 +29,27 @@
#define LOG_TAG "Netd"
#include "cutils/log.h"
+#include "utils/RWLock.h"
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
#include "CommandListener.h"
+#include "NetdConstants.h"
+#include "NetdNativeService.h"
#include "NetlinkManager.h"
#include "DnsProxyListener.h"
#include "MDnsSdListener.h"
#include "FwmarkServer.h"
+using android::status_t;
+using android::sp;
+using android::IPCThreadState;
+using android::ProcessState;
+using android::defaultServiceManager;
+using android::net::NetdNativeService;
+
static void blockSigpipe();
static void remove_pid_file();
static bool write_pid_file();
@@ -44,6 +58,10 @@
const int PID_FILE_FLAGS = O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW | O_CLOEXEC;
const mode_t PID_FILE_MODE = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // mode 0644, rw-r--r--
+
+android::RWLock android::net::gBigNetdLock;
+
+
int main() {
CommandListener *cl;
@@ -99,17 +117,15 @@
exit(1);
}
- bool wrote_pid = write_pid_file();
+ write_pid_file();
- while(1) {
- sleep(30); // 30 sec
- if (!wrote_pid) {
- wrote_pid = write_pid_file();
- }
- }
+ IPCThreadState::self()->disableBackgroundScheduling(true);
+ NetdNativeService::publishAndJoinThreadPool();
ALOGI("Netd exiting");
+
remove_pid_file();
+
exit(0);
}