8221852: SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE should be selected at runtime, not build time
authorbpb
Tue, 09 Apr 2019 12:17:03 -0700
changeset 54476 20f7bbfc61d3
parent 54475 805584336738
child 54477 511be32f3863
8221852: SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE should be selected at runtime, not build time Reviewed-by: alanb, shade
src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java
src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java
src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java	Tue Apr 09 09:49:36 2019 -0700
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java	Tue Apr 09 12:17:03 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -75,6 +75,7 @@
     public static final int IO_REPARSE_TAG_SYMLINK              = 0xA000000C;
     public static final int MAXIMUM_REPARSE_DATA_BUFFER_SIZE    = 16 * 1024;
     public static final int SYMBOLIC_LINK_FLAG_DIRECTORY        = 0x1;
+    public static final int SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2;
 
     // volume flags
     public static final int FILE_CASE_SENSITIVE_SEARCH      = 0x00000001;
@@ -104,6 +105,7 @@
     public static final int ERROR_MORE_DATA             = 234;
     public static final int ERROR_DIRECTORY             = 267;
     public static final int ERROR_NOTIFY_ENUM_DIR       = 1022;
+    public static final int ERROR_PRIVILEGE_NOT_HELD    = 1314;
     public static final int ERROR_NONE_MAPPED           = 1332;
     public static final int ERROR_NOT_A_REPARSE_POINT   = 4390;
     public static final int ERROR_INVALID_REPARSE_DATA  = 4392;
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Tue Apr 09 09:49:36 2019 -0700
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Tue Apr 09 12:17:03 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -29,6 +29,8 @@
 import java.security.PrivilegedAction;
 import jdk.internal.misc.Unsafe;
 
+import static sun.nio.fs.WindowsConstants.*;
+
 /**
  * Win32 and library calls.
  */
@@ -920,6 +922,12 @@
      *   LPCWSTR lpTargetFileName,
      *   DWORD dwFlags
      * )
+     *
+     * Creates a symbolic link, conditionally retrying with the addition of
+     * the flag SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE if the initial
+     * attempt fails with ERROR_PRIVILEGE_NOT_HELD. If the retry fails, throw
+     * the original exception due to ERROR_PRIVILEGE_NOT_HELD. The retry will
+     * succeed only on Windows build 14972 or later if Developer Mode is on.
      */
     static void CreateSymbolicLink(String link, String target, int flags)
         throws WindowsException
@@ -929,6 +937,19 @@
         try {
             CreateSymbolicLink0(linkBuffer.address(), targetBuffer.address(),
                                 flags);
+        } catch (WindowsException x) {
+            if (x.lastError() == ERROR_PRIVILEGE_NOT_HELD) {
+                flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+                try {
+                    CreateSymbolicLink0(linkBuffer.address(),
+                                        targetBuffer.address(), flags);
+                    return;
+                } catch (WindowsException ignored) {
+                    // Will fail with ERROR_INVALID_PARAMETER for Windows
+                    // builds older than 14972.
+                }
+            }
+            throw x;
         } finally {
             targetBuffer.release();
             linkBuffer.release();
--- a/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c	Tue Apr 09 09:49:36 2019 -0700
+++ b/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c	Tue Apr 09 12:17:03 2019 -0700
@@ -1063,17 +1063,7 @@
     LPCWSTR link = jlong_to_ptr(linkAddress);
     LPCWSTR target = jlong_to_ptr(targetAddress);
 
-    // Allow creation of symbolic links when the process is not elevated.
-    // Developer Mode must be enabled for this option to function, otherwise
-    // it will be ignored. Check that symbol is available in current build SDK.
-    DWORD dwFlags = (DWORD)flags;
-#ifdef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
-    dwFlags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
-#endif
-
-    // On Windows 64-bit this appears to succeed even when there are
-    // insufficient privileges
-    if (CreateSymbolicLinkW(link, target, dwFlags) == 0)
+    if (CreateSymbolicLinkW(link, target, (DWORD)flags) == 0)
         throwWindowsException(env, GetLastError());
 }