HHH-13324 Install the security manager check layer once and for all

If the security manager is defined later, the checks won't be installed.

The security manager should be defined when starting the JVM.
This commit is contained in:
Guillaume Smet 2019-03-20 12:10:34 +01:00
parent 3420ac9754
commit eca8816ec3
1 changed files with 70 additions and 37 deletions

View File

@ -57,11 +57,10 @@ public final class ByteBuddyState {
private final ByteBuddy byteBuddy;
private final ForDeclaredMethods getDeclaredMethodMemberSubstitution;
private final ForDeclaredMethods getMethodMemberSubstitution;
private final ProxyDefinitionHelpers proxyDefinitionHelpers;
private final ClassRewriter classRewriter;
/**
* It will be easier to maintain the cache and its state when it will no longer be static
* in Hibernate ORM 6+.
@ -78,12 +77,10 @@ public final class ByteBuddyState {
this.basicProxyCache = new TypeCache.WithInlineExpunction<TypeCache.SimpleKey>( TypeCache.Sort.WEAK );
if ( System.getSecurityManager() != null ) {
this.getDeclaredMethodMemberSubstitution = getDeclaredMethodMemberSubstitution();
this.getMethodMemberSubstitution = getMethodMemberSubstitution();
this.classRewriter = new SecurityManagerClassRewriter();
}
else {
this.getDeclaredMethodMemberSubstitution = null;
this.getMethodMemberSubstitution = null;
this.classRewriter = new StandardClassRewriter();
}
this.proxyDefinitionHelpers = new ProxyDefinitionHelpers();
@ -189,10 +186,7 @@ public final class ByteBuddyState {
}
private Unloaded<?> make(TypePool typePool, DynamicType.Builder<?> builder) {
if ( System.getSecurityManager() != null ) {
builder = builder.visit( getDeclaredMethodMemberSubstitution );
builder = builder.visit( getMethodMemberSubstitution );
}
classRewriter.installReflectionMethodVisitors( builder );
Unloaded<?> unloadedClass;
if ( typePool != null ) {
@ -211,36 +205,11 @@ public final class ByteBuddyState {
}
}
if ( System.getSecurityManager() != null ) {
// we authorize the proxy class to access the method lookup dispatcher
HibernateMethodLookupDispatcher.registerAuthorizedClass( unloadedClass.getTypeDescription().getName() );
}
classRewriter.registerAuthorizedClass( unloadedClass );
return unloadedClass;
}
private static ForDeclaredMethods getDeclaredMethodMemberSubstitution() {
// this should only be called if the security manager is enabled, thus the privileged calls
return MemberSubstitution.relaxed()
.method( ElementMatchers.is( AccessController.doPrivileged( new GetDeclaredMethodAction( Class.class,
"getDeclaredMethod", String.class, Class[].class ) ) ) )
.replaceWith(
AccessController.doPrivileged( new GetDeclaredMethodAction( HibernateMethodLookupDispatcher.class,
"getDeclaredMethod", Class.class, String.class, Class[].class ) ) )
.on( ElementMatchers.isTypeInitializer() );
}
private static ForDeclaredMethods getMethodMemberSubstitution() {
// this should only be called if the security manager is enabled, thus the privileged calls
return MemberSubstitution.relaxed()
.method( ElementMatchers.is( AccessController.doPrivileged( new GetDeclaredMethodAction( Class.class,
"getMethod", String.class, Class[].class ) ) ) )
.replaceWith(
AccessController.doPrivileged( new GetDeclaredMethodAction( HibernateMethodLookupDispatcher.class,
"getMethod", Class.class, String.class, Class[].class ) ) )
.on( ElementMatchers.isTypeInitializer() );
}
private static class GetDeclaredMethodAction implements PrivilegedAction<Method> {
private final Class<?> clazz;
private final String methodName;
@ -330,4 +299,68 @@ public final class ByteBuddyState {
return interceptorFieldAccessor;
}
}
private interface ClassRewriter {
void installReflectionMethodVisitors(DynamicType.Builder<?> builder);
void registerAuthorizedClass(Unloaded<?> unloadedClass);
}
private static class SecurityManagerClassRewriter implements ClassRewriter {
private final ForDeclaredMethods getDeclaredMethodMemberSubstitution;
private final ForDeclaredMethods getMethodMemberSubstitution;
private SecurityManagerClassRewriter() {
this.getDeclaredMethodMemberSubstitution = getDeclaredMethodMemberSubstitution();
this.getMethodMemberSubstitution = getMethodMemberSubstitution();
}
@Override
public void installReflectionMethodVisitors(DynamicType.Builder<?> builder) {
builder = builder.visit( getDeclaredMethodMemberSubstitution );
builder = builder.visit( getMethodMemberSubstitution );
}
@Override
public void registerAuthorizedClass(Unloaded<?> unloadedClass) {
// we authorize the proxy class to access the method lookup dispatcher
HibernateMethodLookupDispatcher.registerAuthorizedClass( unloadedClass.getTypeDescription().getName() );
}
private static ForDeclaredMethods getDeclaredMethodMemberSubstitution() {
// this should only be called if the security manager is enabled, thus the privileged calls
return MemberSubstitution.relaxed()
.method( ElementMatchers.is( AccessController.doPrivileged( new GetDeclaredMethodAction( Class.class,
"getDeclaredMethod", String.class, Class[].class ) ) ) )
.replaceWith(
AccessController.doPrivileged( new GetDeclaredMethodAction( HibernateMethodLookupDispatcher.class,
"getDeclaredMethod", Class.class, String.class, Class[].class ) ) )
.on( ElementMatchers.isTypeInitializer() );
}
private static ForDeclaredMethods getMethodMemberSubstitution() {
// this should only be called if the security manager is enabled, thus the privileged calls
return MemberSubstitution.relaxed()
.method( ElementMatchers.is( AccessController.doPrivileged( new GetDeclaredMethodAction( Class.class,
"getMethod", String.class, Class[].class ) ) ) )
.replaceWith(
AccessController.doPrivileged( new GetDeclaredMethodAction( HibernateMethodLookupDispatcher.class,
"getMethod", Class.class, String.class, Class[].class ) ) )
.on( ElementMatchers.isTypeInitializer() );
}
}
private static class StandardClassRewriter implements ClassRewriter {
@Override
public void installReflectionMethodVisitors(DynamicType.Builder<?> builder) {
// do nothing
}
@Override
public void registerAuthorizedClass(Unloaded<?> unloadedClass) {
// do nothing
}
}
}