8343958: Remove security manager impl in java.lang.Process and java.lang.Runtime.exec

Reviewed-by: jpai, mullan, alanb
This commit is contained in:
Roger Riggs 2024-11-13 20:49:59 +00:00
parent 5ac330b1ac
commit 168b18ec68
4 changed files with 55 additions and 169 deletions

View file

@ -339,11 +339,6 @@ public final class ProcessBuilder
* @see System#getenv() * @see System#getenv()
*/ */
public Map<String,String> environment() { public Map<String,String> environment() {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkPermission(new RuntimePermission("getenv.*"));
if (environment == null) if (environment == null)
environment = ProcessEnvironment.environment(); environment = ProcessEnvironment.environment();
@ -1069,11 +1064,6 @@ public final class ProcessBuilder
// Throws IndexOutOfBoundsException if command is empty // Throws IndexOutOfBoundsException if command is empty
String prog = cmdarray[0]; String prog = cmdarray[0];
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkExec(prog);
String dir = directory == null ? null : directory.toString(); String dir = directory == null ? null : directory.toString();
for (String s : cmdarray) { for (String s : cmdarray) {
@ -1112,24 +1102,13 @@ public final class ProcessBuilder
} }
return process; return process;
} catch (IOException | IllegalArgumentException e) { } catch (IOException | IllegalArgumentException e) {
String exceptionInfo = ": " + e.getMessage();
Throwable cause = e;
if ((e instanceof IOException) && security != null) {
// Can not disclose the fail reason for read-protected files.
try {
security.checkRead(prog);
} catch (SecurityException se) {
exceptionInfo = "";
cause = se;
}
}
// It's much easier for us to create a high-quality error // It's much easier for us to create a high-quality error
// message than the low-level C code which found the problem. // message than the low-level C code which found the problem.
throw new IOException( throw new IOException(
"Cannot run program \"" + prog + "\"" "Cannot run program \"" + prog + "\""
+ (dir == null ? "" : " (in directory \"" + dir + "\")") + (dir == null ? "" : " (in directory \"" + dir + "\")")
+ exceptionInfo, + ": " + e.getMessage(),
cause); e);
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -84,28 +84,28 @@ final class ProcessHandleImpl implements ProcessHandle {
/** /**
* The thread pool of "process reaper" daemon threads. * The thread pool of "process reaper" daemon threads.
*/ */
@SuppressWarnings("removal") private static final Executor processReaperExecutor = initReaper();
private static final Executor processReaperExecutor =
AccessController.doPrivileged((PrivilegedAction<Executor>) () -> {
// Initialize ThreadLocalRandom now to avoid using the smaller stack
// of the processReaper threads.
ThreadLocalRandom.current();
// For a debug build, the stack shadow zone is larger; private static Executor initReaper() {
// Increase the total stack size to avoid potential stack overflow. // Initialize ThreadLocalRandom now to avoid using the smaller stack
int debugDelta = "release".equals(System.getProperty("jdk.debug")) ? 0 : (4*4096); // of the processReaper threads.
final long stackSize = Boolean.getBoolean("jdk.lang.processReaperUseDefaultStackSize") ThreadLocalRandom.current();
? 0 : REAPER_DEFAULT_STACKSIZE + debugDelta;
ThreadFactory threadFactory = grimReaper -> { // For a debug build, the stack shadow zone is larger;
Thread t = InnocuousThread.newSystemThread("process reaper", grimReaper, // Increase the total stack size to avoid potential stack overflow.
stackSize, Thread.MAX_PRIORITY); int debugDelta = "release".equals(System.getProperty("jdk.debug")) ? 0 : (4 * 4096);
privilegedThreadSetDaemon(t, true); final long stackSize = Boolean.getBoolean("jdk.lang.processReaperUseDefaultStackSize")
return t; ? 0 : REAPER_DEFAULT_STACKSIZE + debugDelta;
};
return Executors.newCachedThreadPool(threadFactory); ThreadFactory threadFactory = grimReaper -> {
}); Thread t = InnocuousThread.newSystemThread("process reaper", grimReaper,
stackSize, Thread.MAX_PRIORITY);
t.setDaemon(true);
return t;
};
return Executors.newCachedThreadPool(threadFactory);
}
private static class ExitCompletion extends CompletableFuture<Integer> { private static class ExitCompletion extends CompletableFuture<Integer> {
final boolean isReaping; final boolean isReaping;
@ -115,22 +115,6 @@ final class ProcessHandleImpl implements ProcessHandle {
} }
} }
@SuppressWarnings("removal")
private static void privilegedThreadSetName(Thread thread, String name) {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
thread.setName(name);
return null;
});
}
@SuppressWarnings("removal")
private static void privilegedThreadSetDaemon(Thread thread, boolean on) {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
thread.setDaemon(on);
return null;
});
}
/** /**
* Returns a CompletableFuture that completes with process exit status when * Returns a CompletableFuture that completes with process exit status when
* the process completes. * the process completes.
@ -158,7 +142,7 @@ final class ProcessHandleImpl implements ProcessHandle {
public void run() { public void run() {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
String threadName = t.getName(); String threadName = t.getName();
privilegedThreadSetName(t, "process reaper (pid " + pid + ")"); t.setName("process reaper (pid " + pid + ")");
try { try {
int exitValue = waitForProcessExit0(pid, shouldReap); int exitValue = waitForProcessExit0(pid, shouldReap);
if (exitValue == NOT_A_CHILD) { if (exitValue == NOT_A_CHILD) {
@ -189,7 +173,7 @@ final class ProcessHandleImpl implements ProcessHandle {
completions.remove(pid, newCompletion); completions.remove(pid, newCompletion);
} finally { } finally {
// Restore thread name // Restore thread name
privilegedThreadSetName(t, threadName); t.setName(threadName);
} }
} }
}); });
@ -255,14 +239,8 @@ final class ProcessHandleImpl implements ProcessHandle {
* @param pid the native process identifier * @param pid the native process identifier
* @return The ProcessHandle for the pid if the process is alive; * @return The ProcessHandle for the pid if the process is alive;
* or {@code null} if the process ID does not exist in the native system. * or {@code null} if the process ID does not exist in the native system.
* @throws SecurityException if RuntimePermission("manageProcess") is not granted
*/ */
static Optional<ProcessHandle> get(long pid) { static Optional<ProcessHandle> get(long pid) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess"));
}
long start = isAlive0(pid); long start = isAlive0(pid);
return (start >= 0) return (start >= 0)
? Optional.of(new ProcessHandleImpl(pid, start)) ? Optional.of(new ProcessHandleImpl(pid, start))
@ -296,14 +274,8 @@ final class ProcessHandleImpl implements ProcessHandle {
* Returns the ProcessHandle for the current native process. * Returns the ProcessHandle for the current native process.
* *
* @return The ProcessHandle for the OS process. * @return The ProcessHandle for the OS process.
* @throws SecurityException if RuntimePermission("manageProcess") is not granted
*/ */
public static ProcessHandleImpl current() { public static ProcessHandleImpl current() {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess"));
}
return current; return current;
} }
@ -319,15 +291,8 @@ final class ProcessHandleImpl implements ProcessHandle {
* *
* @return a ProcessHandle of the parent process; {@code null} is returned * @return a ProcessHandle of the parent process; {@code null} is returned
* if the child process does not have a parent * if the child process does not have a parent
* @throws SecurityException if permission is not granted by the
* security policy
*/ */
public Optional<ProcessHandle> parent() { public Optional<ProcessHandle> parent() {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess"));
}
long ppid = parent0(pid, startTime); long ppid = parent0(pid, startTime);
if (ppid <= 0) { if (ppid <= 0) {
return Optional.empty(); return Optional.empty();
@ -442,11 +407,6 @@ final class ProcessHandleImpl implements ProcessHandle {
* @return a stream of ProcessHandles * @return a stream of ProcessHandles
*/ */
static Stream<ProcessHandle> children(long pid) { static Stream<ProcessHandle> children(long pid) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess"));
}
int size = 100; int size = 100;
long[] childpids = null; long[] childpids = null;
long[] starttimes = null; long[] starttimes = null;
@ -463,11 +423,6 @@ final class ProcessHandleImpl implements ProcessHandle {
@Override @Override
public Stream<ProcessHandle> descendants() { public Stream<ProcessHandle> descendants() {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess"));
}
int size = 100; int size = 100;
long[] pids = null; long[] pids = null;
long[] ppids = null; long[] ppids = null;

View file

@ -42,14 +42,10 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import jdk.internal.access.JavaIOFileDescriptorAccess; import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
import jdk.internal.util.OperatingSystem; import jdk.internal.util.OperatingSystem;
import jdk.internal.util.StaticProperty; import jdk.internal.util.StaticProperty;
import sun.security.action.GetPropertyAction;
/** /**
* java.lang.Process subclass in the UNIX environment. * java.lang.Process subclass in the UNIX environment.
@ -95,7 +91,7 @@ final class ProcessImpl extends Process {
* @throws Error if the requested launch mechanism is not found or valid * @throws Error if the requested launch mechanism is not found or valid
*/ */
private static LaunchMechanism launchMechanism() { private static LaunchMechanism launchMechanism() {
String s = GetPropertyAction.privilegedGetProperty("jdk.lang.Process.launchMechanism"); String s = System.getProperty("jdk.lang.Process.launchMechanism");
if (s == null) { if (s == null) {
return LaunchMechanism.POSIX_SPAWN; return LaunchMechanism.POSIX_SPAWN;
} }
@ -282,7 +278,6 @@ final class ProcessImpl extends Process {
boolean redirectErrorStream) boolean redirectErrorStream)
throws IOException; throws IOException;
@SuppressWarnings("removal")
private ProcessImpl(final byte[] prog, private ProcessImpl(final byte[] prog,
final byte[] argBlock, final int argc, final byte[] argBlock, final int argc,
final byte[] envBlock, final int envc, final byte[] envBlock, final int envc,
@ -302,14 +297,7 @@ final class ProcessImpl extends Process {
redirectErrorStream); redirectErrorStream);
processHandle = ProcessHandleImpl.getInternal(pid); processHandle = ProcessHandleImpl.getInternal(pid);
try { initStreams(fds, forceNullOutputStream);
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
initStreams(fds, forceNullOutputStream);
return null;
});
} catch (PrivilegedActionException ex) {
throw (IOException) ex.getCause();
}
} }
static FileDescriptor newFileDescriptor(int fd) { static FileDescriptor newFileDescriptor(int fd) {
@ -507,11 +495,6 @@ final class ProcessImpl extends Process {
@Override @Override
public ProcessHandle toHandle() { public ProcessHandle toHandle() {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess"));
}
return processHandle; return processHandle;
} }

View file

@ -35,8 +35,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.ProcessBuilder.Redirect; import java.lang.ProcessBuilder.Redirect;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -48,7 +46,6 @@ import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
import jdk.internal.ref.CleanerFactory; import jdk.internal.ref.CleanerFactory;
import jdk.internal.misc.Blocker; import jdk.internal.misc.Blocker;
import sun.security.action.GetPropertyAction;
/* This class is for the exclusive use of ProcessBuilder.start() to /* This class is for the exclusive use of ProcessBuilder.start() to
* create new processes. * create new processes.
@ -71,25 +68,15 @@ final class ProcessImpl extends Process {
* to append to a file does not open the file in a manner that guarantees * to append to a file does not open the file in a manner that guarantees
* that writes by the child process will be atomic. * that writes by the child process will be atomic.
*/ */
@SuppressWarnings("removal")
private static FileOutputStream newFileOutputStream(File f, boolean append) private static FileOutputStream newFileOutputStream(File f, boolean append)
throws IOException throws IOException
{ {
if (append) { if (append) {
String path = f.getPath(); String path = f.getPath();
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkWrite(path);
long handle = openForAtomicAppend(path); long handle = openForAtomicAppend(path);
final FileDescriptor fd = new FileDescriptor(); final FileDescriptor fd = new FileDescriptor();
fdAccess.setHandle(fd, handle); fdAccess.setHandle(fd, handle);
return AccessController.doPrivileged( return new FileOutputStream(fd);
new PrivilegedAction<FileOutputStream>() {
public FileOutputStream run() {
return new FileOutputStream(fd);
}
}
);
} else { } else {
return new FileOutputStream(f); return new FileOutputStream(f);
} }
@ -424,7 +411,6 @@ final class ProcessImpl extends Process {
private InputStream stdout_stream; private InputStream stdout_stream;
private InputStream stderr_stream; private InputStream stderr_stream;
@SuppressWarnings("removal")
private ProcessImpl(String cmd[], private ProcessImpl(String cmd[],
final String envblock, final String envblock,
final String path, final String path,
@ -434,13 +420,10 @@ final class ProcessImpl extends Process {
throws IOException throws IOException
{ {
String cmdstr; String cmdstr;
final SecurityManager security = System.getSecurityManager(); final String value = System.getProperty("jdk.lang.Process.allowAmbiguousCommands", "true");
final String value = GetPropertyAction.
privilegedGetProperty("jdk.lang.Process.allowAmbiguousCommands",
(security == null ? "true" : "false"));
final boolean allowAmbiguousCommands = !"false".equalsIgnoreCase(value); final boolean allowAmbiguousCommands = !"false".equalsIgnoreCase(value);
if (allowAmbiguousCommands && security == null) { if (allowAmbiguousCommands) {
// Legacy mode. // Legacy mode.
// Normalize path if possible. // Normalize path if possible.
@ -478,10 +461,6 @@ final class ProcessImpl extends Process {
// Parse the command line again. // Parse the command line again.
cmd = getTokensFromCommand(join.toString()); cmd = getTokensFromCommand(join.toString());
executablePath = getExecutablePath(cmd[0]); executablePath = getExecutablePath(cmd[0]);
// Check new executable name once more
if (security != null)
security.checkExec(executablePath);
} }
// Quotation protects from interpretation of the [path] argument as // Quotation protects from interpretation of the [path] argument as
@ -505,39 +484,34 @@ final class ProcessImpl extends Process {
processHandle = ProcessHandleImpl.getInternal(getProcessId0(handle)); processHandle = ProcessHandleImpl.getInternal(getProcessId0(handle));
java.security.AccessController.doPrivileged( if (stdHandles[0] == -1L)
new java.security.PrivilegedAction<Void>() { stdin_stream = ProcessBuilder.NullOutputStream.INSTANCE;
public Void run() { else {
if (stdHandles[0] == -1L) FileDescriptor stdin_fd = new FileDescriptor();
stdin_stream = ProcessBuilder.NullOutputStream.INSTANCE; fdAccess.setHandle(stdin_fd, stdHandles[0]);
else { fdAccess.registerCleanup(stdin_fd);
FileDescriptor stdin_fd = new FileDescriptor(); stdin_stream = new BufferedOutputStream(
fdAccess.setHandle(stdin_fd, stdHandles[0]); new PipeOutputStream(stdin_fd));
fdAccess.registerCleanup(stdin_fd); }
stdin_stream = new BufferedOutputStream(
new PipeOutputStream(stdin_fd));
}
if (stdHandles[1] == -1L || forceNullOutputStream) if (stdHandles[1] == -1L || forceNullOutputStream)
stdout_stream = ProcessBuilder.NullInputStream.INSTANCE; stdout_stream = ProcessBuilder.NullInputStream.INSTANCE;
else { else {
FileDescriptor stdout_fd = new FileDescriptor(); FileDescriptor stdout_fd = new FileDescriptor();
fdAccess.setHandle(stdout_fd, stdHandles[1]); fdAccess.setHandle(stdout_fd, stdHandles[1]);
fdAccess.registerCleanup(stdout_fd); fdAccess.registerCleanup(stdout_fd);
stdout_stream = new BufferedInputStream( stdout_stream = new BufferedInputStream(
new PipeInputStream(stdout_fd)); new PipeInputStream(stdout_fd));
} }
if (stdHandles[2] == -1L) if (stdHandles[2] == -1L)
stderr_stream = ProcessBuilder.NullInputStream.INSTANCE; stderr_stream = ProcessBuilder.NullInputStream.INSTANCE;
else { else {
FileDescriptor stderr_fd = new FileDescriptor(); FileDescriptor stderr_fd = new FileDescriptor();
fdAccess.setHandle(stderr_fd, stdHandles[2]); fdAccess.setHandle(stderr_fd, stdHandles[2]);
fdAccess.registerCleanup(stderr_fd); fdAccess.registerCleanup(stderr_fd);
stderr_stream = new PipeInputStream(stderr_fd); stderr_stream = new PipeInputStream(stderr_fd);
} }
return null; }});
} }
public OutputStream getOutputStream() { public OutputStream getOutputStream() {
@ -632,11 +606,6 @@ final class ProcessImpl extends Process {
@Override @Override
public ProcessHandle toHandle() { public ProcessHandle toHandle() {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess"));
}
return processHandle; return processHandle;
} }