Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.io.FileDescriptor;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
Expand Down Expand Up @@ -71,7 +70,6 @@
import java.nio.file.FileStore;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.OpenOption;
import java.nio.file.Path;
Expand Down Expand Up @@ -2760,14 +2758,7 @@ public void checkPathToRealPath(Class<?> callerClass, Path that, LinkOption... o
followLinks = false;
}
}
if (followLinks) {
try {
policyManager.checkFileRead(callerClass, Files.readSymbolicLink(that));
} catch (IOException | UnsupportedOperationException e) {
// that is not a link, or unrelated IOException or unsupported
}
}
policyManager.checkFileRead(callerClass, that);
policyManager.checkFileRead(callerClass, that, followLinks);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,15 @@ static List<String> pruneSortedPaths(List<String> paths) {
return prunedReadPaths;
}

public String toDebugString() {
return Strings.format(
"FileAccessTree[readPaths: [%s], writePaths: [%s], exclusivePaths: [%s]]",
String.join(",", readPaths),
String.join(",", writePaths),
String.join(",", exclusivePaths)
);
}

public static FileAccessTree of(
String componentName,
String moduleName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
import org.elasticsearch.logging.Logger;

import java.io.File;
import java.io.IOException;
import java.lang.StackWalker.StackFrame;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
Expand Down Expand Up @@ -325,6 +327,10 @@ private static boolean isPathOnDefaultFilesystem(Path path) {
}

public void checkFileRead(Class<?> callerClass, Path path) {
checkFileRead(callerClass, path, false);
}

public void checkFileRead(Class<?> callerClass, Path path, boolean followLinks) {
if (isPathOnDefaultFilesystem(path) == false) {
return;
}
Expand All @@ -334,14 +340,35 @@ public void checkFileRead(Class<?> callerClass, Path path) {
}

ModuleEntitlements entitlements = getEntitlements(requestingClass);
if (entitlements.fileAccess().canRead(path) == false) {

Path realPath = null, symbolicLinkPath = null;
boolean canRead = entitlements.fileAccess().canRead(path);

if (canRead && followLinks) {
try {
realPath = path.toRealPath();
} catch (IOException e) {}
try {
symbolicLinkPath = Files.readSymbolicLink(path);
canRead = entitlements.fileAccess.canRead(symbolicLinkPath);
} catch (IOException e) {}

if (canRead == false) {
logger.warn("Cannot read symbolic link [{} -> {}]: [real path: {}]", path, symbolicLinkPath, realPath);
}
}

if (canRead == false) {
logger.info(entitlements.fileAccess().toDebugString());
notEntitled(
Strings.format(
"Not entitled: component [%s], module [%s], class [%s], entitlement [file], operation [read], path [%s]",
entitlements.componentName(),
requestingClass.getModule().getName(),
requestingClass,
path
symbolicLinkPath == null
? FileAccessTree.normalizePath(path)
: FileAccessTree.normalizePath(path) + " -> " + FileAccessTree.normalizePath(symbolicLinkPath)
),
callerClass
);
Expand All @@ -364,13 +391,14 @@ public void checkFileWrite(Class<?> callerClass, Path path) {

ModuleEntitlements entitlements = getEntitlements(requestingClass);
if (entitlements.fileAccess().canWrite(path) == false) {
logger.info(entitlements.fileAccess().toDebugString());
notEntitled(
Strings.format(
"Not entitled: component [%s], module [%s], class [%s], entitlement [file], operation [write], path [%s]",
entitlements.componentName(),
requestingClass.getModule().getName(),
requestingClass,
path
FileAccessTree.normalizePath(path)
),
callerClass
);
Expand Down Expand Up @@ -607,7 +635,7 @@ Optional<Class<?>> findRequestingClass(Stream<Class<?>> classes) {
/**
* @return true if permission is granted regardless of the entitlement
*/
private static boolean isTriviallyAllowed(Class<?> requestingClass) {
protected static boolean isTriviallyAllowed(Class<?> requestingClass) {
if (logger.isTraceEnabled()) {
logger.trace("Stack trace for upcoming trivially-allowed check", new Exception());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@
import java.io.PrintStream;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.Permission;
import java.security.Security;
import java.util.ArrayList;
Expand All @@ -73,6 +76,7 @@
import java.util.stream.Stream;

import static org.elasticsearch.bootstrap.BootstrapSettings.SECURITY_FILTER_BAD_DEFAULTS_SETTING;
import static org.elasticsearch.core.PathUtils.getDefaultFileSystem;
import static org.elasticsearch.nativeaccess.WindowsFunctions.ConsoleCtrlHandler.CTRL_CLOSE_EVENT;

/**
Expand All @@ -98,6 +102,65 @@ public static void main(final String[] args) {
}
}

public static String listFiles(Path path) throws IOException {
StringBuilder builder = new StringBuilder();
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
private int depth = 0;

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
append(dir, builder, depth);
depth++;
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
append(file, builder, depth);
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
depth--;
return FileVisitResult.CONTINUE;
}

private static void append(Path path, StringBuilder builder, int depth) {
for (int i = 0; i < depth; i++) {
builder.append("|--");
}
builder.append(path.getFileName());
builder.append(" [");
try {
Path realPath = path.toRealPath();
if (path.equals(realPath) == false) {
builder.append("realPath:").append(realPath).append(", ");
}
} catch (IOException e) {
builder.append("error:").append(e.getMessage()).append(", ");
;
}
builder.append("normalizedPath:").append(normalizePath(path));
builder.append("]\n");
}

private static final String FILE_SEPARATOR = getDefaultFileSystem().getSeparator();

private 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.
String result = path.toAbsolutePath().normalize().toString();
while (result.endsWith(FILE_SEPARATOR)) {
result = result.substring(0, result.length() - FILE_SEPARATOR.length());
}
return result;
}
});
return builder.toString();
}

@SuppressForbidden(reason = "grab stderr for communication with server-cli")
private static PrintStream getStderr() {
return System.err;
Expand Down Expand Up @@ -231,6 +294,8 @@ private static void initPhase2(Bootstrap bootstrap) throws IOException {

final PluginsLoader pluginsLoader;

LogManager.getLogger(Elasticsearch.class).info("File system: \n{}", listFiles(nodeEnv.configDir()));

if (bootstrap.useEntitlements()) {
LogManager.getLogger(Elasticsearch.class).info("Bootstrapping Entitlements");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.elasticsearch.common.Randomness;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.core.FixForMultiProject;
import org.elasticsearch.entitlement.runtime.api.NotEntitledException;

import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
Expand Down Expand Up @@ -122,7 +123,12 @@ private static FileUpdateState readFileUpdateState(Path path) throws IOException
return null;
}

return new FileUpdateState(attr.lastModifiedTime().toMillis(), path.toRealPath().toString(), attr.fileKey());
try {
return new FileUpdateState(attr.lastModifiedTime().toMillis(), path.toRealPath().toString(), attr.fileKey());
} catch (NotEntitledException e) {
logger.warn("Not entitled to get real path of [{}] [{}]", path, path.toAbsolutePath().normalize(), e);
throw e;
}
}

// platform independent way to tell if a file changed
Expand Down