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

Commit e9261ea9 authored by Roshan Pius's avatar Roshan Pius
Browse files

NetworkCapabilities: Embed location senstive TransportInfo

Changes:
i) Add a new constructor for NetworkCapabilities which accepts whether
location sensitive fields need to be parceled or not. Defalts to false
on the other constructor. This boolean should only be set on the copy of
NetworkCapabilities when sent to apps that hold location permission.
(Similar to how sensitive fields are handled in LinkProperties)
ii) Add a new makeCopy() method in the TransportInfo interface which
accepts whether location sensitive fields need to be parceled or not.
iii) Migrate the existing NetworkCapabilities owner UID masking to use
this new mechanism (instead of existing masking in ConnectivityService).
iv) Always set parcelLocationSensitiveFields to true in the NetworkAgent
surface (since that is a privileged surface from the transports to the
connectivity service)
v) Add a hasSensitiveFields() in TransportInfo interface to avoid
perfoming location permission checks for location insensitive
TrasnsportInfo.

Also, migrate to the new SdkLevel util for isAtLeastR() & isAtLeastS()
checks.

Bug: 162602799
Test: atest android.net
Test: atest com.android.server
Change-Id: Ie522d8c75a82ae521ccfd5165823d0c72642e651
parent 24686a67
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -6851,6 +6851,7 @@ package android.net {
  }
  public final class NetworkCapabilities implements android.os.Parcelable {
    ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean);
    method @NonNull public int[] getAdministratorUids();
    method @Nullable public String getSsid();
    method @NonNull public int[] getTransportTypes();
@@ -7072,6 +7073,11 @@ package android.net {
    field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = -256; // 0xffffff00
  }
  public interface TransportInfo {
    method public default boolean hasLocationSensitiveFields();
    method @NonNull public default android.net.TransportInfo makeCopy(boolean);
  }
  public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
    method @NonNull public String toSafeString();
  }
+5 −2
Original line number Diff line number Diff line
@@ -408,7 +408,8 @@ public abstract class NetworkAgent {
            throw new IllegalArgumentException();
        }

        mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc),
        mInitialConfiguration = new InitialConfiguration(context,
                new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true),
                new LinkProperties(lp), score, config, ni);
    }

@@ -818,7 +819,9 @@ public abstract class NetworkAgent {
        Objects.requireNonNull(networkCapabilities);
        mBandwidthUpdatePending.set(false);
        mLastBwRefreshTime = System.currentTimeMillis();
        final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
        final NetworkCapabilities nc =
                new NetworkCapabilities(networkCapabilities,
                        /* parcelLocationSensitiveFields */ true);
        queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc));
    }

