On Sat, 16 May 2026 00:19:02 GMT, Ashay Rane <[email protected]> wrote:
> Prior to this patch, when `userOnly` was true, the conflicting "allow" > entry (for the owner) and "deny" entry (for groups that the owner is a > member of) resulted in the owner being denied access since the "deny" > entry takes precedence. This resulted in RmiBootstrapTest and > RmiSslNoKeyStoreTest tests failing with an "Access Denied" error. > > In reality, the "deny" entry is not required, since Windows grants > access only when an explicit "allow" entry matches the requesting > principal. So this patch fixes the ACLs so that when `userOnly` is > true, only the owner has "allow" access. Principals without a matching > "allow" entry are denied access, thus restricting access without risking > a group "deny" entry overriding the owner's access. > > This patch also fixes the case when `userOnly` is false so that it > doesn't inadvertently deny access when a principal didn't already have > an ACL entry for the file. > > --------- > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). The following standalone program demonstrates the problem more succintly: import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.AclEntry; import java.nio.file.attribute.AclEntryPermission; import java.nio.file.attribute.AclEntryType; import java.nio.file.attribute.AclFileAttributeView; import java.nio.file.attribute.UserPrincipal; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; public class AclDemo { public static void main(String[] args) throws Exception { Path file = Files.createTempFile("acl-demo-", ".txt"); AclFileAttributeView view = Files.getFileAttributeView(file, AclFileAttributeView.class); System.out.println("Owner: " + view.getOwner().getName()); List<AclEntry> originalAcl = view.getAcl(); System.out.println("\nOriginal ACL:"); printAcl(originalAcl); System.out.println("\nACL after updating using old code:"); List<AclEntry> buggyAcl = oldUpdate(originalAcl, view.getOwner()); view.setAcl(buggyAcl); printAcl(view.getAcl()); tryRead(file); List<AclEntry> revisedAcl = newUpdate(originalAcl, view.getOwner()); System.out.println("\nACL after updating using new code:"); view.setAcl(revisedAcl); printAcl(view.getAcl()); tryRead(file); Files.deleteIfExists(file); } static List<AclEntry> oldUpdate(List<AclEntry> oldAcl, UserPrincipal owner) { List<AclEntry> newAcl = new ArrayList<>(); for (AclEntry entry : oldAcl) { String principalName = entry.principal().getName(); boolean isOwner = principalName.equals(owner.getName()); if (isOwner) { AclEntry allowed = AclEntry.newBuilder(entry).setType(AclEntryType.ALLOW).build(); newAcl.add(allowed); } else if (entry.type() == AclEntryType.ALLOW) { AclEntry denied = AclEntry.newBuilder(entry).setType(AclEntryType.DENY).build(); newAcl.add(denied); } else { newAcl.add(entry); } } return newAcl; } static List<AclEntry> newUpdate(List<AclEntry> oldAcl, UserPrincipal owner) { List<AclEntry> newAcl = new ArrayList<>(); newAcl.add(AclEntry.newBuilder() .setType(AclEntryType.ALLOW) .setPrincipal(owner) .setPermissions(EnumSet.allOf(AclEntryPermission.class)) .build()); return newAcl; } static void printAcl(List<AclEntry> acl) { for (int i = 0; i < acl.size(); i++) { AclEntry entry = acl.get(i); System.out.println("[" + i + "] principal=" + entry.principal().getName() + ", type=" + entry.type()); } } static void tryRead(Path file) { try (FileInputStream fis = new FileInputStream(file.toFile())) { byte[] data = fis.readAllBytes(); System.out.println("\nSUCCESS: Read " + data.length + " bytes"); } catch (IOException e) { System.out.println("\nFAILED: " + e.getClass().getName() + ": " + e.getMessage()); } } } which results in the following output on my machine: >_ java AclDemo.java Owner: REDMOND\raneashay Original ACL: [0] principal=NT AUTHORITY\SYSTEM, type=ALLOW [1] principal=BUILTIN\Administrators, type=ALLOW [2] principal=REDMOND\raneashay, type=ALLOW ACL after updating using old code: [0] principal=NT AUTHORITY\SYSTEM, type=DENY [1] principal=BUILTIN\Administrators, type=DENY [2] principal=REDMOND\raneashay, type=ALLOW FAILED: java.io.FileNotFoundException: C:\Users\RANEAS~1\AppData\Local\Temp\acl-demo-1845852012895386055.txt (Access is denied) ACL after updating using new code: [0] principal=REDMOND\raneashay, type=ALLOW SUCCESS: Read 0 bytes ------------- PR Comment: https://git.openjdk.org/jdk/pull/31179#issuecomment-4464712606
