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

Commit d7795cd5 authored by Chiachang Wang's avatar Chiachang Wang Committed by Automerger Merge Worker
Browse files

Merge "Resolve UidRange dependency between NMS and CS module" am: c3806f72

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1495869

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I2e55c3c4bed3d71eb48242428c179809aae00a1f
parents 62621db9 c3806f72
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -320,16 +320,6 @@ interface INetworkManagementService
    void setFirewallUidRules(int chain, in int[] uids, in int[] rules);
    void setFirewallChainEnabled(int chain, boolean enable);

    /**
     * Set all packets from users in ranges to go through VPN specified by netId.
     */
    void addVpnUidRanges(int netId, in UidRange[] ranges);

    /**
     * Clears the special VPN rules for users in ranges and VPN specified by netId.
     */
    void removeVpnUidRanges(int netId, in UidRange[] ranges);

    /**
     * Start listening for mobile activity state changes.
     */
@@ -361,7 +351,5 @@ interface INetworkManagementService
    void removeInterfaceFromLocalNetwork(String iface);
    int removeRoutesFromLocalNetwork(in List<RouteInfo> routes);

    void setAllowOnlyVpnForUids(boolean enable, in UidRange[] uidRanges);

    boolean isNetworkRestricted(int uid);
}
+15 −7
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ import android.net.RouteInfoParcel;
import android.net.SocketKeepalive;
import android.net.TetheringManager;
import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnService;
@@ -5152,7 +5153,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                loge("Starting user already has a VPN");
                return;
            }
            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore);
            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore);
            mVpns.put(userId, userVpn);
            if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
                updateLockdownVpn();
@@ -6622,6 +6623,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
                && (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
    }

    private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
        final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()];
        int index = 0;
        for (UidRange range : ranges) {
            stableRanges[index] = new UidRangeParcel(range.start, range.stop);
            index++;
        }
        return stableRanges;
    }

    private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
            NetworkCapabilities newNc) {
        Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
@@ -6641,14 +6652,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
            // removing old range works because, unlike the filtering rules below, it's possible to
            // add duplicate UID routing rules.
            if (!newRanges.isEmpty()) {
                final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
                newRanges.toArray(addedRangesArray);
                mNMS.addVpnUidRanges(nai.network.getNetId(), addedRangesArray);
                mNetd.networkAddUidRanges(nai.network.netId, toUidRangeStableParcels(newRanges));
            }
            if (!prevRanges.isEmpty()) {
                final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
                prevRanges.toArray(removedRangesArray);
                mNMS.removeVpnUidRanges(nai.network.getNetId(), removedRangesArray);
                mNetd.networkRemoveUidRanges(
                        nai.network.netId, toUidRangeStableParcels(prevRanges));
            }
            final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties);
            final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties);
