From bdf70485711a1d749fe098ced978433ad3bd1f4d Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 25 Feb 2019 12:33:22 -0800 Subject: [PATCH] Add NATT keepalive resources and methods into IpSecService This change adds a new NATTKeepalive resource type, along with the associated allocation/deallocation. Additionally, this change allows ReferenceCountedResource(s) to not be binder-linked, to allow the ConnectivityService to verify ownership and allocate a NattKeepalive without double-registering for binder-death notifications. Bug: 125517194 Test: IpSecService frameworks tests ran Change-Id: I8293f79940ad57dabb6f2b9de5e334d06b869443 --- .../com/android/server/IpSecServiceTest.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 4a35015044..6b5a2203ce 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -118,6 +118,7 @@ public class IpSecServiceTest { INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; + int mUid = Os.getuid(); @Before public void setUp() throws Exception { @@ -665,4 +666,99 @@ public class IpSecServiceTest { mIpSecService.releaseNetId(releasedNetId); assertEquals(releasedNetId, mIpSecService.reserveNetId()); } + + @Test + public void testLockEncapSocketForNattKeepalive() throws Exception { + IpSecUdpEncapResponse udpEncapResp = + mIpSecService.openUdpEncapsulationSocket(0, new Binder()); + assertNotNull(udpEncapResp); + assertEquals(IpSecManager.Status.OK, udpEncapResp.status); + + // Verify no NATT keepalive records upon startup + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive(udpEncapResp.resourceId, mUid); + + // Validate response, and record was added + assertNotEquals(IpSecManager.INVALID_RESOURCE_ID, nattKeepaliveResourceId); + assertEquals(1, userRecord.mNattKeepaliveRecords.size()); + + // Validate keepalive can be released and removed. + mIpSecService.releaseNattKeepalive(nattKeepaliveResourceId, mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); + } + + @Test + public void testLockEncapSocketForNattKeepaliveInvalidUid() throws Exception { + IpSecUdpEncapResponse udpEncapResp = + mIpSecService.openUdpEncapsulationSocket(0, new Binder()); + assertNotNull(udpEncapResp); + assertEquals(IpSecManager.Status.OK, udpEncapResp.status); + + // Verify no NATT keepalive records upon startup + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + try { + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive( + udpEncapResp.resourceId, mUid + 1); + fail("Expected SecurityException for invalid user"); + } catch (SecurityException expected) { + } + + // Validate keepalive was not added to lists + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + } + + @Test + public void testLockEncapSocketForNattKeepaliveInvalidResourceId() throws Exception { + // Verify no NATT keepalive records upon startup + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + try { + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive(12345, mUid); + fail("Expected IllegalArgumentException for invalid resource ID"); + } catch (IllegalArgumentException expected) { + } + + // Validate keepalive was not added to lists + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + } + + @Test + public void testEncapSocketReleasedBeforeKeepaliveReleased() throws Exception { + IpSecUdpEncapResponse udpEncapResp = + mIpSecService.openUdpEncapsulationSocket(0, new Binder()); + assertNotNull(udpEncapResp); + assertEquals(IpSecManager.Status.OK, udpEncapResp.status); + + // Get encap socket record, verify initial starting refcount. + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + IpSecService.RefcountedResource encapSocketRefcountedRecord = + userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow( + udpEncapResp.resourceId); + assertEquals(1, encapSocketRefcountedRecord.mRefCount); + + // Verify that the reference was added + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive(udpEncapResp.resourceId, mUid); + assertNotEquals(IpSecManager.INVALID_RESOURCE_ID, nattKeepaliveResourceId); + assertEquals(2, encapSocketRefcountedRecord.mRefCount); + + // Close UDP encap socket, but expect the refcountedRecord to still have a reference. + mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); + assertEquals(1, encapSocketRefcountedRecord.mRefCount); + + // Verify UDP encap socket cleaned up once reference is removed. Expect -1 if cleanup + // was properly completed. + mIpSecService.releaseNattKeepalive(nattKeepaliveResourceId, mUid); + assertEquals(-1, encapSocketRefcountedRecord.mRefCount); + } }