Allow finer-grained locking, and use it in FirewallCmd.
FirewallController is stateless and FirewallCmd does not access
any other controllers, so it is safe not to take the big netd
lock.
Bug: 27239233
Change-Id: I246696c4b17fa005c7d6b38ecd627747aa608831
diff --git a/server/CommandListener.cpp b/server/CommandListener.cpp
index 6e03563..1a291b1 100644
--- a/server/CommandListener.cpp
+++ b/server/CommandListener.cpp
@@ -82,6 +82,24 @@
return strtoul(arg, NULL, 0);
}
+class LockingFrameworkCommand : public FrameworkCommand {
+public:
+ LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
+ FrameworkCommand(wrappedCmd->getCommand()),
+ mWrappedCmd(wrappedCmd),
+ mLock(lock) {}
+
+ int runCommand(SocketClient *c, int argc, char **argv) {
+ android::RWLock::AutoWLock lock(mLock);
+ return mWrappedCmd->runCommand(c, argc, argv);
+ }
+
+private:
+ FrameworkCommand *mWrappedCmd;
+ android::RWLock& mLock;
+};
+
+
} // namespace
/**
@@ -159,6 +177,10 @@
} while (*(++childChain) != NULL);
}
+void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
+ registerCmd(new LockingFrameworkCommand(cmd, lock));
+}
+
CommandListener::CommandListener() :
FrameworkListener("netd", true) {
registerLockingCmd(new InterfaceCmd());
@@ -171,7 +193,7 @@
registerLockingCmd(new BandwidthControlCmd());
registerLockingCmd(new IdletimerControlCmd());
registerLockingCmd(new ResolverCmd());
- registerLockingCmd(new FirewallCmd());
+ registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
registerLockingCmd(new ClatdCmd());
registerLockingCmd(new NetworkCommand());
registerLockingCmd(new StrictCmd());
diff --git a/server/CommandListener.h b/server/CommandListener.h
index 2e29246..56323d6 100644
--- a/server/CommandListener.h
+++ b/server/CommandListener.h
@@ -35,29 +35,15 @@
#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 {
public:
CommandListener();
virtual ~CommandListener() {}
private:
+ void registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock);
void registerLockingCmd(FrameworkCommand *cmd) {
- registerCmd(new LockingFrameworkCommand(cmd));
+ registerLockingCmd(cmd, android::net::gBigNetdLock);
}
class SoftapCmd : public NetdCommand {
diff --git a/server/Controllers.h b/server/Controllers.h
index e608981..5634800 100644
--- a/server/Controllers.h
+++ b/server/Controllers.h
@@ -18,6 +18,7 @@
#define _CONTROLLERS_H__
#include <sysutils/FrameworkListener.h>
+
#include "NetworkController.h"
#include "TetherController.h"
#include "NatController.h"
diff --git a/server/FirewallController.h b/server/FirewallController.h
index 34a8b9c..d3ef777 100644
--- a/server/FirewallController.h
+++ b/server/FirewallController.h
@@ -19,6 +19,8 @@
#include <string>
+#include <utils/RWLock.h>
+
enum FirewallRule { DENY, ALLOW };
// WHITELIST means the firewall denies all by default, uids must be explicitly ALLOWed
@@ -34,6 +36,10 @@
/*
* Simple firewall that drops all packets except those matching explicitly
* defined ALLOW rules.
+ *
+ * Methods in this class must be called when holding a write lock on |lock|, and may not call
+ * any other controller without explicitly managing that controller's lock. There are currently
+ * no such methods.
*/
class FirewallController {
public:
@@ -67,6 +73,8 @@
static const char* ICMPV6_TYPES[];
+ android::RWLock lock;
+
private:
FirewallType mFirewallType;
int attachChain(const char*, const char*);