diff options
5 files changed, 99 insertions, 19 deletions
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java index 87a2b05a4430..9ce2a5bd1b54 100644 --- a/core/java/android/net/NetworkSpecifier.java +++ b/core/java/android/net/NetworkSpecifier.java @@ -33,4 +33,20 @@ public abstract class NetworkSpecifier { * @hide */ public abstract boolean satisfiedBy(NetworkSpecifier other); + + /** + * Optional method which can be overriden by concrete implementations of NetworkSpecifier to + * check a self-reported UID. A concrete implementation may contain a UID which would be self- + * reported by the caller (since NetworkSpecifier implementations should be non-mutable). This + * function is called by ConnectivityService and is passed the actual UID of the caller - + * allowing the verification of the self-reported UID. In cases of mismatch the implementation + * should throw a SecurityException. + * + * @param requestorUid The UID of the requestor as obtained from its binder. + * + * @hide + */ + public void assertValidFromUid(int requestorUid) { + // empty + } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index dca3b35f14f1..0748816a8957 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -42,7 +42,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.ConnectivityManager.PacketKeepalive; @@ -63,6 +62,7 @@ import android.net.NetworkInfo.DetailedState; import android.net.NetworkMisc; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; +import android.net.NetworkSpecifier; import android.net.NetworkState; import android.net.NetworkUtils; import android.net.Proxy; @@ -102,7 +102,6 @@ import android.text.TextUtils; import android.util.LocalLog; import android.util.LocalLog.ReadOnlyLocalLog; import android.util.Log; -import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -4007,6 +4006,18 @@ public class ConnectivityService extends IConnectivityManager.Stub 0, 0, thresholds); } + private void ensureValidNetworkSpecifier(NetworkCapabilities nc) { + if (nc == null) { + return; + } + NetworkSpecifier ns = nc.getNetworkSpecifier(); + if (ns == null) { + return; + } + MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns); + ns.assertValidFromUid(Binder.getCallingUid()); + } + @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType) { @@ -4032,9 +4043,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (timeoutMs < 0) { throw new IllegalArgumentException("Bad timeout specified"); } - - MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( - networkCapabilities.getNetworkSpecifier()); + ensureValidNetworkSpecifier(networkCapabilities); NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, nextNetworkRequestId(), type); @@ -4102,9 +4111,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceNetworkRequestPermissions(networkCapabilities); enforceMeteredApnPolicy(networkCapabilities); ensureRequestableCapabilities(networkCapabilities); - - MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( - networkCapabilities.getNetworkSpecifier()); + ensureValidNetworkSpecifier(networkCapabilities); NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.REQUEST); @@ -4166,9 +4173,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // can't request networks. nc.addCapability(NET_CAPABILITY_FOREGROUND); } - - MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( - networkCapabilities.getNetworkSpecifier()); + ensureValidNetworkSpecifier(networkCapabilities); NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); @@ -4186,9 +4191,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); } - - MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( - networkCapabilities.getNetworkSpecifier()); + ensureValidNetworkSpecifier(networkCapabilities); NetworkRequest networkRequest = new NetworkRequest( new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(), diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 6140a896b1a8..633a914778a5 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1997,6 +1997,40 @@ public class ConnectivityServiceTest extends AndroidTestCase { } @SmallTest + public void testNetworkSpecifierUidSpoofSecurityException() { + class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable { + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + return true; + } + + @Override + public void assertValidFromUid(int requestorUid) { + throw new SecurityException("failure"); + } + + @Override + public int describeContents() { return 0; } + @Override + public void writeToParcel(Parcel dest, int flags) {} + } + + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(false); + + UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier(); + NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier( + networkSpecifier).build(); + TestNetworkCallback networkCallback = new TestNetworkCallback(); + try { + mCm.requestNetwork(networkRequest, networkCallback); + fail("Network request with spoofed UID did not throw a SecurityException"); + } catch (SecurityException e) { + // expected + } + } + + @SmallTest public void testRegisterDefaultNetworkCallback() throws Exception { final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultNetworkCallback); diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index d3ed79245426..87f199292dd8 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -31,6 +31,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; @@ -453,7 +454,8 @@ public class WifiAwareManager { peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID null, // peerMac (not used in this method) pmk, - passphrase); + passphrase, + Process.myUid()); } /** @hide */ @@ -490,7 +492,8 @@ public class WifiAwareManager { 0, // 0 is an invalid peer ID peer, pmk, - passphrase); + passphrase, + Process.myUid()); } private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub { diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java index 59934806f398..e152f6ced571 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java @@ -19,6 +19,7 @@ package android.net.wifi.aware; import android.net.NetworkSpecifier; import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; import java.util.Arrays; import java.util.Objects; @@ -115,9 +116,18 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements */ public final String passphrase; + /** + * The UID of the process initializing this network specifier. Validated by receiver using + * checkUidIfNecessary() and is used by satisfiedBy() to determine whether matches the + * offered network. + * + * @hide + */ + public final int requestorUid; + /** @hide */ public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId, - byte[] peerMac, byte[] pmk, String passphrase) { + byte[] peerMac, byte[] pmk, String passphrase, int requestorUid) { this.type = type; this.role = role; this.clientId = clientId; @@ -126,6 +136,7 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements this.peerMac = peerMac; this.pmk = pmk; this.passphrase = passphrase; + this.requestorUid = requestorUid; } public static final Creator<WifiAwareNetworkSpecifier> CREATOR = @@ -140,7 +151,8 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements in.readInt(), // peerId in.createByteArray(), // peerMac in.createByteArray(), // pmk - in.readString()); // passphrase + in.readString(), // passphrase + in.readInt()); // requestorUid } @Override @@ -164,6 +176,7 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements dest.writeByteArray(peerMac); dest.writeByteArray(pmk); dest.writeString(passphrase); + dest.writeInt(requestorUid); } /** @hide */ @@ -186,6 +199,7 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements result = 31 * result + Arrays.hashCode(peerMac); result = 31 * result + Arrays.hashCode(pmk); result = 31 * result + Objects.hashCode(passphrase); + result = 31 * result + requestorUid; return result; } @@ -210,7 +224,8 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements && peerId == lhs.peerId && Arrays.equals(peerMac, lhs.peerMac) && Arrays.equals(pmk, lhs.pmk) - && Objects.equals(passphrase, lhs.passphrase); + && Objects.equals(passphrase, lhs.passphrase) + && requestorUid == lhs.requestorUid; } /** @hide */ @@ -228,7 +243,16 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements .append(", pmk=").append((pmk == null) ? "<null>" : "<non-null>") // masking PII .append(", passphrase=").append((passphrase == null) ? "<null>" : "<non-null>") + .append(", requestorUid=").append(requestorUid) .append("]"); return sb.toString(); } + + /** @hide */ + @Override + public void assertValidFromUid(int requestorUid) { + if (this.requestorUid != requestorUid) { + throw new SecurityException("mismatched UIDs"); + } + } } |