Merge "Add UserQuotaTracker to IpSecService" am: a0c97b3ddb am: b1d39a7aff

am: 31e299220a

Change-Id: Icc10cf54879e8f5b103392418edc1947593a8b39
This commit is contained in:
nharold
2017-08-09 18:36:13 +00:00
committed by android-build-merger

View File

@@ -115,6 +115,67 @@ public class IpSecService extends IIpSecService.Stub {
private final IpSecServiceConfiguration mSrvConfig; private final IpSecServiceConfiguration mSrvConfig;
/* Very simple counting class that looks much like a counting semaphore */
public static class ResourceTracker {
private final int mMax;
int mCurrent;
ResourceTracker(int max) {
mMax = max;
mCurrent = 0;
}
synchronized boolean isAvailable() {
return (mCurrent < mMax);
}
synchronized void take() {
if (!isAvailable()) {
Log.wtf(TAG, "Too many resources allocated!");
}
mCurrent++;
}
synchronized void give() {
if (mCurrent <= 0) {
Log.wtf(TAG, "We've released this resource too many times");
}
mCurrent--;
}
}
private static final class UserQuotaTracker {
/* Maximum number of UDP Encap Sockets that a single UID may possess */
public static final int MAX_NUM_ENCAP_SOCKETS = 2;
/* Maximum number of IPsec Transforms that a single UID may possess */
public static final int MAX_NUM_TRANSFORMS = 4;
/* Maximum number of IPsec Transforms that a single UID may possess */
public static final int MAX_NUM_SPIS = 8;
/* Record for one users's IpSecService-managed objects */
public static class UserRecord {
public final ResourceTracker socket = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS);
public final ResourceTracker transform = new ResourceTracker(MAX_NUM_TRANSFORMS);
public final ResourceTracker spi = new ResourceTracker(MAX_NUM_SPIS);
}
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
/* a never-fail getter so that we can populate the list of UIDs as-needed */
public synchronized UserRecord getUserRecord(int uid) {
UserRecord r = mUserRecords.get(uid);
if (r == null) {
r = new UserRecord();
mUserRecords.put(uid, r);
}
return r;
}
}
private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker();
/** /**
* The ManagedResource class provides a facility to cleanly and reliably release system * The ManagedResource 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 ManagedResource to automatically
@@ -132,11 +193,15 @@ public class IpSecService extends IIpSecService.Stub {
ManagedResource(int resourceId, IBinder binder) { ManagedResource(int resourceId, IBinder binder) {
super(); super();
if (resourceId == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
}
mBinder = binder; mBinder = binder;
mResourceId = resourceId; mResourceId = resourceId;
pid = Binder.getCallingPid(); pid = Binder.getCallingPid();
uid = Binder.getCallingUid(); uid = Binder.getCallingUid();
getResourceTracker().take();
try { try {
mBinder.linkToDeath(this, 0); mBinder.linkToDeath(this, 0);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -184,6 +249,7 @@ public class IpSecService extends IIpSecService.Stub {
} }
releaseResources(); releaseResources();
getResourceTracker().give();
if (mBinder != null) { if (mBinder != null) {
mBinder.unlinkToDeath(this, 0); mBinder.unlinkToDeath(this, 0);
} }
@@ -215,6 +281,9 @@ public class IpSecService extends IIpSecService.Stub {
*/ */
protected abstract void releaseResources() throws RemoteException; protected abstract void releaseResources() throws RemoteException;
/** Get the resource tracker for this resource */
protected abstract ResourceTracker getResourceTracker();
@Override @Override
public String toString() { public String toString() {
return new StringBuilder() return new StringBuilder()
@@ -330,6 +399,10 @@ public class IpSecService extends IIpSecService.Stub {
} }
} }
protected ResourceTracker getResourceTracker() {
return mUserQuotaTracker.getUserRecord(this.uid).transform;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder strBuilder = new StringBuilder(); StringBuilder strBuilder = new StringBuilder();
@@ -398,6 +471,11 @@ public class IpSecService extends IIpSecService.Stub {
mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
} }
@Override
protected ResourceTracker getResourceTracker() {
return mUserQuotaTracker.getUserRecord(this.uid).spi;
}
public int getSpi() { public int getSpi() {
return mSpi; return mSpi;
} }
@@ -450,6 +528,11 @@ public class IpSecService extends IIpSecService.Stub {
mSocket = null; mSocket = null;
} }
@Override
protected ResourceTracker getResourceTracker() {
return mUserQuotaTracker.getUserRecord(this.uid).socket;
}
public int getPort() { public int getPort() {
return mPort; return mPort;
} }
@@ -535,7 +618,14 @@ public class IpSecService extends IIpSecService.Stub {
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
String localAddress = ""; String localAddress = "";
try { try {
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).spi.isAvailable()) {
return new IpSecSpiResponse(
IpSecManager.Status.RESOURCE_UNAVAILABLE,
INVALID_RESOURCE_ID,
spi);
}
spi = spi =
mSrvConfig mSrvConfig
.getNetdInstance() .getNetdInstance()
@@ -552,7 +642,7 @@ public class IpSecService extends IIpSecService.Stub {
} catch (ServiceSpecificException e) { } catch (ServiceSpecificException e) {
// TODO: Add appropriate checks when other ServiceSpecificException types are supported // TODO: Add appropriate checks when other ServiceSpecificException types are supported
return new IpSecSpiResponse( return new IpSecSpiResponse(
IpSecManager.Status.SPI_UNAVAILABLE, IpSecManager.INVALID_RESOURCE_ID, spi); IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -635,6 +725,10 @@ public class IpSecService extends IIpSecService.Stub {
int resourceId = mNextResourceId.getAndIncrement(); int resourceId = mNextResourceId.getAndIncrement();
FileDescriptor sockFd = null; FileDescriptor sockFd = null;
try { try {
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).socket.isAvailable()) {
return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (port != 0) { if (port != 0) {
@@ -679,6 +773,9 @@ public class IpSecService extends IIpSecService.Stub {
public synchronized IpSecTransformResponse createTransportModeTransform( public synchronized IpSecTransformResponse createTransportModeTransform(
IpSecConfig c, IBinder binder) throws RemoteException { IpSecConfig c, IBinder binder) throws RemoteException {
int resourceId = mNextResourceId.getAndIncrement(); int resourceId = mNextResourceId.getAndIncrement();
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).transform.isAvailable()) {
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
SpiRecord[] spis = new SpiRecord[DIRECTIONS.length]; SpiRecord[] spis = new SpiRecord[DIRECTIONS.length];
// TODO: Basic input validation here since it's coming over the Binder // TODO: Basic input validation here since it's coming over the Binder
int encapType, encapLocalPort = 0, encapRemotePort = 0; int encapType, encapLocalPort = 0, encapRemotePort = 0;