am eb3c0d9a: am 1aad3ad4: Merge "Fix support for simultaneous VPN tuns" into klp-dev
* commit 'eb3c0d9ac387bb0aea5b4956daac1403253bc76d':
Fix support for simultaneous VPN tuns
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 0a58552..376414b 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -352,6 +352,12 @@
Binder.restoreCallingIdentity(token);
}
+ // Save the old config in case we need to go back.
+ VpnConfig oldConfig = mConfig;
+ String oldInterface = mInterface;
+ Connection oldConnection = mConnection;
+ SparseBooleanArray oldUsers = mVpnUsers;
+
// Configure the interface. Abort if any of these steps fails.
ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
try {
@@ -371,12 +377,7 @@
new UserHandle(mUserId))) {
throw new IllegalStateException("Cannot bind " + config.user);
}
- if (mConnection != null) {
- mContext.unbindService(mConnection);
- }
- if (mInterface != null && !mInterface.equals(interfaze)) {
- jniReset(mInterface);
- }
+
mConnection = connection;
mInterface = interfaze;
@@ -385,50 +386,74 @@
config.interfaze = mInterface;
config.startTime = SystemClock.elapsedRealtime();
mConfig = config;
+
// Set up forwarding and DNS rules.
mVpnUsers = new SparseBooleanArray();
token = Binder.clearCallingIdentity();
try {
mCallback.setMarkedForwarding(mInterface);
- mCallback.setRoutes(interfaze, config.routes);
+ mCallback.setRoutes(mInterface, config.routes);
mCallback.override(mInterface, config.dnsServers, config.searchDomains);
addVpnUserLocked(mUserId);
-
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- } catch (RuntimeException e) {
- updateState(DetailedState.FAILED, "establish");
- IoUtils.closeQuietly(tun);
- // make sure marked forwarding is cleared if it was set
- try {
- mCallback.clearMarkedForwarding(mInterface);
- } catch (Exception ingored) {
- // ignored
- }
- throw e;
- }
- Log.i(TAG, "Established by " + config.user + " on " + mInterface);
-
-
- // If we are owner assign all Restricted Users to this VPN
- if (mUserId == UserHandle.USER_OWNER) {
- token = Binder.clearCallingIdentity();
- try {
- for (UserInfo user : mgr.getUsers()) {
- if (user.isRestricted()) {
- try {
- addVpnUserLocked(user.id);
- } catch (Exception e) {
- Log.wtf(TAG, "Failed to add user " + user.id + " to owner's VPN");
+ // If we are owner assign all Restricted Users to this VPN
+ if (mUserId == UserHandle.USER_OWNER) {
+ for (UserInfo user : mgr.getUsers()) {
+ if (user.isRestricted()) {
+ try {
+ addVpnUserLocked(user.id);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Failed to add user " + user.id + " to owner's VPN");
+ }
}
}
}
} finally {
Binder.restoreCallingIdentity(token);
}
+
+ if (oldConnection != null) {
+ mContext.unbindService(oldConnection);
+ }
+ if (oldInterface != null && !oldInterface.equals(interfaze)) {
+ // Remove the old tun's user forwarding rules
+ // The new tun's user rules have already been added so they will take over
+ // as rules are deleted. This prevents data leakage as the rules are moved over.
+ token = Binder.clearCallingIdentity();
+ try {
+ final int size = oldUsers.size();
+ final boolean forwardDns = (oldConfig.dnsServers != null &&
+ oldConfig.dnsServers.size() != 0);
+ for (int i = 0; i < size; i++) {
+ int user = oldUsers.keyAt(i);
+ mCallback.clearUserForwarding(oldInterface, user, forwardDns);
+ }
+ mCallback.clearMarkedForwarding(oldInterface);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ jniReset(oldInterface);
+ }
+ } catch (RuntimeException e) {
+ updateState(DetailedState.FAILED, "establish");
+ IoUtils.closeQuietly(tun);
+ // make sure marked forwarding is cleared if it was set
+ token = Binder.clearCallingIdentity();
+ try {
+ mCallback.clearMarkedForwarding(mInterface);
+ } catch (Exception ingored) {
+ // ignored
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ // restore old state
+ mConfig = oldConfig;
+ mConnection = oldConnection;
+ mVpnUsers = oldUsers;
+ mInterface = oldInterface;
+ throw e;
}
+ Log.i(TAG, "Established by " + config.user + " on " + mInterface);
+
// TODO: ensure that contract class eventually marks as connected
updateState(DetailedState.AUTHENTICATING, "establish");
return tun;