+34 −1
Original line number Diff line number Diff line
@@ -76,12 +76,33 @@ public final class NetworkCapabilities implements Parcelable {
     */
    private String mRequestorPackageName;

    /**
     * Indicates whether parceling should preserve fields that are set based on permissions of
     * the process receiving the {@link NetworkCapabilities}.
     */
    private final boolean mParcelLocationSensitiveFields;

    public NetworkCapabilities() {
        mParcelLocationSensitiveFields = false;
        clearAll();
        mNetworkCapabilities = DEFAULT_CAPABILITIES;
    }

    public NetworkCapabilities(NetworkCapabilities nc) {
        this(nc, false /* parcelLocationSensitiveFields */);
    }

    /**
     * Make a copy of NetworkCapabilities.
     *
     * @param nc Original NetworkCapabilities
     * @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not.
     * @hide
     */
    @SystemApi
    public NetworkCapabilities(
            @Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) {
        mParcelLocationSensitiveFields = parcelLocationSensitiveFields;
        if (nc != null) {
            set(nc);
        }
@@ -93,6 +114,12 @@ public final class NetworkCapabilities implements Parcelable {
     * @hide
     */
    public void clearAll() {
        // Ensures that the internal copies maintained by the connectivity stack does not set
        // this bit.
        if (mParcelLocationSensitiveFields) {
            throw new UnsupportedOperationException(
                    "Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set");
        }
        mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0;
        mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
        mNetworkSpecifier = null;
@@ -109,6 +136,8 @@ public final class NetworkCapabilities implements Parcelable {

    /**
     * Set all contents of this object to the contents of a NetworkCapabilities.
     *
     * @param nc Original NetworkCapabilities
     * @hide
     */
    public void set(@NonNull NetworkCapabilities nc) {
@@ -117,7 +146,11 @@ public final class NetworkCapabilities implements Parcelable {
        mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
        mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
        mNetworkSpecifier = nc.mNetworkSpecifier;
        mTransportInfo = nc.mTransportInfo;
        if (nc.getTransportInfo() != null) {
            setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields));
        } else {
            setTransportInfo(null);
        }
        mSignalStrength = nc.mSignalStrength;
        setUids(nc.mUids); // Will make the defensive copy
        setAdministratorUids(nc.getAdministratorUids());
+38 −0
Original line number Diff line number Diff line
@@ -16,10 +16,48 @@

package android.net;

import android.annotation.NonNull;
import android.annotation.SystemApi;

/**
 * A container for transport-specific capabilities which is returned by
 * {@link NetworkCapabilities#getTransportInfo()}. Specific networks
 * may provide concrete implementations of this interface.
 * @see android.net.wifi.aware.WifiAwareNetworkInfo
 * @see android.net.wifi.WifiInfo
 */
public interface TransportInfo {

    /**
     * Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that
     * were set based on the permissions of the process that originally received it.
     *
     * <p>By default {@link TransportInfo} does not preserve such fields during parceling, as
     * they should not be shared outside of the process that receives them without appropriate
     * checks.
     *
     * @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept
     *                                      when parceling
     * @return Copy of this instance.
     * @hide
     */
    @SystemApi
    @NonNull
    default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) {
        return this;
    }

    /**
     * Returns whether this TransportInfo type has location sensitive fields or not (helps
     * to determine whether to perform a location permission check or not before sending to
     * apps).
     *
     * @return {@code true} if this instance contains location sensitive info, {@code false}
     * otherwise.
     * @hide
     */
    @SystemApi
    default boolean hasLocationSensitiveFields() {
        return false;
    }
}
+37 −21
Original line number Diff line number Diff line
@@ -1557,7 +1557,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        if (nc != null) {
            result.put(
                    nai.network,
                    maybeSanitizeLocationInfoForCaller(
                    createWithLocationInfoSanitizedIfNecessaryWhenParceled(
                            nc, mDeps.getCallingUid(), callingPackageName));
        }

@@ -1567,7 +1567,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
            for (Network network : networks) {
                nc = getNetworkCapabilitiesInternal(network);
                if (nc != null) {
                    result.put(network, maybeSanitizeLocationInfoForCaller(
                    result.put(
                            network,
                            createWithLocationInfoSanitizedIfNecessaryWhenParceled(
                                    nc, mDeps.getCallingUid(), callingPackageName));
                }
            }
@@ -1649,7 +1651,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
    public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
        mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName);
        enforceAccessPermission();
        return maybeSanitizeLocationInfoForCaller(
        return createWithLocationInfoSanitizedIfNecessaryWhenParceled(
                getNetworkCapabilitiesInternal(network),
                mDeps.getCallingUid(), callingPackageName);
    }
@@ -1670,37 +1672,51 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return newNc;
    }

    private boolean hasLocationPermission(int callerUid, @NonNull String callerPkgName) {
        final long token = Binder.clearCallingIdentity();
        try {
            return mLocationPermissionChecker.checkLocationPermission(
                    callerPkgName, null /* featureId */, callerUid, null /* message */);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @VisibleForTesting
    @Nullable
    NetworkCapabilities maybeSanitizeLocationInfoForCaller(
    NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled(
            @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) {
        if (nc == null) {
            return null;
        }
        final NetworkCapabilities newNc = new NetworkCapabilities(nc);
        if (callerUid != newNc.getOwnerUid()) {
        Boolean hasLocationPermission = null;
        final NetworkCapabilities newNc;
        // Avoid doing location permission check if the transport info has no location sensitive
        // data.
        if (nc.getTransportInfo() != null && nc.getTransportInfo().hasLocationSensitiveFields()) {
            hasLocationPermission = hasLocationPermission(callerUid, callerPkgName);
            newNc = new NetworkCapabilities(nc, hasLocationPermission);
        } else {
            newNc = new NetworkCapabilities(nc, false /* parcelLocationSensitiveFields */);
        }
        // Reset owner uid if not destined for the owner app.
        if (callerUid != nc.getOwnerUid()) {
            newNc.setOwnerUid(INVALID_UID);
            return newNc;
        }

        // Allow VPNs to see ownership of their own VPN networks - not location sensitive.
        if (nc.hasTransport(TRANSPORT_VPN)) {
            // Owner UIDs already checked above. No need to re-check.
            return newNc;
        }

        final long token = Binder.clearCallingIdentity();
        try {
            if (!mLocationPermissionChecker.checkLocationPermission(
                    callerPkgName, null /* featureId */, callerUid, null /* message */)) {
                // Caller does not have the requisite location permissions. Reset the
                // owner's UID in the NetworkCapabilities.
                newNc.setOwnerUid(INVALID_UID);
        if (hasLocationPermission == null) {
            // Location permission not checked yet, check now for masking owner UID.
            hasLocationPermission = hasLocationPermission(callerUid, callerPkgName);
        }
        } finally {
            Binder.restoreCallingIdentity(token);
        // Reset owner uid if the app has no location permission.
        if (!hasLocationPermission) {
            newNc.setOwnerUid(INVALID_UID);
        }

        return newNc;
    }

@@ -6839,7 +6855,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                                networkAgent.networkCapabilities, nri.mPid, nri.mUid);
                putParcelable(
                        bundle,
                        maybeSanitizeLocationInfoForCaller(
                        createWithLocationInfoSanitizedIfNecessaryWhenParceled(
                                nc, nri.mUid, nri.request.getRequestorPackageName()));
                putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
                        networkAgent.linkProperties, nri.mPid, nri.mUid));
@@ -6858,7 +6874,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                                networkAgent.networkCapabilities, nri.mPid, nri.mUid);
                putParcelable(
                        bundle,
                        maybeSanitizeLocationInfoForCaller(
                        createWithLocationInfoSanitizedIfNecessaryWhenParceled(
                                netCap, nri.mUid, nri.request.getRequestorPackageName()));
                break;
            }
Loading