Feedback about an experiment to embed Python interpreter with FFI API

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Jan 4 11:09:37 UTC 2022


Hi Maxim
> The topic I want to talk about is a small flag `--enable-native-access=X`
> that looks harmless and useful at first glance. tl,dr: it is neither
> harmless nor useful. The reasoning that "user must opt-in to use unsafe
> APIs" implies that: (1) unsafe APIs are something illegal and should be
> avoided; (2) user has competencies to make such decisions; (3) user has
> other choice than use unsafe APIs. From my point of view, all three
> assumptions are false.

This has been discussed before (see [1]). My main suggestion here is to 
avoid over-generalization - e.g. speaking about "programs" and "users" 
in general is almost always incorrect and prone to simplifications and 
biases. Which programs? Which users? Note that there are actual 
instances of users who found the flag very useful (see [2]), which 
suggests that reality is probably more fragmented than what we'd like it 
to be.

Native access is not illegal, of course (though some of the wording 
around the exceptions thrown when the flag isn't there might be 
unfortunate and suggest that). But doing native access (of any kind) 
puts the application under much greater risk of misuse, as there is no 
way for the JVM to enforce safety for native code (e.g. module access 
boundaries). The fact that other mechanisms such as System.exit, or 
process builder exists by which bad things can happen and for which no 
protection exists is not, in itself, a justification as to why accessing 
native features of the Java API should not be protected.

When a developer uses JNI a number of things have to happen for that 
code to be in a workable state. When writing a program, native code has 
to be compiled - when executing, native libraries must be made 
available. These things all require command line flags (e.g. 
-Djava.library.path). There are, of course, frameworks that will 
side-step the library loading requirement by embedding the desired 
library somewhere in a dependency jar file, extract it into a temp 
folder, and then load the library directly from there, so that these 
libraries appear to work "seamlessly".

With the foreign API, when writing code there's no requirement to use 
GCC/clang. So that's one obstacle removed for the developer. And, when 
executing, assuming you are only using system libraries (e.g. posix, 
windows API), an application could just start calling native functions 
seamlessly (w/o any kind of workaround, unlike in JNI).

This means that it is now much easier for seemingly innocuous Java code 
to behave in unpredictable ways, hence the flag.


>
>
> The constructive part: what will be more helpful and much less 
> burdensome? I
> would say that much better alternative to a feature flag is just to 
> record
> all modules (or classes) which do native access, either by FFI or (in
> future) by JNI. Then just include list of such modules or classes in 
> crash
> dump. Straightforward: the VM has crashed, but classes A, B or C might be
> an issue since they used native access. Try to removing these classes 
> first
> before reporting any bugs. No deployment burden, no breaking of 
> compatibilty
> by introducing new restrictions and much more helpful crash dumps.


I think a better way, which we have thought about (but have not got to 
yet) is to think about native access as a permission that can be granted 
to a module to other modules. Let's say you have an application module 
App - and App depends on Foo and Bar, where Bar requires native access. 
If the required information is captured in the module system, then the 
application developer can simply grant native access to App, and App 
will be responsible to transfer the native access permission as required 
to the modules which requires it. I think such a solution would address 
most of the issues with the current flag (e.g. finding all the modules 
which need native access and granting them explicitly) and retain the 
spirit of capturing important permission information at the module-graph 
level (so that, if an application is executed w/o enough permission, it 
would fail to start early, rather than wait for the first unsafe method 
to be called).

Another option we considered was to turn native access errors into 
warnings if no --enable-native-access flag is specified (but retain 
existing behavior if the flag is specified). This would allow for a 
smoother migration, while allowing clients that want to be strict about 
native access (see [2]) to still function in the way they do today. To 
conclude, I think there are possible tweaks to make the flag more useful 
w/o merely turning it into a debugging feature as you propose.

Maurizio

[1] - 
https://mail.openjdk.java.net/pipermail/panama-dev/2021-September/015036.html
[2] - 
https://mail.openjdk.java.net/pipermail/panama-dev/2021-December/015981.html



More information about the panama-dev mailing list