Merge "Add UserQuotaTracker to IpSecService"

am: a0c97b3ddb

Change-Id: I43a9617b077ecd5fc2b445a1ade8b76c00562640
This commit is contained in:
nharold
2017-08-09 17:49:42 +00:00
committed by android-build-merger

View File

@@ -115,6 +115,67 @@ public class IpSecService extends IIpSecService.Stub {
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
* 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) {
super();
if (resourceId == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
}
mBinder = binder;
mResourceId = resourceId;
pid = Binder.getCallingPid();
uid = Binder.getCallingUid();
getResourceTracker().take();
try {
mBinder.linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -184,6 +249,7 @@ public class IpSecService extends IIpSecService.Stub {
}
releaseResources();
getResourceTracker().give();
if (mBinder != null) {
mBinder.unlinkToDeath(this, 0);
}
@@ -215,6 +281,9 @@ public class IpSecService extends IIpSecService.Stub {
*/
protected abstract void releaseResources() throws RemoteException;
/** Get the resource tracker for this resource */
protected abstract ResourceTracker getResourceTracker();
@Override
public String toString() {
return new StringBuilder()
@@ -330,6 +399,10 @@ public class IpSecService extends IIpSecService.Stub {
}
}
protected ResourceTracker getResourceTracker() {
return mUserQuotaTracker.getUserRecord(this.uid).transform;
}
@Override
public String toString() {
StringBuilder strBuilder = new StringBuilder();
@@ -398,6 +471,11 @@ public class IpSecService extends IIpSecService.Stub {
mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
}
@Override
protected ResourceTracker getResourceTracker() {
return mUserQuotaTracker.getUserRecord(this.uid).spi;
}
public int getSpi() {
return mSpi;
}
@@ -450,6 +528,11 @@ public class IpSecService extends IIpSecService.Stub {
mSocket = null;
}
@Override
protected ResourceTracker getResourceTracker() {
return mUserQuotaTracker.getUserRecord(this.uid).socket;
}
public int getPort() {
return mPort;
}
@@ -535,7 +618,14 @@ public class IpSecService extends IIpSecService.Stub {
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
String localAddress = "";
try {
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).spi.isAvailable()) {
return new IpSecSpiResponse(
IpSecManager.Status.RESOURCE_UNAVAILABLE,
INVALID_RESOURCE_ID,
spi);
}
spi =
mSrvConfig
.getNetdInstance()
@@ -552,7 +642,7 @@ public class IpSecService extends IIpSecService.Stub {
} catch (ServiceSpecificException e) {
// TODO: Add appropriate checks when other ServiceSpecificException types are supported
return new IpSecSpiResponse(
IpSecManager.Status.SPI_UNAVAILABLE, IpSecManager.INVALID_RESOURCE_ID, spi);
IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -635,6 +725,10 @@ public class IpSecService extends IIpSecService.Stub {
int resourceId = mNextResourceId.getAndIncrement();
FileDescriptor sockFd = null;
try {
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).socket.isAvailable()) {
return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (port != 0) {
@@ -679,6 +773,9 @@ public class IpSecService extends IIpSecService.Stub {
public synchronized IpSecTransformResponse createTransportModeTransform(
IpSecConfig c, IBinder binder) throws RemoteException {
int resourceId = mNextResourceId.getAndIncrement();
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).transform.isAvailable()) {
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
SpiRecord[] spis = new SpiRecord[DIRECTIONS.length];
// TODO: Basic input validation here since it's coming over the Binder
int encapType, encapLocalPort = 0, encapRemotePort = 0;