From 6b396da278094d7109ad2fbe7a1a52a500e15d75 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 16 Aug 2023 17:53:56 +0000 Subject: [PATCH] 8062795: (fs) Files.setPermissions requires read access when NOFOLLOW_LINKS specified Reviewed-by: alanb --- .../sun/nio/fs/UnixFileAttributeViews.java | 50 ++++++++++++++----- .../PosixFileAttributeView/Basic.java | 48 ++++++++++++++++-- 2 files changed, 82 insertions(+), 16 deletions(-) diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java index f35541a9e19..94e0f91e812 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.io.IOException; +import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixNativeDispatcher.*; class UnixFileAttributeViews { @@ -262,19 +263,44 @@ class UnixFileAttributeViews { // chmod final void setMode(int mode) throws IOException { checkWriteExtended(); - try { - if (followLinks) { + + if (followLinks) { + try { chmod(file, mode); - } else { - int fd = file.openForAttributeAccess(false); - try { - fchmod(fd, mode); - } finally { - close(fd); - } + } catch (UnixException e) { + e.rethrowAsIOException(file); } - } catch (UnixException x) { - x.rethrowAsIOException(file); + return; + } + + if (O_NOFOLLOW == 0) { + throw new IOException("NOFOLLOW_LINKS is not supported on this platform"); + } + + int fd = -1; + try { + fd = open(file, O_RDONLY, O_NOFOLLOW); + } catch (UnixException e1) { + if (e1.errno() == EACCES) { + // retry with write access if there is no read permission + try { + fd = open(file, O_WRONLY, O_NOFOLLOW); + } catch (UnixException e2) { + e2.rethrowAsIOException(file); + } + } else { + e1.rethrowAsIOException(file); + } + } + + try { + try { + fchmod(fd, mode); + } finally { + close(fd); + } + } catch (UnixException e) { + e.rethrowAsIOException(file); } } diff --git a/test/jdk/java/nio/file/attribute/PosixFileAttributeView/Basic.java b/test/jdk/java/nio/file/attribute/PosixFileAttributeView/Basic.java index 1ce0c6031cd..6626a289dce 100644 --- a/test/jdk/java/nio/file/attribute/PosixFileAttributeView/Basic.java +++ b/test/jdk/java/nio/file/attribute/PosixFileAttributeView/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 + * @bug 4313887 6838333 8062795 * @summary Unit test for java.nio.file.attribute.PosixFileAttributeView * @library ../.. */ @@ -167,9 +167,9 @@ public class Basic { Files.delete(file); } - // create link (to file that doesn't exist) and test reading of - // permissions if (TestUtil.supportsLinks(dir)) { + // create link (to file that doesn't exist) and test reading of + // permissions Path link = dir.resolve("link"); System.out.format("create link %s\n", link); Files.createSymbolicLink(link, file); @@ -185,6 +185,46 @@ public class Basic { } finally { Files.delete(link); } + + // test that setting permissions on paths with and without + // links succeeds when the NOFOLLOW_LINKS option is set + + // ensure there are no links in the path to test + Path realDir = dir.toRealPath(); + + // realDir/a/b/c/d + Path leaf = realDir.resolve(Path.of("a", "b", "c", "d")); + Files.createDirectories(leaf); + + // realDir/a/b/c/d/FUBAR + Path sansLinks = Files.createTempFile(leaf, "FU", "BAR"); + + PosixFileAttributeView sansView = + Files.getFileAttributeView(sansLinks, + PosixFileAttributeView.class, + LinkOption.NOFOLLOW_LINKS); + sansView.setPermissions(Set.of(PosixFilePermission.OWNER_WRITE)); + sansView.setPermissions(Set.of(PosixFilePermission.OWNER_WRITE)); + + // reinstate read permission + sansView.setPermissions(Set.of(PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE)); + + // lien -> realDir/a/b/c + Path lien = realDir.resolve(Path.of("a", "lien")); + Files.createSymbolicLink(lien, + realDir.resolve(Path.of("a", "b", "c"))); + + // lien/d/FUBAR + Path withLinks = lien.resolve(Path.of("d"), + sansLinks.getFileName()); + + PosixFileAttributeView withView = + Files.getFileAttributeView(withLinks, + PosixFileAttributeView.class, + LinkOption.NOFOLLOW_LINKS); + withView.setPermissions(Set.of(PosixFilePermission.OWNER_WRITE)); + withView.setPermissions(Set.of(PosixFilePermission.OWNER_WRITE)); } System.out.println("OKAY");