OSDN Git Service

Do not enforce CONTROL_VPN for calls from lockdown VPN.
authorJeff Davidson <jpd@google.com>
Tue, 10 Feb 2015 18:02:11 +0000 (10:02 -0800)
committerJeff Davidson <jpd@google.com>
Wed, 11 Feb 2015 07:41:42 +0000 (23:41 -0800)
Clearly document which methods in Vpn.java are designed to be used to
service a Binder call, and which must therefore check permissions and
clear the calling identity, and which methods are designed for
internal use only and which therefore need not check permission.

Add a new startLegacyVpnPrivileged method which bypasses the
permission checks, to be used by lockdown VPN which is a trusted
system service. Ensure that the existing startLegacyVpn method checks
permissions as this is used whenever we respond to a binder call.

Bug: 19311172
Change-Id: I34f13258ee7481f1356bc523124cf5db068b4972

services/core/java/com/android/server/connectivity/Vpn.java
services/core/java/com/android/server/net/LockdownVpnTracker.java

index f08a652..8533f69 100644 (file)
@@ -846,9 +846,29 @@ public class Vpn {
     /**
      * Start legacy VPN, controlling native daemons as needed. Creates a
      * secondary thread to perform connection work, returning quickly.
+     *
+     * Should only be called to respond to Binder requests as this enforces caller permission. Use
+     * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the
+     * permission check only when the caller is trusted (or the call is initiated by the system).
      */
     public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
         enforceControlPermission();
+        long token = Binder.clearCallingIdentity();
+        try {
+            startLegacyVpnPrivileged(profile, keyStore, egress);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check
+     * permissions under the assumption that the caller is the system.
+     *
+     * Callers are responsible for checking permissions if needed.
+     */
+    public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore,
+            LinkProperties egress) {
         if (!keyStore.isUnlocked()) {
             throw new IllegalStateException("KeyStore isn't unlocked");
         }
@@ -959,10 +979,10 @@ public class Vpn {
     }
 
     private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
-        stopLegacyVpn();
+        stopLegacyVpnPrivileged();
 
-        // Prepare for the new request. This also checks the caller.
-        prepare(null, VpnConfig.LEGACY_VPN);
+        // Prepare for the new request.
+        prepareInternal(VpnConfig.LEGACY_VPN);
         updateState(DetailedState.CONNECTING, "startLegacyVpn");
 
         // Start a new LegacyVpnRunner and we are done!
@@ -970,7 +990,8 @@ public class Vpn {
         mLegacyVpnRunner.start();
     }
 
-    public synchronized void stopLegacyVpn() {
+    /** Stop legacy VPN. Permissions must be checked by callers. */
+    public synchronized void stopLegacyVpnPrivileged() {
         if (mLegacyVpnRunner != null) {
             mLegacyVpnRunner.exit();
             mLegacyVpnRunner = null;
index 3a1e4a4..752614f 100644 (file)
@@ -140,7 +140,7 @@ public class LockdownVpnTracker {
         if (egressDisconnected || egressChanged) {
             clearSourceRulesLocked();
             mAcceptedEgressIface = null;
-            mVpn.stopLegacyVpn();
+            mVpn.stopLegacyVpnPrivileged();
         }
         if (egressDisconnected) {
             hideNotification();
@@ -163,7 +163,9 @@ public class LockdownVpnTracker {
 
                 mAcceptedEgressIface = egressProp.getInterfaceName();
                 try {
-                    mVpn.startLegacyVpn(mProfile, KeyStore.getInstance(), egressProp);
+                    // Use the privileged method because Lockdown VPN is initiated by the system, so
+                    // no additional permission checks are necessary.
+                    mVpn.startLegacyVpnPrivileged(mProfile, KeyStore.getInstance(), egressProp);
                 } catch (IllegalStateException e) {
                     mAcceptedEgressIface = null;
                     Slog.e(TAG, "Failed to start VPN", e);
@@ -250,7 +252,7 @@ public class LockdownVpnTracker {
         mAcceptedEgressIface = null;
         mErrorCount = 0;
 
-        mVpn.stopLegacyVpn();
+        mVpn.stopLegacyVpnPrivileged();
         try {
             mNetService.setFirewallEgressDestRule(mProfile.server, 500, false);
             mNetService.setFirewallEgressDestRule(mProfile.server, 4500, false);