Fix proposal for bug JDK-8221642
Mandy Chung
mandy.chung at oracle.com
Fri Jan 28 01:54:19 UTC 2022
I see how NPE is thrown (from `AccessibleObject::setAccessible` and
`trySetAccessible`). The proper fix should follow the rule as the
access check that it can set the accessible flag only on public members
of a public type that is exported unconditionally.
The fix is straight forward but involves spec change. I'll post PR soon.
Mandy
On 1/27/22 8:45 AM, Mandy Chung wrote:
> Hi Andreas,
>
> What methods are you calling that throws NPE? Do you have the stack
> trace to share?
>
> The spec of AccessibleObject was updated for JDK-8221530 if there is
> no caller frame when calling from JNI:
>
> "The check when invoked by JNI code with no Java class on the stack
> only succeeds if the member and the declaring class are public, and
> the class is in a package that is exported to all modules."
>
> I think AccessibleObject::canAccess, setAccessible, trySetAccessible
> should follow the same rule.
>
> Mandy
>
> On 1/27/22 2:19 AM, Andreas Rosenberg wrote:
>> Hi,
>>
>> this is my first posting regarding to JDK contribution, so this may be the wrong place to ask.
>> Please point me in the right direction in this case.
>>
>> We are using Java rather heavily via JNI on a custom application. For a long time we did stick to JRE 1.8
>> for various reasons. My task is to plan an upgrade to a more recent JDK version and while doing some
>> test I encountered bugs related to this: JDK-8227491 (JNI - caller sensitive methods).
>>
>> We are parsing Java class files to auto gen the JNI code for our application, and are also using reflection.
>> The workaround given is clumsy and needs manual intervention, so I was looking for a more elegant solution.
>>
>> The problem is: a caller sensitive method wants to determine the caller class for security checks. In case of
>> a JNI call no Java stack frame exists, so the JVM function "jclass JVM_GetCallerClass(JNIEnv* env)" answers NULL
>> which leads to NPEs.
>>
>> My idea is this: create an internal proxy class inside "java.base" that reflects this case
>> (e.g. "java.lang.NativeCall" or "java.lang.NativeCode").
>> This class is final and implements nothing.
>>
>> Then "jclass JVM_GetCallerClass(JNIEnv* env)" (jvm.cpp) could be modified and instead of answering NULL
>> in case of a JNI call, it should do this to answer the class proxy:
>>
>> return JVM_FindClassFromBootLoader(env, "java/lang/NativeCall");
>>
>> This would have the following advantages:
>> - JNI code could again simply call "caller sensitive methods" without the need to make an additional wrapper class
>> - it would be more a expressive way on the Java side to detect "the callee is native code" than checking for null
>> - it would fit better into the framework
>>
>> I already applied this fix on my own copy of the JDK 17 sources and it works pretty well for us.
>>
>> As there are probably security considerations involved, advice from experts is required.
>> But from my understanding the Java security model is designed for the main app being writing in Java.
>> In this case there are always Java stacks frames available as parents for caller sensitive methods, so
>> the proposed fix would not affect the behavior. This assumes that "GetCallerClass" only answers
>> NULL for the JNI case. This needs verification.
>>
>> If the main app is native code which uses JNI, the Java security model can only affect the Java part and
>> as soon as an additional Java stack frame has been generated a regular Java class will be found and
>> the "standard behavior" should apply again.
>>
>> Comments appreciated.
>>
>> It this fix looks reasonable, what are the steps to get it implemented and integrated into the official
>> source tree?
>>
>> Best regards,
>> Andy
>>
>>
More information about the core-libs-dev
mailing list