Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3546a5ef authored by nharold's avatar nharold Committed by android-build-merger
Browse files

Merge "Add UserQuotaTracker to IpSecService"

am: a0c97b3d

Change-Id: I43a9617b077ecd5fc2b445a1ade8b76c00562640
parents abff77e4 a0c97b3d
Loading
Loading
Loading
Loading
+98 −1
Original line number Diff line number Diff line
@@ -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;