diff --git a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java index ff9cf8b0fbd..1596f23c921 100644 --- a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java +++ b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java @@ -100,7 +100,7 @@ final class ProcessHandleImpl implements ProcessHandle { ThreadFactory threadFactory = grimReaper -> { Thread t = InnocuousThread.newSystemThread("process reaper", grimReaper, stackSize, Thread.MAX_PRIORITY); - t.setDaemon(true); + privilegedThreadSetDaemon(t, true); return t; }; @@ -115,6 +115,22 @@ private static class ExitCompletion extends CompletableFuture { } } + @SuppressWarnings("removal") + private static void privilegedThreadSetName(Thread thread, String name) { + AccessController.doPrivileged((PrivilegedAction) () -> { + thread.setName(name); + return null; + }); + } + + @SuppressWarnings("removal") + private static void privilegedThreadSetDaemon(Thread thread, boolean on) { + AccessController.doPrivileged((PrivilegedAction) () -> { + thread.setDaemon(on); + return null; + }); + } + /** * Returns a CompletableFuture that completes with process exit status when * the process completes. @@ -140,8 +156,9 @@ static CompletableFuture completion(long pid, boolean shouldReap) { processReaperExecutor.execute(new Runnable() { // Use inner class to avoid lambda stack overhead public void run() { - String threadName = Thread.currentThread().getName(); - Thread.currentThread().setName("process reaper (pid " + pid + ")"); + Thread t = Thread.currentThread(); + String threadName = t.getName(); + privilegedThreadSetName(t, "process reaper (pid " + pid + ")"); try { int exitValue = waitForProcessExit0(pid, shouldReap); if (exitValue == NOT_A_CHILD) { @@ -172,7 +189,7 @@ public void run() { completions.remove(pid, newCompletion); } finally { // Restore thread name - Thread.currentThread().setName(threadName); + privilegedThreadSetName(t, threadName); } } }); diff --git a/test/jdk/java/lang/ProcessBuilder/SecurityManagerClinit.java b/test/jdk/java/lang/ProcessBuilder/SecurityManagerClinit.java index 1aa56c9b728..068acad0ed0 100644 --- a/test/jdk/java/lang/ProcessBuilder/SecurityManagerClinit.java +++ b/test/jdk/java/lang/ProcessBuilder/SecurityManagerClinit.java @@ -24,7 +24,7 @@ /* * @test - * @bug 6980747 + * @bug 6980747 8297451 * @summary Check that Process-related classes have the proper * doPrivileged blocks, and can be initialized with an adversarial * security manager. @@ -52,6 +52,17 @@ public boolean implies(ProtectionDomain pd, Permission p) { } } + // Security manager that unconditionally performs Thread Modify Access checks. + @SuppressWarnings("removal") + private static class TMACSecurityManager extends SecurityManager { + static final RuntimePermission MODIFY_THREAD_PERMISSION = + new RuntimePermission("modifyThread"); + @Override + public void checkAccess(Thread thread) { + checkPermission(MODIFY_THREAD_PERMISSION); + } + } + public static void main(String[] args) throws Throwable { String javaExe = System.getProperty("java.home") + @@ -60,10 +71,11 @@ public static void main(String[] args) throws Throwable { final SimplePolicy policy = new SimplePolicy (new FilePermission("<>", "execute"), - new RuntimePermission("setSecurityManager")); + new RuntimePermission("setSecurityManager"), + new RuntimePermission("modifyThread")); Policy.setPolicy(policy); - System.setSecurityManager(new SecurityManager()); + System.setSecurityManager(new TMACSecurityManager()); try { String[] cmd = { javaExe, "-version" };