RFE: support safely wrapping restricted FFM calls
Rob Spoor
openjdk at icemanx.nl
Thu Nov 16 19:20:45 UTC 2023
On 16/11/2023 18:15, Maurizio Cimadamore wrote:
>
> On 16/11/2023 16:54, Rob Spoor wrote:
>> Hi Maurizio,
>>
>> I don't think you understand what my module is doing. For instance,
>> it's not specifying the downcall method handles themselves, it's just
>> making it easy to define them. Maybe a small example would show what
>> I'm doing.
>>
>> Consider the following partial interface from JNA:
>>
>> public interface Kernel32 extends StdCallLibrary, WinNT, Wincon {
>>
>> /** The instance. */
>> Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class,
>> W32APIOptions.DEFAULT_OPTIONS);
>>
>> int GetLastError();
>> }
>>
>> What JNA is doing is creating an implementation based on this
>> interface that delegates to the native kernel32 library. This is all
>> done through the Native.load method.
>
>>
>> What I'm building is not an FFM-backed version of Kernel32 interface,
>> but something like Native.load. In other words, my module will call
>> the restricted Linker.downcallHandle method. Somebody that then wants
>> to build a Kernel32 interface would not directly call any restricted
>> methods. As a result, their code would not need to have native access
>> enabled because they would get it through my module. That's something
>> I want to protect against, because it's definitely not safe to just
>> grant any access. (In fact, some incorrectly written test code has
>> already crashed my JVM.) While my module will definitely need to have
>> native access enabled, I'd like to require that the module with such a
>> Kernel32 interface needs to have native access enabled as well.
>
> I believe I understood what you were attempting to do :-)
>
> And I still stand by what I said yesterday - a client will need to trust
> your library (and a flag is required there) to generate the correct
> stuff when it gives you an interface (which your framework will generate
> an implementation of using some black magic). Whether the client itself
> is enabled to do native access or not is irrelevant, because unsafe
> operation will not occur on the client module, they will occur on the
> module of your framework. The crucial part here is that for an
> application to be able to use your framework _some_ form of
> `--enable-native-access` will be required (so, the command line will
> give away the fact that the application will require some form of unsafe
> access somewhere).
>
I understand that my module needs to be included in
`--enable-native-access` (or programmatically), I'm just trying to force
direct callers of my own restricted methods to be included as well.
Your answer below makes it clear this isn't something that can (easily)
be made public. That means I'll have to perform my own security checks.
Using a stack walk or MethodHandle.Lookup to find the caller class
provides me with an alternative to Reflection.getCallerClass(), which
indeed cannot be called directly by any non-JDK code.
Module.isNativeAccessEnabled() allows me to check if a module is
included in the JDK's --enable-native-access flag (or its alternatives),
but I can't use the JDK's handling if a module doesn't have access.
As for documentation, I'll have to find another way - either a custom
@Documented annotation, or simply Javadoc text.
Thanks for the time spent on this discussion :)
Rob
>>
>> The idea of using a MethodHandles.Lookup instance looks interesting,
>> but it would only replace the use of the StackWalker. I still would
>> need to print a message or throw an exception from my module instead
>> of reusing the code from Module.ensureNativeAccess, which makes my
>> module either stricter than the FFM API right now, or less strict in
>> the future when the FFM API starts throwing exceptions.
>
> What you are asking boils down to: how can I define _custom_ restricted
> methods?
>
> The answer is you can't. Restricted methods are a feature of the Java SE
> API (pretty much like preview methods). And I believe this is likely to
> remain that way: as you noticed, emulating a restricted method from
> custom code requires a stackwalk, which we avoid using caller sensitive
> methods (which are also not available outside the JDK).
>
> Maurizio
>
>
More information about the core-libs-dev
mailing list