Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1aad3ad4 authored by Chad Brubaker's avatar Chad Brubaker Committed by Android (Google) Code Review
Browse files

Merge "Fix support for simultaneous VPN tuns" into klp-dev

parents de4e7b49 4c5c33e5
Loading
Loading
Loading
Loading
+51 −26
Original line number Diff line number Diff line
@@ -352,6 +352,12 @@ public class Vpn extends BaseNetworkStateTracker {
            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 @@ public class Vpn extends BaseNetworkStateTracker {
                        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 @@ public class Vpn extends BaseNetworkStateTracker {
            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);

                // 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);


        // 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");
                        }
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
        // TODO: ensure that contract class eventually marks as connected
        updateState(DetailedState.AUTHENTICATING, "establish");
        return tun;