From 56b2395f396741bf667c085d69fc8689df15b0f8 Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Mon, 3 Apr 2017 17:44:10 -0700 Subject: [AWARE] Add UID checking to WifiAware network specifier Wifi Aware networks are tied to a specific session - which is tied to a specific UID. Change verifies that a network requestor is only using session contexts which are owned by the same UID. Bug: 36053921 Test: integration (sl4a) tests Change-Id: Ife235e3d3f509d3425614ef1392c20f2b127c88f --- .../wifi/aware/WifiAwareDataPathStateManager.java | 9 +- .../aware/WifiAwareDataPathStateManagerTest.java | 99 +++++++++++++++++++++- 2 files changed, 102 insertions(+), 6 deletions(-) diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java index 14d855e00..723828d7f 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java @@ -592,8 +592,6 @@ public class WifiAwareDataPathStateManager { return true; } - // TODO: validate that the client ID actually comes from the correct process and is - // not faked? nnri = AwareNetworkRequestInformation.processNetworkSpecifier(networkSpecifier, mMgr); if (nnri == null) { Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request @@ -903,6 +901,13 @@ public class WifiAwareDataPathStateManager { } } + // validate UID + if (ns.requestorUid != uid) { + Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() + + " -- UID mismatch to clientId's uid=" + uid); + return null; + } + // create container and populate AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation(); nnri.state = (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java index e7a383c5e..a2e7c77cf 100644 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java @@ -57,6 +57,7 @@ import android.os.Handler; import android.os.INetworkManagementService; import android.os.Message; import android.os.Messenger; +import android.os.Process; import android.os.test.TestLooper; import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; @@ -302,6 +303,23 @@ public class WifiAwareDataPathStateManagerTest { testDataPathInitiatorResponderMismatchUtility(true); } + /** + * Validate the fail flow of an Initiator (subscriber) with its UID unset + */ + @Test + public void testDataPathInitiatorUidUnsetError() throws Exception { + testDataPathInitiatorResponderInvalidUidUtility(false, false); + } + + /** + * Validate the fail flow of an Initiator (subscriber) with its UID set as a malicious + * attacker (i.e. mismatched to its requested client's UID). + */ + @Test + public void testDataPathInitiatorUidSetIncorrectlyError() throws Exception { + testDataPathInitiatorResponderInvalidUidUtility(false, true); + } + /* * Responder tests */ @@ -395,6 +413,23 @@ public class WifiAwareDataPathStateManagerTest { testDataPathInitiatorResponderMismatchUtility(false); } + /** + * Validate the fail flow of an Initiator (subscriber) with its UID unset + */ + @Test + public void testDataPathResponderUidUnsetError() throws Exception { + testDataPathInitiatorResponderInvalidUidUtility(true, false); + } + + /** + * Validate the fail flow of an Initiator (subscriber) with its UID set as a malicious + * attacker (i.e. mismatched to its requested client's UID). + */ + @Test + public void testDataPathResponderUidSetIncorrectlyError() throws Exception { + testDataPathInitiatorResponderInvalidUidUtility(true, true); + } + /* * Utilities */ @@ -428,10 +463,66 @@ public class WifiAwareDataPathStateManagerTest { ns.peerId, ns.peerMac, ns.pmk, - ns.passphrase - ); + ns.passphrase, + ns.requestorUid); + nr.networkCapabilities.setNetworkSpecifier(ns); + + Message reqNetworkMsg = Message.obtain(); + reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK; + reqNetworkMsg.obj = nr; + reqNetworkMsg.arg1 = 0; + res.second.send(reqNetworkMsg); + mMockLooper.dispatchAll(); + + // consequences of failure: + // Responder (publisher): responds with a rejection to any data-path requests + // Initiator (subscribe): doesn't initiate (i.e. no HAL requests) + if (doPublish) { + // (2) get request & respond + mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false), + eq(ndpId), eq(""), eq(null), eq(null), any()); + } + + verifyNoMoreInteractions(mMockNative, mMockCm); + } + + private void testDataPathInitiatorResponderInvalidUidUtility(boolean doPublish, + boolean isUidSet) throws Exception { + final int clientId = 123; + final int pubSubId = 11234; + final int ndpId = 2; + final byte[] pmk = "some bytes".getBytes(); + final PeerHandle peerHandle = new PeerHandle(1341234); + final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); + + InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); + + // (0) initialize + Pair res = initDataPathEndPoint(clientId, pubSubId, peerHandle, + peerDiscoveryMac, inOrder, doPublish); + + // (1) create network request + NetworkRequest nr = getSessionNetworkRequest(clientId, res.first, peerHandle, pmk, + doPublish); + + // (2) corrupt request's UID + WifiAwareNetworkSpecifier ns = + (WifiAwareNetworkSpecifier) nr.networkCapabilities.getNetworkSpecifier(); + ns = new WifiAwareNetworkSpecifier( + ns.type, + ns.role, + ns.clientId, + ns.sessionId, + ns.peerId, + ns.peerMac, + ns.pmk, + ns.passphrase, + ns.requestorUid + 1); // corruption hack nr.networkCapabilities.setNetworkSpecifier(ns); + // (3) request network Message reqNetworkMsg = Message.obtain(); reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK; reqNetworkMsg.obj = nr; @@ -751,7 +842,6 @@ public class WifiAwareDataPathStateManagerTest { PeerHandle peerHandle, byte[] peerDiscoveryMac, InOrder inOrder, boolean doPublish) throws Exception { - final int uid = 1000; final int pid = 2000; final String callingPackage = "com.android.somePackage"; final String someMsg = "some arbitrary message from peer"; @@ -790,7 +880,8 @@ public class WifiAwareDataPathStateManagerTest { mMockLooper.dispatchAll(); // (3) create client & session & rx message - mDut.connect(clientId, uid, pid, callingPackage, mMockCallback, configRequest, false); + mDut.connect(clientId, Process.myUid(), pid, callingPackage, mMockCallback, configRequest, + false); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), eq(false), eq(true)); -- cgit v1.2.3