From d9d119864ade0c7b2c6adfaf37f4a95dd9f7f051 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Wed, 29 Jan 2025 10:06:52 -0500 Subject: [PATCH 01/10] Fix FileAccessTree for prefixes that aren't parents --- .../entitlement/runtime/policy/FileAccessTree.java | 2 +- .../entitlement/runtime/policy/FileAccessTreeTests.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index d574609d13218..605cd83ddaba6 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -64,7 +64,7 @@ private static boolean checkPath(String path, String[] paths) { int ndx = Arrays.binarySearch(paths, path); if (ndx < -1) { String maybeParent = paths[-ndx - 2]; - return path.startsWith(maybeParent); + return path.startsWith(maybeParent) && path.charAt(maybeParent.length()) == '/'; } return ndx >= 0; } diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java index c133cf0f1242e..9c4decc154258 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java @@ -41,7 +41,9 @@ public void testRead() { var tree = FileAccessTree.of(List.of(entitlement("foo", "read"))); assertThat(tree.canRead(path("foo")), is(true)); assertThat(tree.canRead(path("foo/subdir")), is(true)); + assertThat(tree.canRead(path("food")), is(false)); assertThat(tree.canWrite(path("foo")), is(false)); + assertThat(tree.canWrite(path("food")), is(false)); assertThat(tree.canRead(path("before")), is(false)); assertThat(tree.canRead(path("later")), is(false)); @@ -51,7 +53,9 @@ public void testWrite() { var tree = FileAccessTree.of(List.of(entitlement("foo", "read_write"))); assertThat(tree.canWrite(path("foo")), is(true)); assertThat(tree.canWrite(path("foo/subdir")), is(true)); + assertThat(tree.canWrite(path("food")), is(false)); assertThat(tree.canRead(path("foo")), is(true)); + assertThat(tree.canRead(path("food")), is(false)); assertThat(tree.canWrite(path("before")), is(false)); assertThat(tree.canWrite(path("later")), is(false)); From 156c1ed3e133a1a0a216298b61b47557a73c95e7 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Mon, 3 Feb 2025 17:35:59 -0500 Subject: [PATCH 02/10] Support backslashes --- .../runtime/policy/FileAccessTree.java | 15 ++++++++++----- .../runtime/policy/FileAccessTreeTests.java | 11 +++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 605cd83ddaba6..18365e1f6fb5f 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -11,6 +11,7 @@ import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement; +import java.io.File; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -27,11 +28,11 @@ private FileAccessTree(List fileEntitlements) { List readPaths = new ArrayList<>(); List writePaths = new ArrayList<>(); for (FileEntitlement fileEntitlement : fileEntitlements) { - var mode = fileEntitlement.mode(); - if (mode == FileEntitlement.Mode.READ_WRITE) { - writePaths.add(fileEntitlement.path()); + String path = normalizedPath(fileEntitlement); + if (fileEntitlement.mode() == FileEntitlement.Mode.READ_WRITE) { + writePaths.add(path); } - readPaths.add(fileEntitlement.path()); + readPaths.add(path); } readPaths.sort(String::compareTo); @@ -53,8 +54,12 @@ boolean canWrite(Path path) { return checkPath(normalize(path), writePaths); } + private static String normalizedPath(FileEntitlement fileEntitlement) { + return normalize(new File(fileEntitlement.path()).toPath()); + } + private static String normalize(Path path) { - return path.toAbsolutePath().normalize().toString(); + return path.toAbsolutePath().normalize().toString().replace('\\', '/'); } private static boolean checkPath(String path, String[] paths) { diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java index 9c4decc154258..b95f6848019af 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java @@ -87,6 +87,17 @@ public void testNormalizePath() { assertThat(tree.canRead(path("")), is(false)); } + public void testSlashesAreInterchangeable() { + var tree = FileAccessTree.of(List.of(entitlement("a/b", "read"), entitlement("m\\n", "read"))); + assertThat(tree.canRead(path("a/b")), is(true)); + assertThat(tree.canRead(path("a\\b")), is(true)); + assertThat(tree.canRead(path("m/n")), is(true)); + assertThat(tree.canRead(path("m\\n")), is(true)); + + // Backslash shouldn't be treated as an escape + assertThat(tree.canRead(path("m\n")), is(false)); + } + FileEntitlement entitlement(String path, String mode) { Path p = path(path); return new FileEntitlement(p.toString(), mode); From 860028823f87b7d42026672b31954b547a605c88 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Mon, 3 Feb 2025 20:31:11 -0500 Subject: [PATCH 03/10] Whoops, nio --- .../entitlement/runtime/policy/FileAccessTree.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 18365e1f6fb5f..55435935324fd 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -11,8 +11,8 @@ import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement; -import java.io.File; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -55,7 +55,7 @@ boolean canWrite(Path path) { } private static String normalizedPath(FileEntitlement fileEntitlement) { - return normalize(new File(fileEntitlement.path()).toPath()); + return normalize(Paths.get(fileEntitlement.path())); } private static String normalize(Path path) { From dd9de2c5b740a4937032bcbc4d1ac90d3e249459 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Tue, 4 Feb 2025 10:30:12 -0500 Subject: [PATCH 04/10] Move normalization responsibility to FileEntitlement --- .../runtime/policy/FileAccessTree.java | 17 +++++------------ .../policy/entitlements/FileEntitlement.java | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 55435935324fd..8ee9face5142d 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -12,12 +12,13 @@ import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import static org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement.normalizePath; + public final class FileAccessTree { public static final FileAccessTree EMPTY = new FileAccessTree(List.of()); @@ -28,7 +29,7 @@ private FileAccessTree(List fileEntitlements) { List readPaths = new ArrayList<>(); List writePaths = new ArrayList<>(); for (FileEntitlement fileEntitlement : fileEntitlements) { - String path = normalizedPath(fileEntitlement); + String path = fileEntitlement.path(); if (fileEntitlement.mode() == FileEntitlement.Mode.READ_WRITE) { writePaths.add(path); } @@ -47,19 +48,11 @@ public static FileAccessTree of(List fileEntitlements) { } boolean canRead(Path path) { - return checkPath(normalize(path), readPaths); + return checkPath(normalizePath(path), readPaths); } boolean canWrite(Path path) { - return checkPath(normalize(path), writePaths); - } - - private static String normalizedPath(FileEntitlement fileEntitlement) { - return normalize(Paths.get(fileEntitlement.path())); - } - - private static String normalize(Path path) { - return path.toAbsolutePath().normalize().toString().replace('\\', '/'); + return checkPath(normalizePath(path), writePaths); } private static boolean checkPath(String path, String[] paths) { diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java index f3a0ee1758a04..2944093e1c412 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java @@ -12,10 +12,15 @@ import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement; import org.elasticsearch.entitlement.runtime.policy.PolicyValidationException; +import java.nio.file.Path; import java.nio.file.Paths; /** - * Describes a file entitlement with a path and mode. + * Describes entitlement to access files at a particular location. + * + * @param path the location of the files. Will be automatically {@link #normalizePath normalized}. + * For directories, implicitly includes access to all contained files and (recursively) subdirectories. + * @param mode the type of operation */ public record FileEntitlement(String path, Mode mode) implements Entitlement { @@ -25,11 +30,14 @@ public enum Mode { } public FileEntitlement { - path = normalizePath(path); + path = normalizePath(Paths.get(path)); } - private static String normalizePath(String path) { - return Paths.get(path).toAbsolutePath().normalize().toString(); + /** + * @return the "canonical" form of of the given {@code path}, to be used for entitlement checks. + */ + public static String normalizePath(Path path) { + return path.toAbsolutePath().normalize().toString().replace('\\', '/'); } private static Mode parseMode(String mode) { From 377cdfd0ca76ead629c15735e052c3933d332b75 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Tue, 4 Feb 2025 16:15:12 -0500 Subject: [PATCH 05/10] Normalize to native separators --- .../runtime/policy/FileAccessTree.java | 3 ++- .../policy/entitlements/FileEntitlement.java | 7 +++++-- .../runtime/policy/FileAccessTreeTests.java | 15 ++++++++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 8ee9face5142d..9ab8dbfc4cf11 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -11,6 +11,7 @@ import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement; +import java.io.File; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -62,7 +63,7 @@ private static boolean checkPath(String path, String[] paths) { int ndx = Arrays.binarySearch(paths, path); if (ndx < -1) { String maybeParent = paths[-ndx - 2]; - return path.startsWith(maybeParent) && path.charAt(maybeParent.length()) == '/'; + return path.startsWith(maybeParent) && path.charAt(maybeParent.length()) == File.separatorChar; } return ndx >= 0; } diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java index 2944093e1c412..327941e893e6f 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java @@ -34,10 +34,13 @@ public enum Mode { } /** - * @return the "canonical" form of of the given {@code path}, to be used for entitlement checks. + * @return the "canonical" form of the given {@code path}, to be used for entitlement checks. */ public static String normalizePath(Path path) { - return path.toAbsolutePath().normalize().toString().replace('\\', '/'); + // Note that toAbsolutePath produces paths separated by File.separator, + // so on Windows, if the given path uses forward slashes, this consistently + // converts it to backslashes. + return path.toAbsolutePath().normalize().toString(); } private static Mode parseMode(String mode) { diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java index b95f6848019af..e067c4e8daee8 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java @@ -13,6 +13,7 @@ import org.elasticsearch.test.ESTestCase; import org.junit.BeforeClass; +import java.io.File; import java.nio.file.Path; import java.util.List; @@ -87,14 +88,18 @@ public void testNormalizePath() { assertThat(tree.canRead(path("")), is(false)); } - public void testSlashesAreInterchangeable() { - var tree = FileAccessTree.of(List.of(entitlement("a/b", "read"), entitlement("m\\n", "read"))); + public void testForwardSlashes() { + var tree = FileAccessTree.of(List.of(entitlement("a/b", "read"), entitlement("m" + File.separatorChar + "n", "read"))); + + // Native separators work + assertThat(tree.canRead(path("a" + File.separatorChar + "b")), is(true)); + assertThat(tree.canRead(path("m" + File.separatorChar + "n")), is(true)); + + // Forward slashes also work assertThat(tree.canRead(path("a/b")), is(true)); - assertThat(tree.canRead(path("a\\b")), is(true)); assertThat(tree.canRead(path("m/n")), is(true)); - assertThat(tree.canRead(path("m\\n")), is(true)); - // Backslash shouldn't be treated as an escape + // In case the native separator is a backslash, don't treat that as an escape assertThat(tree.canRead(path("m\n")), is(false)); } From 872b307db0b50a1538550867dfe5bb8e56eb9992 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Tue, 4 Feb 2025 16:34:16 -0500 Subject: [PATCH 06/10] Avoid forbidden API --- .../entitlement/runtime/policy/FileAccessTree.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 9ab8dbfc4cf11..63820868abe77 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -11,13 +11,13 @@ import org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement; -import java.io.File; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import static org.elasticsearch.core.PathUtils.getDefaultFileSystem; import static org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement.normalizePath; public final class FileAccessTree { @@ -63,7 +63,7 @@ private static boolean checkPath(String path, String[] paths) { int ndx = Arrays.binarySearch(paths, path); if (ndx < -1) { String maybeParent = paths[-ndx - 2]; - return path.startsWith(maybeParent) && path.charAt(maybeParent.length()) == File.separatorChar; + return path.startsWith(maybeParent + getDefaultFileSystem().getSeparator()); } return ndx >= 0; } From bfe61019b6ec7c9838caa92066741fb61b456943 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Tue, 4 Feb 2025 16:44:46 -0500 Subject: [PATCH 07/10] Avoid forbidden APIs in tests too --- .../entitlement/runtime/policy/FileAccessTreeTests.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java index e067c4e8daee8..095905ff786aa 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java @@ -13,10 +13,10 @@ import org.elasticsearch.test.ESTestCase; import org.junit.BeforeClass; -import java.io.File; import java.nio.file.Path; import java.util.List; +import static org.elasticsearch.core.PathUtils.getDefaultFileSystem; import static org.hamcrest.Matchers.is; public class FileAccessTreeTests extends ESTestCase { @@ -89,11 +89,12 @@ public void testNormalizePath() { } public void testForwardSlashes() { - var tree = FileAccessTree.of(List.of(entitlement("a/b", "read"), entitlement("m" + File.separatorChar + "n", "read"))); + String sep = getDefaultFileSystem().getSeparator(); + var tree = FileAccessTree.of(List.of(entitlement("a/b", "read"), entitlement("m" + sep + "n", "read"))); // Native separators work - assertThat(tree.canRead(path("a" + File.separatorChar + "b")), is(true)); - assertThat(tree.canRead(path("m" + File.separatorChar + "n")), is(true)); + assertThat(tree.canRead(path("a" + sep + "b")), is(true)); + assertThat(tree.canRead(path("m" + sep + "n")), is(true)); // Forward slashes also work assertThat(tree.canRead(path("a/b")), is(true)); From 17ae6e9b842db213b976ed3f60dce0c164579f61 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Wed, 5 Feb 2025 10:50:06 -0500 Subject: [PATCH 08/10] Do path normalization only in FileAccessTree --- .../runtime/policy/FileAccessTree.java | 13 ++++++++++-- .../policy/entitlements/FileEntitlement.java | 21 ++----------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 63820868abe77..3fbfbe2581668 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -18,7 +18,6 @@ import java.util.Objects; import static org.elasticsearch.core.PathUtils.getDefaultFileSystem; -import static org.elasticsearch.entitlement.runtime.policy.entitlements.FileEntitlement.normalizePath; public final class FileAccessTree { public static final FileAccessTree EMPTY = new FileAccessTree(List.of()); @@ -30,7 +29,7 @@ private FileAccessTree(List fileEntitlements) { List readPaths = new ArrayList<>(); List writePaths = new ArrayList<>(); for (FileEntitlement fileEntitlement : fileEntitlements) { - String path = fileEntitlement.path(); + String path = normalizePath(Path.of(fileEntitlement.path())); if (fileEntitlement.mode() == FileEntitlement.Mode.READ_WRITE) { writePaths.add(path); } @@ -56,6 +55,16 @@ boolean canWrite(Path path) { return checkPath(normalizePath(path), writePaths); } + /** + * @return the "canonical" form of the given {@code path}, to be used for entitlement checks. + */ + static String normalizePath(Path path) { + // Note that toAbsolutePath produces paths separated by the default file separator, + // so on Windows, if the given path uses forward slashes, this consistently + // converts it to backslashes. + return path.toAbsolutePath().normalize().toString(); + } + private static boolean checkPath(String path, String[] paths) { if (paths.length == 0) { return false; diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java index 327941e893e6f..1573b36b65d2a 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FileEntitlement.java @@ -12,14 +12,11 @@ import org.elasticsearch.entitlement.runtime.policy.ExternalEntitlement; import org.elasticsearch.entitlement.runtime.policy.PolicyValidationException; -import java.nio.file.Path; -import java.nio.file.Paths; - /** * Describes entitlement to access files at a particular location. * - * @param path the location of the files. Will be automatically {@link #normalizePath normalized}. - * For directories, implicitly includes access to all contained files and (recursively) subdirectories. + * @param path the location of the files. For directories, implicitly includes access to + * all contained files and (recursively) subdirectories. * @param mode the type of operation */ public record FileEntitlement(String path, Mode mode) implements Entitlement { @@ -29,20 +26,6 @@ public enum Mode { READ_WRITE } - public FileEntitlement { - path = normalizePath(Paths.get(path)); - } - - /** - * @return the "canonical" form of the given {@code path}, to be used for entitlement checks. - */ - public static String normalizePath(Path path) { - // Note that toAbsolutePath produces paths separated by File.separator, - // so on Windows, if the given path uses forward slashes, this consistently - // converts it to backslashes. - return path.toAbsolutePath().normalize().toString(); - } - private static Mode parseMode(String mode) { if (mode.equals("read")) { return Mode.READ; From 969a78c84b9fcb2a02fb4841af260690ec883c30 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Wed, 5 Feb 2025 10:53:54 -0500 Subject: [PATCH 09/10] Check file separator char to avoid String allocation --- .../entitlement/runtime/policy/FileAccessTree.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 3fbfbe2581668..9fbdea9992db0 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -21,6 +21,16 @@ public final class FileAccessTree { public static final FileAccessTree EMPTY = new FileAccessTree(List.of()); + private static final char FILE_SEPARATOR; + + static { + String separator = getDefaultFileSystem().getSeparator(); + if (separator.length() == 1) { + FILE_SEPARATOR = separator.charAt(0); + } else { + throw new IllegalStateException("Multi-character file separator not supported: [" + separator + "]"); + } + } private final String[] readPaths; private final String[] writePaths; @@ -72,7 +82,7 @@ private static boolean checkPath(String path, String[] paths) { int ndx = Arrays.binarySearch(paths, path); if (ndx < -1) { String maybeParent = paths[-ndx - 2]; - return path.startsWith(maybeParent + getDefaultFileSystem().getSeparator()); + return path.startsWith(maybeParent) && path.charAt(maybeParent.length()) == FILE_SEPARATOR; } return ndx >= 0; } From baa13f25b61e043cce79ecd0fa398effe00090c8 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Wed, 5 Feb 2025 11:31:22 -0500 Subject: [PATCH 10/10] Use startsWith overload --- .../entitlement/runtime/policy/FileAccessTree.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 9fbdea9992db0..3333eefa4f716 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -21,16 +21,7 @@ public final class FileAccessTree { public static final FileAccessTree EMPTY = new FileAccessTree(List.of()); - private static final char FILE_SEPARATOR; - - static { - String separator = getDefaultFileSystem().getSeparator(); - if (separator.length() == 1) { - FILE_SEPARATOR = separator.charAt(0); - } else { - throw new IllegalStateException("Multi-character file separator not supported: [" + separator + "]"); - } - } + private static final String FILE_SEPARATOR = getDefaultFileSystem().getSeparator(); private final String[] readPaths; private final String[] writePaths; @@ -82,7 +73,7 @@ private static boolean checkPath(String path, String[] paths) { int ndx = Arrays.binarySearch(paths, path); if (ndx < -1) { String maybeParent = paths[-ndx - 2]; - return path.startsWith(maybeParent) && path.charAt(maybeParent.length()) == FILE_SEPARATOR; + return path.startsWith(maybeParent) && path.startsWith(FILE_SEPARATOR, maybeParent.length()); } return ndx >= 0; }