Skip to content

Commit

Permalink
Remove SecurityManager references from logging package eclipse-ee4j#16
Browse files Browse the repository at this point in the history
Signed-off-by: jmehrens <[email protected]>
  • Loading branch information
jmehrens committed Jan 14, 2024
1 parent 576e4cc commit 3471c2d
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Comparator;
Expand All @@ -37,6 +36,7 @@
import java.util.logging.Filter;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
Expand Down Expand Up @@ -251,62 +251,19 @@ static String fromLogManager(final String name) {
* @since JavaMail 1.5.3
*/
static void checkLogManagerAccess() {
boolean checked = false;
final Object m = LOG_MANAGER;
if (m != null) {
try {
if (m instanceof LogManager) {
checked = true;
((LogManager) m).checkAccess();
}
} catch (final SecurityException notAllowed) {
if (checked) {
throw notAllowed;
}
} catch (final LinkageError | RuntimeException restricted) {
}
}

if (!checked) {
checkLoggingAccess();
}
}

/**
* Check that the current context is trusted to modify the logging
* configuration when the LogManager is not present. This requires
* LoggingPermission("control").
*
* @throws SecurityException if a security manager exists and the caller
* does not have {@code LoggingPermission("control")}.
* @since JavaMail 1.5.3
*/
private static void checkLoggingAccess() {
/**
* Some environments selectively enforce logging permissions by allowing
* access to loggers but not allowing access to handlers. This is an
* indirect way of checking for LoggingPermission when the LogManager is
* not present. The root logger will lazy create handlers so the global
* logger is used instead as it is a known named logger with well
* defined behavior. If the global logger is a subclass then fallback to
* using the SecurityManager.
* defined behavior. Contractually, Logger::remove will check
* permission before checking if the argument is null.
*/
boolean checked = false;
final Logger global = Logger.getLogger("global");
try {
if (Logger.class == global.getClass()) {
global.removeHandler((Handler) null);
checked = true;
}
Logger.getGlobal().removeHandler((Handler) null);
} catch (final NullPointerException unexpected) {
}

if (!checked) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new LoggingPermission("control", null));
}
}
}

/**
Expand Down Expand Up @@ -881,7 +838,7 @@ private static Class<?> tryLoad(String name, ClassLoader l) throws ClassNotFound
* @return any array of class loaders. Indexes may be null.
*/
private static ClassLoader[] getClassLoaders() {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader[]>() {
return runOrDoPrivileged(new PrivilegedAction<ClassLoader[]>() {

@SuppressWarnings("override") //JDK-6954234
public ClassLoader[] run() {
Expand All @@ -902,6 +859,60 @@ public ClassLoader[] run() {
});
}

/**
* Executes a PrivilegedAction without permissions then falling back to
* running with elevated permissions.
*
* Any unchecked exceptions from the action are passed through this API.
*
* @param <T> the action return type.
* @param a the PrivilegedAction object.
* @return the result.
* @throws NullPointerException if the given action is null.
* @throws UndeclaredThrowableException if a checked exception is thrown.
* @since Angus Mail 2.0.3
*/
static <T> T runOrDoPrivileged(final PrivilegedAction<T> a) {
if (a == null) {
throw new NullPointerException();
}

try {
return a.run();
} catch (SecurityException sandbox) {
return invokeAccessController(a);
}
}

/**
* Dynamic bind to the access controller for sandbox environments.
* Any unchecked exceptions from the action are passed through this API.
*
* @param <T> the return type of the action.
* @param a a non-null action.
* @return the result.
* @throws UndeclaredThrowableException if a checked exception is thrown.
* @since Angus Mail 2.0.3
*/
@SuppressWarnings("unchecked")
private static <T> T invokeAccessController(final PrivilegedAction<T> a) {
assert a != null;
try {
Class<?> c = Class.forName("java.security.AccessController");
return (T) c.getMethod("doPrivileged", PrivilegedAction.class)
.invoke((Object) null, a);
} catch (ReflectiveOperationException roe) {
Throwable cause = roe.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
} else {
throw new UndeclaredThrowableException(roe);
}
}
}

/**
* The namespace prefix to search LogManager and defaults.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Comparator;
Expand Down Expand Up @@ -4589,7 +4588,7 @@ private Object getAndSetContextClassLoader(final Object ccl) {
} else {
pa = new GetAndSetContext(ccl);
}
return AccessController.doPrivileged(pa);
return LogManagerProperties.runOrDoPrivileged(pa);
} catch (final SecurityException ignore) {
}
}
Expand Down

0 comments on commit 3471c2d

Please sign in to comment.