Skip to content

Commit

Permalink
Merged branch 'jetty-11.0.x' into 'jetty-12.0.x'.
Browse files Browse the repository at this point in the history
Signed-off-by: Simone Bordet <[email protected]>
  • Loading branch information
sbordet committed Apr 6, 2023
2 parents bd59b40 + 3aaaeb2 commit 110e092
Show file tree
Hide file tree
Showing 11 changed files with 232 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Locale;
import java.util.Properties;
Expand Down Expand Up @@ -161,29 +159,26 @@ public TimeZone getTimeZone(String key)
*/
public JettyLoggerConfiguration load(ClassLoader loader)
{
return AccessController.doPrivileged((PrivilegedAction<JettyLoggerConfiguration>)() ->
// First see if the jetty-logging.properties object exists in the classpath.
// * This is an optional feature used by embedded mode use, and test cases to allow for early
// * configuration of the Log class in situations where access to the System.properties are
// * either too late or just impossible.
load(readProperties(loader, "jetty-logging.properties"));

// Next see if an OS specific jetty-logging.properties object exists in the classpath.
// This really for setting up test specific logging behavior based on OS.
String osName = System.getProperty("os.name");
if (osName != null && osName.length() > 0)
{
// First see if the jetty-logging.properties object exists in the classpath.
// * This is an optional feature used by embedded mode use, and test cases to allow for early
// * configuration of the Log class in situations where access to the System.properties are
// * either too late or just impossible.
load(readProperties(loader, "jetty-logging.properties"));

// Next see if an OS specific jetty-logging.properties object exists in the classpath.
// This really for setting up test specific logging behavior based on OS.
String osName = System.getProperty("os.name");
if (osName != null && osName.length() > 0)
{
// NOTE: cannot use jetty-util's StringUtil.replace() as it may initialize logging itself.
osName = osName.toLowerCase(Locale.ENGLISH).replace(' ', '-');
load(readProperties(loader, "jetty-logging-" + osName + ".properties"));
}
// NOTE: cannot use jetty-util's StringUtil.replace() as it may initialize logging itself.
osName = osName.toLowerCase(Locale.ENGLISH).replace(' ', '-');
load(readProperties(loader, "jetty-logging-" + osName + ".properties"));
}

// Now load the System.properties as-is into the properties,
// these values will override any key conflicts in properties.
load(System.getProperties());
return this;
});
// Now load the System.properties as-is into the properties,
// these values will override any key conflicts in properties.
load(System.getProperties());
return this;
}

