Merge "Add UserQuotaTracker to IpSecService"
am: a0c97b3ddb Change-Id: I43a9617b077ecd5fc2b445a1ade8b76c00562640
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user