Loading services/core/java/com/android/server/IpSecService.java +199 −20 Original line number Original line Diff line number Diff line Loading @@ -57,11 +57,23 @@ import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; import libcore.io.IoUtils; import libcore.io.IoUtils; /** @hide */ /** * A service to manage multiple clients that want to access the IpSec API. The service is * responsible for maintaining a list of clients and managing the resources (and related quotas) * that each of them own. * * <p>Synchronization in IpSecService is done on all entrypoints due to potential race conditions at * the kernel/xfrm level. Further, this allows the simplifying assumption to be made that only one * thread is ever running at a time. * * @hide */ public class IpSecService extends IIpSecService.Stub { public class IpSecService extends IIpSecService.Stub { private static final String TAG = "IpSecService"; private static final String TAG = "IpSecService"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); Loading Loading @@ -92,15 +104,15 @@ public class IpSecService extends IIpSecService.Stub { private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); @GuardedBy("this") @GuardedBy("this") private final ManagedResourceArray<SpiRecord> mSpiRecords = new ManagedResourceArray<>(); private final KernelResourceArray<SpiRecord> mSpiRecords = new KernelResourceArray<>(); @GuardedBy("this") @GuardedBy("this") private final ManagedResourceArray<TransformRecord> mTransformRecords = private final KernelResourceArray<TransformRecord> mTransformRecords = new ManagedResourceArray<>(); new KernelResourceArray<>(); @GuardedBy("this") @GuardedBy("this") private final ManagedResourceArray<UdpSocketRecord> mUdpSocketRecords = private final KernelResourceArray<UdpSocketRecord> mUdpSocketRecords = new ManagedResourceArray<>(); new KernelResourceArray<>(); interface IpSecServiceConfiguration { interface IpSecServiceConfiguration { INetd getNetdInstance() throws RemoteException; INetd getNetdInstance() throws RemoteException; Loading @@ -120,6 +132,173 @@ public class IpSecService extends IIpSecService.Stub { private final IpSecServiceConfiguration mSrvConfig; private final IpSecServiceConfiguration mSrvConfig; /** * Interface for user-reference and kernel-resource cleanup. * * <p>This interface must be implemented for a resource to be reference counted. */ @VisibleForTesting public interface IResource { /** * Invalidates a IResource object, ensuring it is invalid for the purposes of allocating new * objects dependent on it. * * <p>Implementations of this method are expected to remove references to the IResource * object from the IpSecService's tracking arrays. The removal from the arrays ensures that * the resource is considered invalid for user access or allocation or use in other * resources. * * <p>References to the IResource object may be held by other RefcountedResource objects, * and as such, the kernel resources and quota may not be cleaned up. */ void invalidate() throws RemoteException; /** * Releases underlying resources and related quotas. * * <p>Implementations of this method are expected to remove all system resources that are * tracked by the IResource object. Due to other RefcountedResource objects potentially * having references to the IResource object, releaseKernelResources may not always be * called from releaseIfUnreferencedRecursively(). */ void freeUnderlyingResources() throws RemoteException; } /** * RefcountedResource manages references and dependencies in an exclusively acyclic graph. * * <p>RefcountedResource implements both explicit and implicit resource management. Creating a * RefcountedResource object creates an explicit reference that must be freed by calling * userRelease(). Additionally, adding this object as a child of another RefcountedResource * object will add an implicit reference. * * <p>Resources are cleaned up when all references, both implicit and explicit, are released * (ie, when userRelease() is called and when all parents have called releaseReference() on this * object.) */ @VisibleForTesting public class RefcountedResource<T extends IResource> implements IBinder.DeathRecipient { private final T mResource; private final List<RefcountedResource> mChildren; int mRefCount = 1; // starts at 1 for user's reference. IBinder mBinder; RefcountedResource(T resource, IBinder binder, RefcountedResource... children) { synchronized (IpSecService.this) { this.mResource = resource; this.mChildren = new ArrayList<>(children.length); this.mBinder = binder; for (RefcountedResource child : children) { mChildren.add(child); child.mRefCount++; } try { mBinder.linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } } } /** * If the Binder object dies, this function is called to free the system resources that are * being managed by this record and to subsequently release this record for garbage * collection */ @Override public void binderDied() { synchronized (IpSecService.this) { try { userRelease(); } catch (Exception e) { Log.e(TAG, "Failed to release resource: " + e); } } } public T getResource() { return mResource; } /** * Unlinks from binder and performs IpSecService resource cleanup (removes from resource * arrays) * * <p>If this method has been previously called, the RefcountedResource's binder field will * be null, and the method will return without performing the cleanup a second time. * * <p>Note that calling this function does not imply that kernel resources will be freed at * this time, or that the related quota will be returned. Such actions will only be * performed upon the reference count reaching zero. */ @GuardedBy("IpSecService.this") public void userRelease() throws RemoteException { // Prevent users from putting reference counts into a bad state by calling // userRelease() multiple times. if (mBinder == null) { return; } mBinder.unlinkToDeath(this, 0); mBinder = null; mResource.invalidate(); releaseReference(); } /** * Removes a reference to this resource. If the resultant reference count is zero, the * underlying resources are freed, and references to all child resources are also dropped * recursively (resulting in them freeing their resources and children, etcetera) * * <p>This method also sets the reference count to an invalid value (-1) to signify that it * has been fully released. Any subsequent calls to this method will result in an * IllegalStateException being thrown due to resource already having been previously * released */ @VisibleForTesting @GuardedBy("IpSecService.this") public void releaseReference() throws RemoteException { mRefCount--; if (mRefCount > 0) { return; } else if (mRefCount < 0) { throw new IllegalStateException( "Invalid operation - resource has already been released."); } // Cleanup own resources mResource.freeUnderlyingResources(); // Cleanup child resources as needed for (RefcountedResource<? extends IResource> child : mChildren) { child.releaseReference(); } // Enforce that resource cleanup can only be called once // By decrementing the refcount (from 0 to -1), the next call will throw an // IllegalStateException - it has already been released fully. mRefCount--; } @Override public String toString() { return new StringBuilder() .append("{mResource=") .append(mResource) .append(", mRefCount=") .append(mRefCount) .append(", mChildren=") .append(mChildren) .append("}") .toString(); } } /* Very simple counting class that looks much like a counting semaphore */ /* Very simple counting class that looks much like a counting semaphore */ public static class ResourceTracker { public static class ResourceTracker { private final int mMax; private final int mMax; Loading Loading @@ -211,13 +390,13 @@ public class IpSecService extends IIpSecService.Stub { private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker(); private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker(); /** /** * The ManagedResource class provides a facility to cleanly and reliably release system * The KernelResource class provides a facility to cleanly and reliably release system * resources. It relies on two things: an IBinder that allows ManagedResource to automatically * resources. It relies on two things: an IBinder that allows KernelResource to automatically * clean up in the event that the Binder dies and a user-provided resourceId that should * clean up in the event that the Binder dies and a user-provided resourceId that should * uniquely identify the managed resource. To use this class, the user should implement the * uniquely identify the managed resource. To use this class, the user should implement the * releaseResources() method that is responsible for releasing system resources when invoked. * releaseResources() method that is responsible for releasing system resources when invoked. */ */ private abstract class ManagedResource implements IBinder.DeathRecipient { private abstract class KernelResource implements IBinder.DeathRecipient { final int pid; final int pid; final int uid; final int uid; private IBinder mBinder; private IBinder mBinder; Loading @@ -225,7 +404,7 @@ public class IpSecService extends IIpSecService.Stub { private AtomicInteger mReferenceCount = new AtomicInteger(0); private AtomicInteger mReferenceCount = new AtomicInteger(0); ManagedResource(int resourceId, IBinder binder) { KernelResource(int resourceId, IBinder binder) { super(); super(); if (resourceId == INVALID_RESOURCE_ID) { if (resourceId == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); Loading Loading @@ -341,7 +520,7 @@ public class IpSecService extends IIpSecService.Stub { /** /** * Minimal wrapper around SparseArray that performs ownership validation on element accesses. * Minimal wrapper around SparseArray that performs ownership validation on element accesses. */ */ private class ManagedResourceArray<T extends ManagedResource> { private class KernelResourceArray<T extends KernelResource> { SparseArray<T> mArray = new SparseArray<>(); SparseArray<T> mArray = new SparseArray<>(); T getAndCheckOwner(int key) { T getAndCheckOwner(int key) { Loading Loading @@ -369,7 +548,7 @@ public class IpSecService extends IIpSecService.Stub { } } } } private final class TransformRecord extends ManagedResource { private final class TransformRecord extends KernelResource { private final IpSecConfig mConfig; private final IpSecConfig mConfig; private final SpiRecord[] mSpis; private final SpiRecord[] mSpis; private final UdpSocketRecord mSocket; private final UdpSocketRecord mSocket; Loading Loading @@ -456,7 +635,7 @@ public class IpSecService extends IIpSecService.Stub { } } } } private final class SpiRecord extends ManagedResource { private final class SpiRecord extends KernelResource { private final int mDirection; private final int mDirection; private final String mLocalAddress; private final String mLocalAddress; private final String mRemoteAddress; private final String mRemoteAddress; Loading Loading @@ -544,7 +723,7 @@ public class IpSecService extends IIpSecService.Stub { } } } } private final class UdpSocketRecord extends ManagedResource { private final class UdpSocketRecord extends KernelResource { private FileDescriptor mSocket; private FileDescriptor mSocket; private final int mPort; private final int mPort; Loading Loading @@ -718,8 +897,8 @@ public class IpSecService extends IIpSecService.Stub { /* This method should only be called from Binder threads. Do not call this from /* This method should only be called from Binder threads. Do not call this from * within the system server as it will crash the system on failure. * within the system server as it will crash the system on failure. */ */ private synchronized <T extends ManagedResource> void releaseManagedResource( private synchronized <T extends KernelResource> void releaseKernelResource( ManagedResourceArray<T> resArray, int resourceId, String typeName) KernelResourceArray<T> resArray, int resourceId, String typeName) throws RemoteException { throws RemoteException { // We want to non-destructively get so that we can check credentials before removing // We want to non-destructively get so that we can check credentials before removing // this from the records. // this from the records. Loading @@ -737,7 +916,7 @@ public class IpSecService extends IIpSecService.Stub { /** Release a previously allocated SPI that has been registered with the system server */ /** Release a previously allocated SPI that has been registered with the system server */ @Override @Override public void releaseSecurityParameterIndex(int resourceId) throws RemoteException { public void releaseSecurityParameterIndex(int resourceId) throws RemoteException { releaseManagedResource(mSpiRecords, resourceId, "SecurityParameterIndex"); releaseKernelResource(mSpiRecords, resourceId, "SecurityParameterIndex"); } } /** /** Loading Loading @@ -827,7 +1006,7 @@ public class IpSecService extends IIpSecService.Stub { @Override @Override public void closeUdpEncapsulationSocket(int resourceId) throws RemoteException { public void closeUdpEncapsulationSocket(int resourceId) throws RemoteException { releaseManagedResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); releaseKernelResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); } } /** /** Loading Loading @@ -974,7 +1153,7 @@ public class IpSecService extends IIpSecService.Stub { */ */ @Override @Override public void deleteTransportModeTransform(int resourceId) throws RemoteException { public void deleteTransportModeTransform(int resourceId) throws RemoteException { releaseManagedResource(mTransformRecords, resourceId, "IpSecTransform"); releaseKernelResource(mTransformRecords, resourceId, "IpSecTransform"); } } /** /** Loading @@ -984,7 +1163,7 @@ public class IpSecService extends IIpSecService.Stub { @Override @Override public synchronized void applyTransportModeTransform( public synchronized void applyTransportModeTransform( ParcelFileDescriptor socket, int resourceId) throws RemoteException { ParcelFileDescriptor socket, int resourceId) throws RemoteException { // Synchronize liberally here because we are using ManagedResources in this block // Synchronize liberally here because we are using KernelResources in this block TransformRecord info; TransformRecord info; // FIXME: this code should be factored out into a security check + getter // FIXME: this code should be factored out into a security check + getter info = mTransformRecords.getAndCheckOwner(resourceId); info = mTransformRecords.getAndCheckOwner(resourceId); Loading tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java 0 → 100644 +356 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/IpSecService.java +199 −20 Original line number Original line Diff line number Diff line Loading @@ -57,11 +57,23 @@ import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; import libcore.io.IoUtils; import libcore.io.IoUtils; /** @hide */ /** * A service to manage multiple clients that want to access the IpSec API. The service is * responsible for maintaining a list of clients and managing the resources (and related quotas) * that each of them own. * * <p>Synchronization in IpSecService is done on all entrypoints due to potential race conditions at * the kernel/xfrm level. Further, this allows the simplifying assumption to be made that only one * thread is ever running at a time. * * @hide */ public class IpSecService extends IIpSecService.Stub { public class IpSecService extends IIpSecService.Stub { private static final String TAG = "IpSecService"; private static final String TAG = "IpSecService"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); Loading Loading @@ -92,15 +104,15 @@ public class IpSecService extends IIpSecService.Stub { private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); @GuardedBy("this") @GuardedBy("this") private final ManagedResourceArray<SpiRecord> mSpiRecords = new ManagedResourceArray<>(); private final KernelResourceArray<SpiRecord> mSpiRecords = new KernelResourceArray<>(); @GuardedBy("this") @GuardedBy("this") private final ManagedResourceArray<TransformRecord> mTransformRecords = private final KernelResourceArray<TransformRecord> mTransformRecords = new ManagedResourceArray<>(); new KernelResourceArray<>(); @GuardedBy("this") @GuardedBy("this") private final ManagedResourceArray<UdpSocketRecord> mUdpSocketRecords = private final KernelResourceArray<UdpSocketRecord> mUdpSocketRecords = new ManagedResourceArray<>(); new KernelResourceArray<>(); interface IpSecServiceConfiguration { interface IpSecServiceConfiguration { INetd getNetdInstance() throws RemoteException; INetd getNetdInstance() throws RemoteException; Loading @@ -120,6 +132,173 @@ public class IpSecService extends IIpSecService.Stub { private final IpSecServiceConfiguration mSrvConfig; private final IpSecServiceConfiguration mSrvConfig; /** * Interface for user-reference and kernel-resource cleanup. * * <p>This interface must be implemented for a resource to be reference counted. */ @VisibleForTesting public interface IResource { /** * Invalidates a IResource object, ensuring it is invalid for the purposes of allocating new * objects dependent on it. * * <p>Implementations of this method are expected to remove references to the IResource * object from the IpSecService's tracking arrays. The removal from the arrays ensures that * the resource is considered invalid for user access or allocation or use in other * resources. * * <p>References to the IResource object may be held by other RefcountedResource objects, * and as such, the kernel resources and quota may not be cleaned up. */ void invalidate() throws RemoteException; /** * Releases underlying resources and related quotas. * * <p>Implementations of this method are expected to remove all system resources that are * tracked by the IResource object. Due to other RefcountedResource objects potentially * having references to the IResource object, releaseKernelResources may not always be * called from releaseIfUnreferencedRecursively(). */ void freeUnderlyingResources() throws RemoteException; } /** * RefcountedResource manages references and dependencies in an exclusively acyclic graph. * * <p>RefcountedResource implements both explicit and implicit resource management. Creating a * RefcountedResource object creates an explicit reference that must be freed by calling * userRelease(). Additionally, adding this object as a child of another RefcountedResource * object will add an implicit reference. * * <p>Resources are cleaned up when all references, both implicit and explicit, are released * (ie, when userRelease() is called and when all parents have called releaseReference() on this * object.) */ @VisibleForTesting public class RefcountedResource<T extends IResource> implements IBinder.DeathRecipient { private final T mResource; private final List<RefcountedResource> mChildren; int mRefCount = 1; // starts at 1 for user's reference. IBinder mBinder; RefcountedResource(T resource, IBinder binder, RefcountedResource... children) { synchronized (IpSecService.this) { this.mResource = resource; this.mChildren = new ArrayList<>(children.length); this.mBinder = binder; for (RefcountedResource child : children) { mChildren.add(child); child.mRefCount++; } try { mBinder.linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } } } /** * If the Binder object dies, this function is called to free the system resources that are * being managed by this record and to subsequently release this record for garbage * collection */ @Override public void binderDied() { synchronized (IpSecService.this) { try { userRelease(); } catch (Exception e) { Log.e(TAG, "Failed to release resource: " + e); } } } public T getResource() { return mResource; } /** * Unlinks from binder and performs IpSecService resource cleanup (removes from resource * arrays) * * <p>If this method has been previously called, the RefcountedResource's binder field will * be null, and the method will return without performing the cleanup a second time. * * <p>Note that calling this function does not imply that kernel resources will be freed at * this time, or that the related quota will be returned. Such actions will only be * performed upon the reference count reaching zero. */ @GuardedBy("IpSecService.this") public void userRelease() throws RemoteException { // Prevent users from putting reference counts into a bad state by calling // userRelease() multiple times. if (mBinder == null) { return; } mBinder.unlinkToDeath(this, 0); mBinder = null; mResource.invalidate(); releaseReference(); } /** * Removes a reference to this resource. If the resultant reference count is zero, the * underlying resources are freed, and references to all child resources are also dropped * recursively (resulting in them freeing their resources and children, etcetera) * * <p>This method also sets the reference count to an invalid value (-1) to signify that it * has been fully released. Any subsequent calls to this method will result in an * IllegalStateException being thrown due to resource already having been previously * released */ @VisibleForTesting @GuardedBy("IpSecService.this") public void releaseReference() throws RemoteException { mRefCount--; if (mRefCount > 0) { return; } else if (mRefCount < 0) { throw new IllegalStateException( "Invalid operation - resource has already been released."); } // Cleanup own resources mResource.freeUnderlyingResources(); // Cleanup child resources as needed for (RefcountedResource<? extends IResource> child : mChildren) { child.releaseReference(); } // Enforce that resource cleanup can only be called once // By decrementing the refcount (from 0 to -1), the next call will throw an // IllegalStateException - it has already been released fully. mRefCount--; } @Override public String toString() { return new StringBuilder() .append("{mResource=") .append(mResource) .append(", mRefCount=") .append(mRefCount) .append(", mChildren=") .append(mChildren) .append("}") .toString(); } } /* Very simple counting class that looks much like a counting semaphore */ /* Very simple counting class that looks much like a counting semaphore */ public static class ResourceTracker { public static class ResourceTracker { private final int mMax; private final int mMax; Loading Loading @@ -211,13 +390,13 @@ public class IpSecService extends IIpSecService.Stub { private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker(); private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker(); /** /** * The ManagedResource class provides a facility to cleanly and reliably release system * The KernelResource class provides a facility to cleanly and reliably release system * resources. It relies on two things: an IBinder that allows ManagedResource to automatically * resources. It relies on two things: an IBinder that allows KernelResource to automatically * clean up in the event that the Binder dies and a user-provided resourceId that should * clean up in the event that the Binder dies and a user-provided resourceId that should * uniquely identify the managed resource. To use this class, the user should implement the * uniquely identify the managed resource. To use this class, the user should implement the * releaseResources() method that is responsible for releasing system resources when invoked. * releaseResources() method that is responsible for releasing system resources when invoked. */ */ private abstract class ManagedResource implements IBinder.DeathRecipient { private abstract class KernelResource implements IBinder.DeathRecipient { final int pid; final int pid; final int uid; final int uid; private IBinder mBinder; private IBinder mBinder; Loading @@ -225,7 +404,7 @@ public class IpSecService extends IIpSecService.Stub { private AtomicInteger mReferenceCount = new AtomicInteger(0); private AtomicInteger mReferenceCount = new AtomicInteger(0); ManagedResource(int resourceId, IBinder binder) { KernelResource(int resourceId, IBinder binder) { super(); super(); if (resourceId == INVALID_RESOURCE_ID) { if (resourceId == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); Loading Loading @@ -341,7 +520,7 @@ public class IpSecService extends IIpSecService.Stub { /** /** * Minimal wrapper around SparseArray that performs ownership validation on element accesses. * Minimal wrapper around SparseArray that performs ownership validation on element accesses. */ */ private class ManagedResourceArray<T extends ManagedResource> { private class KernelResourceArray<T extends KernelResource> { SparseArray<T> mArray = new SparseArray<>(); SparseArray<T> mArray = new SparseArray<>(); T getAndCheckOwner(int key) { T getAndCheckOwner(int key) { Loading Loading @@ -369,7 +548,7 @@ public class IpSecService extends IIpSecService.Stub { } } } } private final class TransformRecord extends ManagedResource { private final class TransformRecord extends KernelResource { private final IpSecConfig mConfig; private final IpSecConfig mConfig; private final SpiRecord[] mSpis; private final SpiRecord[] mSpis; private final UdpSocketRecord mSocket; private final UdpSocketRecord mSocket; Loading Loading @@ -456,7 +635,7 @@ public class IpSecService extends IIpSecService.Stub { } } } } private final class SpiRecord extends ManagedResource { private final class SpiRecord extends KernelResource { private final int mDirection; private final int mDirection; private final String mLocalAddress; private final String mLocalAddress; private final String mRemoteAddress; private final String mRemoteAddress; Loading Loading @@ -544,7 +723,7 @@ public class IpSecService extends IIpSecService.Stub { } } } } private final class UdpSocketRecord extends ManagedResource { private final class UdpSocketRecord extends KernelResource { private FileDescriptor mSocket; private FileDescriptor mSocket; private final int mPort; private final int mPort; Loading Loading @@ -718,8 +897,8 @@ public class IpSecService extends IIpSecService.Stub { /* This method should only be called from Binder threads. Do not call this from /* This method should only be called from Binder threads. Do not call this from * within the system server as it will crash the system on failure. * within the system server as it will crash the system on failure. */ */ private synchronized <T extends ManagedResource> void releaseManagedResource( private synchronized <T extends KernelResource> void releaseKernelResource( ManagedResourceArray<T> resArray, int resourceId, String typeName) KernelResourceArray<T> resArray, int resourceId, String typeName) throws RemoteException { throws RemoteException { // We want to non-destructively get so that we can check credentials before removing // We want to non-destructively get so that we can check credentials before removing // this from the records. // this from the records. Loading @@ -737,7 +916,7 @@ public class IpSecService extends IIpSecService.Stub { /** Release a previously allocated SPI that has been registered with the system server */ /** Release a previously allocated SPI that has been registered with the system server */ @Override @Override public void releaseSecurityParameterIndex(int resourceId) throws RemoteException { public void releaseSecurityParameterIndex(int resourceId) throws RemoteException { releaseManagedResource(mSpiRecords, resourceId, "SecurityParameterIndex"); releaseKernelResource(mSpiRecords, resourceId, "SecurityParameterIndex"); } } /** /** Loading Loading @@ -827,7 +1006,7 @@ public class IpSecService extends IIpSecService.Stub { @Override @Override public void closeUdpEncapsulationSocket(int resourceId) throws RemoteException { public void closeUdpEncapsulationSocket(int resourceId) throws RemoteException { releaseManagedResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); releaseKernelResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); } } /** /** Loading Loading @@ -974,7 +1153,7 @@ public class IpSecService extends IIpSecService.Stub { */ */ @Override @Override public void deleteTransportModeTransform(int resourceId) throws RemoteException { public void deleteTransportModeTransform(int resourceId) throws RemoteException { releaseManagedResource(mTransformRecords, resourceId, "IpSecTransform"); releaseKernelResource(mTransformRecords, resourceId, "IpSecTransform"); } } /** /** Loading @@ -984,7 +1163,7 @@ public class IpSecService extends IIpSecService.Stub { @Override @Override public synchronized void applyTransportModeTransform( public synchronized void applyTransportModeTransform( ParcelFileDescriptor socket, int resourceId) throws RemoteException { ParcelFileDescriptor socket, int resourceId) throws RemoteException { // Synchronize liberally here because we are using ManagedResources in this block // Synchronize liberally here because we are using KernelResources in this block TransformRecord info; TransformRecord info; // FIXME: this code should be factored out into a security check + getter // FIXME: this code should be factored out into a security check + getter info = mTransformRecords.getAndCheckOwner(resourceId); info = mTransformRecords.getAndCheckOwner(resourceId); Loading
tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java 0 → 100644 +356 −0 File added.Preview size limit exceeded, changes collapsed. Show changes