+2 −56
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ import android.net.NetworkStack;
import android.net.NetworkStats;
import android.net.RouteInfo;
import android.net.TetherStatsParcel;
import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.shared.NetdUtils;
import android.net.shared.RouteUtils;
@@ -1393,38 +1392,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
        }
    }

    private static UidRangeParcel makeUidRangeParcel(int start, int stop) {
        UidRangeParcel range = new UidRangeParcel();
        range.start = start;
        range.stop = stop;
        return range;
    }

    private static UidRangeParcel[] toStableParcels(UidRange[] ranges) {
        UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length];
        for (int i = 0; i < ranges.length; i++) {
            stableRanges[i] = makeUidRangeParcel(ranges[i].start, ranges[i].stop);
        }
        return stableRanges;
    }

    @Override
    public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
            throws ServiceSpecificException {
        NetworkStack.checkNetworkStackPermission(mContext);
        try {
            mNetdService.networkRejectNonSecureVpn(add, toStableParcels(uidRanges));
        } catch (ServiceSpecificException e) {
            Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
                    + ": netd command failed", e);
            throw e;
        } catch (RemoteException e) {
            Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
                    + ": netd command failed", e);
            throw e.rethrowAsRuntimeException();
        }
    }

    private void applyUidCleartextNetworkPolicy(int uid, int policy) {
        final int policyValue;
        switch (policy) {
@@ -1552,27 +1519,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
        return stats;
    }

    @Override
    public void addVpnUidRanges(int netId, UidRange[] ranges) {
        NetworkStack.checkNetworkStackPermission(mContext);

        try {
            mNetdService.networkAddUidRanges(netId, toStableParcels(ranges));
        } catch (RemoteException | ServiceSpecificException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void removeVpnUidRanges(int netId, UidRange[] ranges) {
        NetworkStack.checkNetworkStackPermission(mContext);
        try {
            mNetdService.networkRemoveUidRanges(netId, toStableParcels(ranges));
        } catch (RemoteException | ServiceSpecificException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void setFirewallEnabled(boolean enabled) {
        enforceSystemUid();
@@ -1616,7 +1562,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
            ranges = new UidRangeParcel[] {
                // TODO: is there a better way of finding all existing users? If so, we could
                // specify their ranges here.
                makeUidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
                new UidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
            };
            // ... except for the UIDs that have allow rules.
            synchronized (mRulesLock) {
@@ -1647,7 +1593,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
                for (int i = 0; i < ranges.length; i++) {
                    if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
                        int uid = rules.keyAt(i);
                        ranges[numUids] = makeUidRangeParcel(uid, uid);
                        ranges[numUids] = new UidRangeParcel(uid, uid);
                        numUids++;
                    }
                }
+39 −24
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.net.ConnectivityManager;
import android.net.DnsResolver;
import android.net.INetd;
import android.net.INetworkManagementEventObserver;
import android.net.Ikev2VpnProfile;
import android.net.IpPrefix;
@@ -68,6 +69,7 @@ import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.RouteInfo;
import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.VpnManager;
import android.net.VpnService;
import android.net.ipsec.ike.ChildSessionCallback;
@@ -188,7 +190,8 @@ public class Vpn {

    private PendingIntent mStatusIntent;
    private volatile boolean mEnableTeardown = true;
    private final INetworkManagementService mNetd;
    private final INetworkManagementService mNms;
    private final INetd mNetd;
    @VisibleForTesting
    protected VpnConfig mConfig;
    private final NetworkProvider mNetworkProvider;
@@ -234,7 +237,7 @@ public class Vpn {
     * @see mLockdown
     */
    @GuardedBy("this")
    private final Set<UidRange> mBlockedUidsAsToldToNetd = new ArraySet<>();
    private final Set<UidRangeParcel> mBlockedUidsAsToldToNetd = new ArraySet<>();

    // The user id of initiating VPN.
    private final int mUserId;
@@ -363,22 +366,23 @@ public class Vpn {
        }
    }

    public Vpn(Looper looper, Context context, INetworkManagementService netService,
    public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
            @UserIdInt int userId, @NonNull KeyStore keyStore) {
        this(looper, context, new Dependencies(), netService, userId, keyStore,
        this(looper, context, new Dependencies(), netService, netd, userId, keyStore,
                new SystemServices(context), new Ikev2SessionCreator());
    }

    @VisibleForTesting
    protected Vpn(Looper looper, Context context, Dependencies deps,
            INetworkManagementService netService,
            INetworkManagementService netService, INetd netd,
            int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
            Ikev2SessionCreator ikev2SessionCreator) {
        mContext = context;
        mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
        mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
        mDeps = deps;
        mNetd = netService;
        mNms = netService;
        mNetd = netd;
        mUserId = userId;
        mLooper = looper;
        mSystemServices = systemServices;
@@ -912,7 +916,7 @@ public class Vpn {
            }

            try {
                mNetd.denyProtect(mOwnerUID);
                mNms.denyProtect(mOwnerUID);
            } catch (Exception e) {
                Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
            }
@@ -922,7 +926,7 @@ public class Vpn {
            mOwnerUID = getAppUid(newPackage, mUserId);
            mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
            try {
                mNetd.allowProtect(mOwnerUID);
                mNms.allowProtect(mOwnerUID);
            } catch (Exception e) {
                Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
            }
@@ -1579,24 +1583,25 @@ public class Vpn {
            exemptedPackages = new ArrayList<>(mLockdownAllowlist);
            exemptedPackages.add(mPackage);
        }
        final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd);
        final Set<UidRangeParcel> rangesToTellNetdToRemove =
                new ArraySet<>(mBlockedUidsAsToldToNetd);

        final Set<UidRange> rangesToTellNetdToAdd;
        final Set<UidRangeParcel> rangesToTellNetdToAdd;
        if (enforce) {
            final Set<UidRange> rangesThatShouldBeBlocked =
            final Set<UidRange> restrictedProfilesRanges =
                    createUserAndRestrictedProfilesRanges(mUserId,
                    /* allowedApplications */ null,
                    /* disallowedApplications */ exemptedPackages);
            final Set<UidRangeParcel> rangesThatShouldBeBlocked = new ArraySet<>();

            // The UID range of the first user (0-99999) would block the IPSec traffic, which comes
            // directly from the kernel and is marked as uid=0. So we adjust the range to allow
            // it through (b/69873852).
            for (UidRange range : rangesThatShouldBeBlocked) {
                if (range.start == 0) {
                    rangesThatShouldBeBlocked.remove(range);
                    if (range.stop != 0) {
                        rangesThatShouldBeBlocked.add(new UidRange(1, range.stop));
                    }
            for (UidRange range : restrictedProfilesRanges) {
                if (range.start == 0 && range.stop != 0) {
                    rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.stop));
                } else if (range.start != 0) {
                    rangesThatShouldBeBlocked.add(new UidRangeParcel(range.start, range.stop));
                }
            }

@@ -1628,13 +1633,13 @@ public class Vpn {
     *         including added ranges that already existed or removed ones that didn't.
     */
    @GuardedBy("this")
    private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) {
    private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRangeParcel> ranges) {
        if (ranges.size() == 0) {
            return true;
        }
        final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]);
        final UidRangeParcel[] stableRanges = ranges.toArray(new UidRangeParcel[ranges.size()]);
        try {
            mNetd.setAllowOnlyVpnForUids(enforce, rangesArray);
            mNetd.networkRejectNonSecureVpn(enforce, stableRanges);
        } catch (RemoteException | RuntimeException e) {
            Log.e(TAG, "Updating blocked=" + enforce
                    + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e);
@@ -1849,8 +1854,18 @@ public class Vpn {
        if (mNetworkInfo.isConnected()) {
            return !appliesToUid(uid);
        } else {
            return UidRange.containsUid(mBlockedUidsAsToldToNetd, uid);
            return containsUid(mBlockedUidsAsToldToNetd, uid);
        }
    }

    private boolean containsUid(Collection<UidRangeParcel> ranges, int uid) {
        if (ranges == null) return false;
        for (UidRangeParcel range : ranges) {
            if (range.start <= uid && uid <= range.stop) {
                return true;
            }
        }
        return false;
    }

    private void updateAlwaysOnNotification(DetailedState networkState) {
@@ -2495,7 +2510,7 @@ public class Vpn {
                                    address /* unused */,
                                    address /* unused */,
                                    network);
                    mNetd.setInterfaceUp(mTunnelIface.getInterfaceName());
                    mNms.setInterfaceUp(mTunnelIface.getInterfaceName());

                    mSession = mIkev2SessionCreator.createIkeSession(
                            mContext,
+12 −5
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ import android.net.RouteInfo;
import android.net.RouteInfoParcel;
import android.net.SocketKeepalive;
import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.Uri;
import android.net.VpnManager;
import android.net.metrics.IpConnectivityLog;
@@ -1055,7 +1056,7 @@ public class ConnectivityServiceTest {

        public MockVpn(int userId) {
            super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
                    userId, mock(KeyStore.class));
                    mMockNetd, userId, mock(KeyStore.class));
            mConfig = new VpnConfig();
        }

@@ -1094,10 +1095,11 @@ public class ConnectivityServiceTest {
            mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
                    mNetworkCapabilities);
            mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
            verify(mNetworkManagementService, times(1))
                    .addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0])));
            verify(mNetworkManagementService, never())
                    .removeVpnUidRanges(eq(mMockVpn.getNetId()), any());

            verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetId()),
                    eq(toUidRangeStableParcels(uids)));
            verify(mMockNetd, never())
                    .networkRemoveUidRanges(eq(mMockVpn.getNetId()), any());
            mAgentRegistered = true;
            mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
            mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
@@ -1169,6 +1171,11 @@ public class ConnectivityServiceTest {
        }
    }

    private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
        return ranges.stream().map(
                r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
    }

    private void mockVpn(int uid) {
        synchronized (mService.mVpns) {
            int userId = UserHandle.getUserId(uid);
Loading