Feedback about an experiment to embed Python interpreter with FFI API
Rémy Maucherat
remm at apache.org
Tue Jan 11 09:49:02 UTC 2022
On Mon, Jan 10, 2022 at 8:14 PM Maxim Karpov <me at m-k.mx> wrote:
>
> Hi Maurizio,
>
> Also I can't agree to claim that FFI allows you to easily abuse native
> API. There are usually very little things that you could do "easily" in
> native. For most of the use cases FFI without proper tooling is actually
> much more compilcated than JNI. FFI forces you to redo by yourself most
> of the work that will be otherwise done by gcc/clang such as parsing
> include files, finding function signatures and determining structure
> layouts. So you either do one-shot simple calls (like ioctl's on file
> descriptors) which I cannot call an "abuse" or setup a complex tooling
> to generate FFI wrappers. The only removed obstactle is, again,
> deployment one: you don't have to carry intermediate native library for
> every architecture you target to. Maybe it also has a performance
> benefits. But from development perspective it is no way easier (and
> harder, I would say) than JNI.
It's really not ok to write something such as: "The only removed
obstactle is, again, deployment one: you don't have to carry
intermediate native library for every architecture you target to".
The JNI wrapper that Tomcat uses for APR and OpenSSL has a huge
productization cost for us, is a constant source of troubles (aka
CVEs, due to static compilation on some platforms) and is problematic
for easily building container images. Also the wrapper has a healthy
amount of C code, which was a source of more CVEs. I understand you're
unhappy about that extra command line argument (the most annoying for
me is that previous JVMs don't know it and will refuse starting up, so
ensuring the argument is there when needed is annoying) but this
single benefit is much bigger than everything else combined.
Rémy
>
> To summarize, I don't see any real-world situation where permission
> mechanism could help, but I do see many situations where it is just a
> burden that you have to carry. Not to mention the fact that adoption
> ratio of module ecosystem is far from stellar.
>
> Best regards, Maxim.
>
> [1] -
> https://mail.openjdk.java.net/pipermail/panama-dev/2021-September/015036.html
>
>
> 04.01.2022 12:09, Maurizio Cimadamore writes:
> > 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