system/netd: Add support for per app network isolation
* Add a new firewall chain fw_isolated that blocks all network access.
* Legacy ipchains and bpf are both supported.
Change-Id: Iab892d8d3d1803fe2626b2a5966e5646cb8b4922
diff --git a/bpf_progs/netd.h b/bpf_progs/netd.h
index cc5f845..a0e586a 100644
--- a/bpf_progs/netd.h
+++ b/bpf_progs/netd.h
@@ -187,6 +187,9 @@
if ((enabledRules & POWERSAVE_MATCH) && !(uidRules & POWERSAVE_MATCH)) {
return BPF_DROP;
}
+ if ((enabledRules & ISOLATED_MATCH) && (uidRules & ISOLATED_MATCH)) {
+ return BPF_DROP;
+ }
}
if (direction == BPF_INGRESS && (uidRules & IIF_MATCH)) {
// Drops packets not coming from lo nor the whitelisted interface
diff --git a/libnetdbpf/include/netdbpf/bpf_shared.h b/libnetdbpf/include/netdbpf/bpf_shared.h
index 6424c81..4335373 100644
--- a/libnetdbpf/include/netdbpf/bpf_shared.h
+++ b/libnetdbpf/include/netdbpf/bpf_shared.h
@@ -86,6 +86,7 @@
POWERSAVE_MATCH = (1 << 4),
IIF_MATCH = (1 << 5),
IF_BLACKLIST = (1 << 6),
+ ISOLATED_MATCH = (1 << 7),
};
enum BpfPemissionMatch {
diff --git a/server/FirewallController.cpp b/server/FirewallController.cpp
index 7512c09..d15aeb2 100644
--- a/server/FirewallController.cpp
+++ b/server/FirewallController.cpp
@@ -74,6 +74,7 @@
const char* FirewallController::LOCAL_DOZABLE = "fw_dozable";
const char* FirewallController::LOCAL_STANDBY = "fw_standby";
const char* FirewallController::LOCAL_POWERSAVE = "fw_powersave";
+const char* FirewallController::LOCAL_ISOLATED = "fw_isolated";
// ICMPv6 types that are required for any form of IPv6 connectivity to work. Note that because the
// fw_dozable chain is called from both INPUT and OUTPUT, this includes both packets that we need
@@ -102,6 +103,7 @@
res |= createChain(LOCAL_DOZABLE, getFirewallType(DOZABLE));
res |= createChain(LOCAL_STANDBY, getFirewallType(STANDBY));
res |= createChain(LOCAL_POWERSAVE, getFirewallType(POWERSAVE));
+ res |= createChain(LOCAL_ISOLATED, getFirewallType(ISOLATED));
return res;
}
@@ -156,6 +158,9 @@
case POWERSAVE:
name = LOCAL_POWERSAVE;
break;
+ case ISOLATED:
+ name = LOCAL_ISOLATED;
+ break;
default:
return res;
}
@@ -220,6 +225,8 @@
return BLACKLIST;
case POWERSAVE:
return WHITELIST;
+ case ISOLATED:
+ return BLACKLIST;
case NONE:
return mFirewallType;
default:
@@ -236,7 +243,7 @@
// When adding, insert RETURN rules at the front, before the catch-all DROP at the end.
op = (rule == ALLOW)? "-I" : "-D";
} else { // BLACKLIST mode
- target = "DROP";
+ target = (chain == ISOLATED) ? "REJECT" : "DROP";
// When adding, append DROP rules at the end, after the RETURN rule that matches TCP RSTs.
op = (rule == DENY)? "-A" : "-D";
}
@@ -252,6 +259,9 @@
case POWERSAVE:
chainNames = { LOCAL_POWERSAVE };
break;
+ case ISOLATED:
+ chainNames = { LOCAL_ISOLATED };
+ break;
case NONE:
chainNames = { LOCAL_INPUT, LOCAL_OUTPUT };
break;
diff --git a/server/FirewallController.h b/server/FirewallController.h
index 43da322..99fe2c4 100644
--- a/server/FirewallController.h
+++ b/server/FirewallController.h
@@ -43,6 +43,7 @@
DOZABLE = INetd::FIREWALL_CHAIN_DOZABLE,
STANDBY = INetd::FIREWALL_CHAIN_STANDBY,
POWERSAVE = INetd::FIREWALL_CHAIN_POWERSAVE,
+ ISOLATED = INetd::FIREWALL_CHAIN_ISOLATED,
INVALID_CHAIN
};
@@ -85,6 +86,7 @@
static const char* LOCAL_DOZABLE;
static const char* LOCAL_STANDBY;
static const char* LOCAL_POWERSAVE;
+ static const char* LOCAL_ISOLATED;
static const char* ICMPV6_TYPES[];
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index 4b0e76a..ccbe6ef 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -103,6 +103,7 @@
FLAG_MSG_TRANS(matchType, POWERSAVE_MATCH, match);
FLAG_MSG_TRANS(matchType, IIF_MATCH, match);
FLAG_MSG_TRANS(matchType, IF_BLACKLIST, match);
+ FLAG_MSG_TRANS(matchType, ISOLATED_MATCH, match);
if (match) {
return StringPrintf("Unknown match: %u", match);
}
@@ -694,6 +695,9 @@
case POWERSAVE:
res = updateOwnerMapEntry(POWERSAVE_MATCH, uid, rule, type);
break;
+ case ISOLATED:
+ res = updateOwnerMapEntry(ISOLATED_MATCH, uid, rule, type);
+ break;
case NONE:
default:
return -EINVAL;
@@ -825,6 +829,8 @@
res = replaceRulesInMap(STANDBY_MATCH, uids);
} else if (!name.compare(FirewallController::LOCAL_POWERSAVE)) {
res = replaceRulesInMap(POWERSAVE_MATCH, uids);
+ } else if (!name.compare(FirewallController::LOCAL_ISOLATED)) {
+ res = replaceRulesInMap(ISOLATED_MATCH, uids);
} else {
ALOGE("unknown chain name: %s", name.c_str());
return -EINVAL;
@@ -858,6 +864,9 @@
case POWERSAVE:
match = POWERSAVE_MATCH;
break;
+ case ISOLATED:
+ match = ISOLATED_MATCH;
+ break;
default:
return -EINVAL;
}
diff --git a/server/aidl/netd/2/android/net/INetd.aidl b/server/aidl/netd/2/android/net/INetd.aidl
index a5f4f71..becd721 100644
--- a/server/aidl/netd/2/android/net/INetd.aidl
+++ b/server/aidl/netd/2/android/net/INetd.aidl
@@ -152,4 +152,5 @@
const String IF_FLAG_POINTOPOINT = "point-to-point";
const String IF_FLAG_RUNNING = "running";
const String IF_FLAG_MULTICAST = "multicast";
+ const int FIREWALL_CHAIN_ISOLATED = 4;
}
diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
index 8b5435a..5f58e00 100644
--- a/server/binder/android/net/INetd.aidl
+++ b/server/binder/android/net/INetd.aidl
@@ -1057,6 +1057,10 @@
const String IF_FLAG_RUNNING = "running";
const String IF_FLAG_MULTICAST = "multicast";
+ // Specify ISOLATED chain (fw_isolated) which is used to unconditionally block all app
+ // network access.
+ const int FIREWALL_CHAIN_ISOLATED = 4;
+
/**
* Get interface configuration
*