public String getString(String key, String defValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@

package org.eclipse.jetty.util;

import java.security.AccessController;
import java.security.PrivilegedAction;

/**
* MemoryUtils provides an abstraction over memory properties and operations.
*/
Expand All @@ -25,18 +22,11 @@ public class MemoryUtils

static
{
final int defaultValue = 64;
int defaultValue = 64;
int value = defaultValue;
try
{
value = Integer.parseInt(AccessController.doPrivileged(new PrivilegedAction<String>()
{
@Override
public String run()
{
return System.getProperty("org.eclipse.jetty.util.cacheLineBytes", String.valueOf(defaultValue));
}
}));
value = Integer.parseInt(System.getProperty("org.eclipse.jetty.util.cacheLineBytes", String.valueOf(defaultValue)));
}
catch (Exception ignored)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -693,7 +691,7 @@ public static URI getCodeSourceLocation(Class<?> clazz)
{
try
{
ProtectionDomain domain = AccessController.doPrivileged((PrivilegedAction<ProtectionDomain>)() -> clazz.getProtectionDomain());
ProtectionDomain domain = clazz.getProtectionDomain();
if (domain != null)
{
CodeSource source = domain.getCodeSource();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.util.security;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.security.Permission;
import java.security.PrivilegedAction;

/**
* <p>Collections of utility methods to deal with the scheduled removal
* of the security classes defined by <a href="https://openjdk.org/jeps/411">JEP 411</a>.</p>
*/
public class SecurityUtils
{
private static final MethodHandle doPrivileged = lookup();

private static MethodHandle lookup()
{
try
{
// Use reflection to work with Java versions that have and don't have AccessController.
Class<?> klass = ClassLoader.getPlatformClassLoader().loadClass("java.security.AccessController");
MethodHandles.Lookup lookup = MethodHandles.lookup();
return lookup.findStatic(klass, "doPrivileged", MethodType.methodType(Object.class, PrivilegedAction.class));
}
catch (Throwable x)
{
return null;
}
}

/**
* @return the current security manager, if available
*/
public static Object getSecurityManager()
{
try
{
// Use reflection to work with Java versions that have and don't have SecurityManager.
return System.class.getMethod("getSecurityManager").invoke(null);
}
catch (Throwable ignored)
{
return null;
}
}

/**
* <p>Checks the given permission, if the {@link #getSecurityManager() security manager}
* is set.</p>
*
* @param permission the permission to check
* @throws SecurityException if the permission check fails
*/
public static void checkPermission(Permission permission) throws SecurityException
{
Object securityManager = SecurityUtils.getSecurityManager();
if (securityManager == null)
return;
try
{
securityManager.getClass().getMethod("checkPermission")
.invoke(securityManager, permission);
}
catch (SecurityException x)
{
throw x;
}
catch (Throwable ignored)
{
}
}

/**
* <p>Runs the given action with the calling context restricted
* to just the calling frame, not all the frames in the stack.</p>
*
* @param action the action to run
* @return the result of running the action
* @param <T> the type of the result
*/
public static <T> T doPrivileged(PrivilegedAction<T> action)
{
// Keep this method short and inlineable.
MethodHandle methodHandle = doPrivileged;
if (methodHandle == null)
return action.run();
return doPrivileged(methodHandle, action);
}

@SuppressWarnings("unchecked")
private static <T> T doPrivileged(MethodHandle doPrivileged, PrivilegedAction<T> action)
{
try
{
return (T)doPrivileged.invoke(action);
}
catch (RuntimeException | Error x)
{
throw x;
}
catch (Throwable x)
{
throw new RuntimeException(x);
}
}

private SecurityUtils()
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,46 @@

package org.eclipse.jetty.util.thread;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.function.Supplier;

import org.eclipse.jetty.util.security.SecurityUtils;

/**
* Convenience class to ensure that a new Thread is created
* inside a privileged block.
*
* This prevents the Thread constructor
* from pinning the caller's context classloader. This happens
* when the Thread constructor takes a snapshot of the current
* calling context - which contains ProtectionDomains that may
* reference the context classloader - and remembers it for the
* lifetime of the Thread.
* <p>Convenience {@link Thread} factory that ensure threads are
* created without referencing any web application {@link ClassLoader}.</p>
* <p>Up to Java 17, the {@code Thread} constructor was taking a
* snapshot of the calling context, which may contain a {@link ProtectionDomain}
* that references a web application {@code ClassLoader}
* (for example if the creation of the {@code Thread} was triggered
* by some operation performed by the web application).
* The {@code Thread} might then be pooled and prevent the
* web application {@code ClassLoader} to be garbage collected
* when the web application is undeployed.
* For this reason, {@code Thread}s must be created in a privileged
* action, which restricts the calling context to just the caller
* frame, not all the frames in the stack.</p>
* <p>Since Java 18 and the removal of the Java security manager
* and related classes by JEP 411, {@code Thread}s do not retain
* the calling context, so there is no need to create them in a
* privileged action.</p>
*/
class PrivilegedThreadFactory
{
/**
* Use a Supplier to make a new thread, calling it within
* a privileged block to prevent classloader pinning.
*
* @param newThreadSupplier a Supplier to create a fresh thread
* @return a new thread, protected from classloader pinning.
* <p>Creates a new {@link Thread} from the given {@link Supplier},
* without retaining the calling context.</p>
*
* @param creator the action that creates the {@link Thread}
* @return a new {@link Thread} without retaining the calling context
*/
static <T extends Thread> T newThread(Supplier<T> newThreadSupplier)
static <T extends Thread> T newThread(PrivilegedAction<T> creator)
{
return SecurityUtils.doPrivileged(creator);
}

private PrivilegedThreadFactory()
{
return AccessController.doPrivileged(new PrivilegedAction<T>()
{
@Override
public T run()
{
return newThreadSupplier.get();
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,11 @@
public class ShutdownThread extends Thread
{
private static final Logger LOG = LoggerFactory.getLogger(ShutdownThread.class);
private static final ShutdownThread _thread = PrivilegedThreadFactory.newThread(() ->
{
return new ShutdownThread();
});
private static final ShutdownThread _thread = PrivilegedThreadFactory.newThread(ShutdownThread::new);

private final AutoLock _lock = new AutoLock();
private boolean _hooked;
private final List<LifeCycle> _lifeCycles = new CopyOnWriteArrayList<LifeCycle>();
private final List<LifeCycle> _lifeCycles = new CopyOnWriteArrayList<>();

/**
* Default constructor for the singleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ public void configure(Object obj, XmlParser.Node cfg, int i) throws Exception
}
catch (Exception e)
{
LOG.warn("Config error {} at {} in {}", e.toString(), node, _configuration);
LOG.warn("Config error {} at {} in {}", e, node, _configuration);
throw e;
}
}
Expand Down
Loading

0 comments on commit 110e092

Please sign in to comment.