diff options
author | Thomas Watson | 2021-02-26 14:46:31 +0000 |
---|---|---|
committer | Thomas Watson | 2021-02-26 14:47:16 +0000 |
commit | d60755236727ba69734922858db966f316bf5936 (patch) | |
tree | 6ee9998463c82b9a4e05b289aebad1b6364652d3 | |
parent | 3429a5e7aaafbad00a933ffcd91d77345d0446bd (diff) | |
download | rt.equinox.framework-d60755236727ba69734922858db966f316bf5936.tar.gz rt.equinox.framework-d60755236727ba69734922858db966f316bf5936.tar.xz rt.equinox.framework-d60755236727ba69734922858db966f316bf5936.zip |
Bug 571531 - Cap evaluation cache at 10000Y20210316-1310Y20210316-0510Y20210315-1000Y20210314-1000Y20210313-1000Y20210312-2250Y20210312-1250Y20210312-1000Y20210311-1000Y20210310-1000Y20210309-1000Y20210307-1000Y20210306-1000Y20210305-1000Y20210304-1000Y20210303-1000Y20210301-1000Y20210228-1000Y20210227-1000S4_19_0_RC2R4_19I20210303-1800I20210303-0600I20210302-1800I20210302-0930I20210302-0720I20210302-0600I20210301-1800I20210301-0600I20210228-1800I20210228-0600I20210227-1800I20210227-0600I20210226-2140I20210226-1800
Because permission instances can be infinite the evaluationCache can
grow unbounded leading to a memory leak. This is a quick fix to cap the
cache at 10000. A better approach may be to use some weak reference
cache in the future, but for now we need to stop the uncontrolled leak.
A test is added that does 10 million different file permission checks.
On my system this grinds to a halt after about 8 million checks. With
the cap at 10000 the 10 million permission checks happen <15 seconds.
Change-Id: I6e18d4d6fcab274bb2f56c69a6e0893f8e474418
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
2 files changed, 26 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java index 3935b9eb1..5e61766cb 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java @@ -1160,6 +1160,29 @@ public class SecurityAdminUnitTests extends AbstractBundleTests { testPermission(acc, new FilePermission(relativeExecutable.getAbsolutePath(), "execute"), true); } + public void testPermissionCheckCache() { + // test single row with signer condition + ConditionalPermissionUpdate update = cpa.newConditionalPermissionUpdate(); + List rows = update.getConditionalPermissionInfos(); + rows.add(cpa.newConditionalPermissionInfo(null, new ConditionInfo[] { SIGNER_CONDITION1 }, READONLY_INFOS, + ConditionalPermissionInfo.ALLOW)); + assertTrue("failed to commit", update.commit()); //$NON-NLS-1$ + + AccessControlContext acc = cpa.getAccessControlContext(new String[] { "cn=t1,c=FR;cn=test1,c=US" }); //$NON-NLS-1$ + + for (int i = 0; i < 10000000; i++) { + try { + if (i % 1000 == 0) { + System.out.println("i=" + i); + } + acc.checkPermission(new FilePermission("test" + i, "read")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (AccessControlException e) { + fail("Unexpected AccessControlExcetpion", e); //$NON-NLS-1$ + } + } + + } + private void checkInfos(ConditionalPermissionInfo testInfo1, ConditionalPermissionInfo testInfo2) { assertTrue("Infos are not equal: " + testInfo1.getEncoded() + " " + testInfo2.getEncoded(), testInfo1.equals(testInfo2)); assertEquals("Info hash code is not equal", testInfo1.hashCode(), testInfo2.hashCode()); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTable.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTable.java index ff32046ac..7fc0837a2 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTable.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/permadmin/SecurityTable.java @@ -51,6 +51,9 @@ public class SecurityTable extends PermissionCollection { if (bundlePermissions == null) { return ABSTAIN; } + if (evaluationCache.size() > 10000) { + clearEvaluationCache(); + } EvaluationCacheKey evaluationCacheKey = new EvaluationCacheKey(bundlePermissions, permission); if (isEmpty()) { evaluationCache.put(evaluationCacheKey, ABSTAIN); |