8221852: SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE should be selected at runtime, not build time

Reviewed-by: alanb, shade
This commit is contained in:
Brian Burkhalter 2019-04-09 12:17:03 -07:00
parent 1aa784cdac
commit 5952e2bc64
3 changed files with 26 additions and 13 deletions
src/java.base/windows

@ -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 @@ class WindowsConstants {
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 @@ class WindowsConstants {
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;

@ -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.AccessController;
import java.security.PrivilegedAction;
import jdk.internal.misc.Unsafe;
import static sun.nio.fs.WindowsConstants.*;
/**
* Win32 and library calls.
*/
@ -920,6 +922,12 @@ class WindowsNativeDispatcher {
* 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 @@ class WindowsNativeDispatcher {
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();

@ -1063,17 +1063,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_CreateSymbolicLink0(JNIEnv* env,
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());
}