From 03b199b260f8a739c9c1dc107ecfcd423a36d9a3 Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Wed, 9 Apr 2025 22:27:29 -0400 Subject: [PATCH 1/2] Fix FileInterceptor's delete calls for Unix Domain Sockets on Windows Signed-off-by: Andriy Redko --- .../main/java/org/opensearch/javaagent/FileInterceptor.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java index e1ceddee23ca4..3910de6b559fa 100644 --- a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java +++ b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java @@ -71,6 +71,11 @@ public static void intercept(@Advice.AllArguments Object[] args, @Advice.Origin boolean isMutating = name.equals("move") || name.equals("write") || name.startsWith("create"); final boolean isDelete = isMutating == false ? name.startsWith("delete") : false; + // This is Windows implementation of UNIX Domain Sockets (close) + if (walker.getCallerClass().getName().equalsIgnoreCase("sun.nio.ch.PipeImpl$Initializer$LoopbackConnector") == true) { + return; + } + String targetFilePath = null; if (isMutating == false && isDelete == false) { if (name.equals("newByteChannel") == true || name.equals("open") == true) { From a10b5026d26b3c135e2dd0b8e6ece055f635c7b5 Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Wed, 9 Apr 2025 22:52:03 -0400 Subject: [PATCH 2/2] Added NetPermission check for UNIX Domain Socket deletion on Windows Signed-off-by: Andriy Redko --- .../opensearch/javaagent/FileInterceptor.java | 97 ++++++++++--------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java index 3910de6b559fa..f17cfccd8d86f 100644 --- a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java +++ b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/FileInterceptor.java @@ -12,6 +12,7 @@ import java.io.FilePermission; import java.lang.reflect.Method; +import java.net.NetPermission; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; @@ -72,63 +73,69 @@ public static void intercept(@Advice.AllArguments Object[] args, @Advice.Origin final boolean isDelete = isMutating == false ? name.startsWith("delete") : false; // This is Windows implementation of UNIX Domain Sockets (close) - if (walker.getCallerClass().getName().equalsIgnoreCase("sun.nio.ch.PipeImpl$Initializer$LoopbackConnector") == true) { - return; - } - - String targetFilePath = null; - if (isMutating == false && isDelete == false) { - if (name.equals("newByteChannel") == true || name.equals("open") == true) { - if (args.length > 1 && args[1] instanceof OpenOption[] opts) { - for (final OpenOption opt : opts) { - if (opt != StandardOpenOption.READ) { - isMutating = true; - break; - } - } - - } - } else if (name.equals("copy") == true) { - if (args.length > 1 && args[1] instanceof String pathStr) { - targetFilePath = Paths.get(pathStr).toAbsolutePath().toString(); - } else if (args.length > 1 && args[1] instanceof Path path) { - targetFilePath = path.toAbsolutePath().toString(); + if (isDelete == true + && walker.getCallerClass().getName().equalsIgnoreCase("sun.nio.ch.PipeImpl$Initializer$LoopbackConnector") == true) { + final NetPermission permission = new NetPermission("accessUnixDomainSocket"); + for (ProtectionDomain domain : callers) { + if (!policy.implies(domain, permission)) { + throw new SecurityException("Denied access to: " + filePath + ", domain " + domain); } } - } + } else { + String targetFilePath = null; + if (isMutating == false && isDelete == false) { + if (name.equals("newByteChannel") == true || name.equals("open") == true) { + if (args.length > 1 && args[1] instanceof OpenOption[] opts) { + for (final OpenOption opt : opts) { + if (opt != StandardOpenOption.READ) { + isMutating = true; + break; + } + } - // Check each permission separately - for (final ProtectionDomain domain : callers) { - // Handle FileChannel.open() separately to check read/write permissions properly - if (method.getName().equals("open")) { - if (isMutating == true && !policy.implies(domain, new FilePermission(filePath, "read,write"))) { - throw new SecurityException("Denied OPEN (read/write) access to file: " + filePath + ", domain: " + domain); - } else if (!policy.implies(domain, new FilePermission(filePath, "read"))) { - throw new SecurityException("Denied OPEN (read) access to file: " + filePath + ", domain: " + domain); + } + } else if (name.equals("copy") == true) { + if (args.length > 1 && args[1] instanceof String pathStr) { + targetFilePath = Paths.get(pathStr).toAbsolutePath().toString(); + } else if (args.length > 1 && args[1] instanceof Path path) { + targetFilePath = path.toAbsolutePath().toString(); + } } } - // Handle Files.copy() separately to check read/write permissions properly - if (method.getName().equals("copy")) { - if (!policy.implies(domain, new FilePermission(filePath, "read"))) { - throw new SecurityException("Denied COPY (read) access to file: " + filePath + ", domain: " + domain); + // Check each permission separately + for (final ProtectionDomain domain : callers) { + // Handle FileChannel.open() separately to check read/write permissions properly + if (method.getName().equals("open")) { + if (isMutating == true && !policy.implies(domain, new FilePermission(filePath, "read,write"))) { + throw new SecurityException("Denied OPEN (read/write) access to file: " + filePath + ", domain: " + domain); + } else if (!policy.implies(domain, new FilePermission(filePath, "read"))) { + throw new SecurityException("Denied OPEN (read) access to file: " + filePath + ", domain: " + domain); + } } - if (targetFilePath != null) { - if (!policy.implies(domain, new FilePermission(targetFilePath, "write"))) { - throw new SecurityException("Denied COPY (write) access to file: " + targetFilePath + ", domain: " + domain); + // Handle Files.copy() separately to check read/write permissions properly + if (method.getName().equals("copy")) { + if (!policy.implies(domain, new FilePermission(filePath, "read"))) { + throw new SecurityException("Denied COPY (read) access to file: " + filePath + ", domain: " + domain); + } + + if (targetFilePath != null) { + if (!policy.implies(domain, new FilePermission(targetFilePath, "write"))) { + throw new SecurityException("Denied COPY (write) access to file: " + targetFilePath + ", domain: " + domain); + } } } - } - // File mutating operations - if (isMutating && !policy.implies(domain, new FilePermission(filePath, "write"))) { - throw new SecurityException("Denied WRITE access to file: " + filePath + ", domain: " + domain); - } + // File mutating operations + if (isMutating && !policy.implies(domain, new FilePermission(filePath, "write"))) { + throw new SecurityException("Denied WRITE access to file: " + filePath + ", domain: " + domain); + } - // File deletion operations - if (isDelete && !policy.implies(domain, new FilePermission(filePath, "delete"))) { - throw new SecurityException("Denied DELETE access to file: " + filePath + ", domain: " + domain); + // File deletion operations + if (isDelete && !policy.implies(domain, new FilePermission(filePath, "delete"))) { + throw new SecurityException("Denied DELETE access to file: " + filePath + ", domain: " + domain); + } } } }