ByteBuddy rebasing, synthetic types and OSGi

爱⌒轻易说出口 提交于 2019-12-24 15:04:21

问题


I have the following interceptor developed for byte-buddy:

public class SecurityInterceptor() {

    @RuntimeType
    public static Object intercept(
        @SuperCall Callable<Object> supercall, 
        @This Object target, 
        @Origin Method method, 
        @AllArguments Object[] args) {  

        // Check args and annotations ...       

        Object obj = supercall.call();

        // Post-process obj content ...
    }
}

The interceptor is registered as follows:

Unloaded<Object> unloaded = new ByteBuddy()
    .rebase(type, classFileLocator)
    .method(ElementMatchers.isAnnotatedWith(Secured.class))
    .intercept(MethodDelegation.to(SecurityInterceptor.class))
    .make();
wovenClass.setBytes(unloaded.getBytes());

and this happens inside a WeavingHook in OSGi. The problem is that rebasing with @SuperCall alters the original code as such

public User getUser(final String s) throws Exception {
    return SecurityInterceptor.intercept((Callable)new UsersServiceImpl$auxiliary$xhbBRSr4(this, s), 
        (Object)this, UsersServiceImpl.cachedValue$nlgHrwy3$sn5qca3, new Object[] { s });
}

where UsersServiceImpl$auxiliary$xhbBRSr4 is a synthetic class that is generated by byte-buddy:

class UsersServiceImpl$auxiliary$xhbBRSr4 implements Runnable, Callable
{
    private UsersServiceImpl argument0;
    private String argument1;

    @Override
    public Object call() throws Exception {
        return this.argument0.getUser$original$6ve6X5gN$accessor$nlgHrwy3(this.argument1);
    }

    @Override
    public void run() {
        this.argument0.getUser$original$6ve6X5gN$accessor$nlgHrwy3(this.argument1);
    }

    UsersServiceImpl$auxiliary$xhbBRSr4(final UsersServiceImpl argument0, final String argument2) {
        this.argument0 = argument0;
        this.argument1 = argument2;
    }
}

where UsersServiceImpl is the class being weaved.

So what I need is to add all these synthetic classes in the class space of the UsersServiceImpl's bundle (or in general make synthetic classes "accessible" from that bundle). Is this possible?


回答1:


One trick you can apply is to not use rebasing but to create your own class loaders during the loading of a proxy where the new class (and all of its synthetic classes) are loaded in a class loader with multiple parents:

dynamicType
  .make()
  .load(new MultipleParentClassLoader.Builder(false)
    .append(type.getClassLoader(), SecurityInterceptor.class.getClassLoader())
    .build());

The proxy class will now be loaded in a new class loader that has multiple parents; the OSGi loader that shields any other types not normally known to a bundle and the security interceptor's class loader that is yours. The multiple parent class loader will however request any type from both class loaders, thus making both visible for the proxy class.

Notice the false argument to the builder's constructor. This unseals the class loader making it potentially vulnerable for injection of additional classes. I don't assume that your proxy classes are sensitive to reflection attacks but it is something to consider. You can remove the flag and pay slightly higher costs for class generation.




回答2:


In the end I used a different approach:

Unloaded<Object> unloaded = new ByteBuddy()
    .redefine(type, classFileLocator)
    .visit(Advice.to(SecurityAdvice.class)
            .on(ElementMatchers.isAnnotatedWith(Secured.class)))
    .make();

with

public class SecurityAdvice {
    @Advice.OnMethodEnter
    private static void enter(@Advice.AllArguments Object[] args) {
        //...
    }

    @Advice.OnMethodExit
    private static void exit(@Advice.Return(typing = Typing.DYNAMIC) Object value) {
       //...
    }
}

this only alters the original class's bytecode without introducing additional synthetic types.



来源:https://stackoverflow.com/questions/58388214/bytebuddy-rebasing-synthetic-types-and-osgi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!