Minor thoughts (Re: [External] : Re: JEP draft: Prepare to Restrict The Use of JNI

Rony G. Flatscher Rony.Flatscher at wu.ac.at
Thu Aug 31 13:03:28 UTC 2023


Hi Ron,

thank you for your comments. One thing, please do not take any of my comments personal if I try to 
point out something that I regard to be possibly oversights and shortcomings, my comments are meant 
constructively.

It is clear that you are an expert and have been working in this area intensively. However, it may 
be the case that you and your peers are focused on pure Java applications that get their own 
tailored JRE exploiting modules with jlink and or tooling that does all the "dirty" work for you. In 
such a world it may be the case that inventing new switches is not regarded to be a problem, if the 
"user" is the application developer from whom you expect to have the same knowledge, overview and 
commandment of all switches and dependencies that each new version of Java brings along. (I doubt 
that that can be really expected.)

There are quite many Java deployments that are important for non-Java applications taking advantage 
of the JRE infrastructure, taking advantage of the platform independent functionality of the JRE 
classes and optionally add additional Java class libraries like jsoup. In such a world the intimate 
knowledge of the latest Java version and the module system is not relevant. :) What counts is what 
public Java classes can be loaded and exploited.

Add to that the fact that in the real world applications may use totally outdated versions of Java 
as long as possible. I know of deployments of Java 6 and 7 still in use which is the reason why I 
still maintain a Java bridge with the Java 6 baseline, believe it or not.

In such a world updating to a new version of Java that starts to warn and potentially terrify the 
end-users that something about using Java has become dangerous all of a sudden is counterproductive 
to say the least. End-users, application users lack the understanding, they have not followed 
discussions like this one, have no knowledge of JEPs, they are usually helpless then, but feeling 
more and more insecure about using Java at all.

Expecting - what is easy for guys like you (or us) - to add just another "easy flag" that removes 
such terrifying messages is just not realistic, they are not able to do so, believe it or not. They 
get scared and for them it is obviously Java's fault that it gets all of a sudden dangerous, 
insecure as even Java itself warns about it!

Take the following ooRexx program as an example (yes, it uses JRE, any actual version of Java will 
do, e.g. Java 8, 17, 22, ...):

    say .java.lang.System~getProperty("java.version")

    ::requires "BSF.CLS"  -- get the ooRexx-Java bridge

The output of running the above program may be something like (depending on the JREs in use):

    1.8.0_362
    17.0.6
    18.0.1.1

Any of my students is able to create such programs that exploit Java classes in the current JRE 
(including exploiting JavaFX by the way). Change JAVA_HOME and you change the JRE in use and the 
program still works.

If running such a program on a new Java version all of a sudden yields a security warning out of the 
blue telling them that what they do is dangerous, unsecure etc. will scare them to death and 
eventually scare them away from Java, making them turn to other programming runtime environments 
that do not scare them.

These students BTW are business administration students, so please do not expect that anything what 
is easy for this group is easy for them at all, rather expect that what is easy for this group is 
simply impossible for them!


On 30.08.2023 20:08, Ron Pressler wrote:
>> On 30 Aug 2023, at 17:21, Rony G. Flatscher<Rony.Flatscher at wu.ac.at>  wrote:
> Hi.
>
>> The road to hell is paved with good intentions ...
> Every Java library requires adding a token to the command line; what we’re talking about here is adding another one for the small minority of libraries that use native code.
>
> In fact, the command line work that’s required has barely changed. If you’re using the classpath, then most applications typically mention each and every JAR individually; if any of them requires native access you only need to add --enable-native-access=ALL-UNNAMED. If, on the other hand, you’re using the module path, then normally you’re only providing a single directory, and now you’ll also have to list every module that requires native access, and it’s still *fewer* tokens on the command line than Java applications put there ten years ago.
>
> So we can talk about the merits of this minor inconvenience, but merited or not — it’s not something that can lead to any hell.

This depends on the "user" who uses/exploits Java without the expert knowledge you have. What is 
easy for you (or us) may be impossible, cumbersome for others. The message these users get is more 
than scary if Java starts to warn (or even aborts with an error) from using Java!

>> A few minor thoughts:
>>      • Java needs JNI itself: so how can the "user" be warned from using Java as this is considered to be potentially dangerous by the Java developers themselves?
>> (And what can be done to warn a "user" from using operating system features? Should Java warn the "user" that potentially dangerous native code gets employed by Java whenever the operating system gets accessed for one reason or another?)
> I’m afraid there’s been some confusion about who the user is. The user we’re referring to in the JEP is the application author. The application’s end user need not add any flags, see any flags, or even be aware they’re running an application written in Java. All the flags we’re discussing are internal to the application, and can be collected in the usual way in configuration @files or with jlink. The application’s author has a choice of whether or not to use a library that requires certain special powers, in this case — running native code.
>
> The application’s author chooses what launcher to use, and that launcher can grant native access privileges to any library that the application author chooses. If someone uses the launcher that comes with the JDK it is preconfigured with such permissions for the JDK’s modules.

In my use case the "application author" are students who use the current JRE and have no clues about 
the Java module system, the latest JEPs and the latest and greatest features of OpenJDK/Java let 
alone the latest invented switches.

If the "user" is the "application author" who is one who creates a pure Java application and 
controls its setup, the JRE to use, why is it then necessary to warn Java "application authors" 
about something that may not be even true, that the JNI module in use would be dangerous and/or a 
security risk?

However, if it is intended to make users of JREs (standard ones or jlink'ed ones) aware that modules 
use JNI without reporting that usage by warning them, then it would be fine as long as no warning 
occurs when modules report the usage of JNI modules in their module-info. This scenario is then a 
constructive one, issuing the warnings only, if JNI usage is not communicated explicitly.


>>      • Possible dangerous or fatal errors in native code do not mean that these errors exist in reality at all, i.e. in deployed JNI modules that get tested and deployed.
>> This is a bit along the line that a knife can be dangerous as it can be used to kill a person, yet, knives in the world do not get used to kill people: the good intent is to make the world safer, so we prohibit knives or only allow their use, if the user keys in the flag "--knives-can-kill-persons" and then the storage box opens to release the knife such that one can finally cut the steak.
>> (Just because something can be used dangerously does not mean that it will be used that way and do harm; any acknowledgement of potential danger does not make the danger go away nor does the warning help to circumvent the potential danger.)
> Sure, which is why we’re not discouraging the use of native code, just asking the application’s author to acknowledge that they know there are knives in play.

Why is that important? For whom is this important?

People know that one can kill with a knife, why would you want to warn everyone forcefully that 
knives can kill people, if the normal, expected usage of a knife is for cutting meat and vegetables?

(If an "application author" uses modules from sources she or he does not trust, then such a human 
would be expected to check thoroughly such modules, if they should be used nevertheless, wouldn't 
she or he?)


>>      • Just pointing out that erroneously implemented JNI modules can be harmful is enough and has been evident since JNI exists, so what has changed all of a sudden?
> The linked JEP explains that in the “Why Now” section. In short: because the JDK is now changing faster than it ever did before, because more and more of it is being written in Java, and because the security threat landscape has changed.

Yes, I have read that JEP and it does not add a real reason IMHO that justifies a forceful, 
unnecessary warning potentially scaring users of Java infrastructures away from using Java.

Maybe, can you just name one convincing reason (from the JEP) that justifies a forceful warning 
about using JNI that would really make a difference to the current situation in which everyone 
("application developers") realize what JNI is about and what it allows for? And that justifies to 
have end-users, application users be confronted with such warnings?

>>      • Deployment of Java: there seems to be the wrong assumption among some developers that Java is not being used as a JRE (non-JRE bubble?) which is simply wrong. What should applications do in a scenario in which the JVM gets dynamically loaded via JNI to then interact with the JRE? Is that considered to be dangerous such that it needs to be made seen by the "user" each time this demand loading of the JVM happens as otherwise the "user" does not realize that theoretically a potential danger exists (and if so for whom)?
> I’m not sure what you mean by JRE (the JRE is something that no longer exists),

This is simply not true and it is a little bit frightening that you seem to believe what you write 
(and probably your peers as well)!


> but the JEP addresses the use of the invocation API. Obviously, whatever launcher is used is controlled by the application author, who can decide who can do what.

This is what is interesting for me: you (and quite a few people from the Java-application-only 
"bubble") seem to only see this kind of Java usage, namely the creation of pure Java applications 
(with customizable installers easying installation). Although, of course, these endeavors are 
applauded and very important, it is by no means the only important usage of Java!

There are plenty of non-Java applications that just use the JRE! JAVA_HOME is your friend to switch 
among the different JREs. JRE are alive and live well, thank you! :)

End user kind of people who after updating to the latest version of Java may be confronted with 
warnings of using Java as it may be dangerous will be scared!

Seriously, it is a little bit frightening to learn that core Java developers think that the only 
usage of Java is in creating pure Java applications, ignoring a simple fact: the JRE allows for 
creating operating system independent applications, something no other infrastructure allows for in 
a comparable manner! One can even create complex JavaFX GUI applications from the available JRE and 
have them run unchanged on Windows, macOS and Linux, whether the operating system owners and 
developers like it or not. [And for that reason alone it is damaging that the JavaFX modules are not 
contained in the standard OpenJDK. Server/daemon Java apps would be able thanks to the module system 
to exclude the four JavaFX modules when not needed, whereas JRE-kind of users would have immediate 
access to JavaFX with a plain JDK installation.]

JRE gets employed heavily in non-Java applications whether one is aware of this fact or not.

>>      • Who is really the "user" who gets addressed here? (How stupid is this particular "user" regarded to be?)
> The application author. The assumption is that they’ve somehow assembled a dependency graph and may not be aware whether any of the transitive dependencies have superpowers that may override the integrity guarantee that we’d like the JDK to make by default.

For an application author to learn about JNI being used in some of the modules it would be 
sufficient to get a warning/information when running a tool that would tell her or him. Such an 
application author would be able to learn from module-info entries (maybe via a tool) which modules 
document their use of JNI.

In such a scenario it then would be probably acceptable that in the case that if modules at runtime 
use JNI without having this usage documented in their module-info that then a warning gets issued to 
make the application author aware of it (and only if the module is at least at the class file level 
of the Java version that introduced this feature and should have been aware of this newly introduced 
documentation obligation).

>>      • Why is it not enough to simply record the fact that JNI gets employed explicitly in module-info? As has been mentioned a few times this would allow for appropriate analysis, if need be? (It also might suffice the intentions of the JEP in that the warnings get issued only if the fact that JNI gets employed in a module is not reported in its module-info.)
> Because, as the linked JEP explains (https://openjdk.org/jeps/8305968) the goal is to gain the permission of the application’s author.

Well, if an application author is using modules that document JNI usage in their module-info, then 
that permission is implicitly granted already. There is no need to issue warnings that scare the 
users of such applications.

Also, an application author is not forced to grant any of the JDK modules explicitly the permission 
to employ JNI, why not? (Of course because she or he trusts the authors of JDK. Such an application 
author would trust the authors of the modules she or he employs in his application, so why come up 
with a warning for those only?)

> A library cannot decide grant itself superpowers that could change any of the integrity guarantees made by the JDK. The application has to grant that permission to the library.

No, not the application the "application author" as you mentioned.

What integrity guarantees does the JDK give that a JNI author would want to intentionally and 
forcefully break with the intent to harm the JDK? (And if a JNI author would do that intentionally 
to harm the JDK then she or he can be traced down and made accountable for it.)

How can an "application author" assess what a JNI module does in detail, whether it is an 
implementation that breaks "integrity guarantees made by the JDK" in a harmful way? How can an 
"application author" grant anything about something she or he has no clues about?

The responsibility of JNI authors breaking what the JDK guarantees in any harmful manner lies 
clearly in the hands of the JNI authors, not the "application author" who usually has no knowledge 
of the black box she or he is using in form of JNI.

---

What may make sense is to make it explicitly known for a module whether the module employs JNI via 
its module-info. This way tools can create reports about the usage of JNI and "application authors" 
learn (maybe for the first time) about that fact.

If a module employs JNI without reporting it that may be regarded as not behaving like a good 
citizen in the modular Java land and hence reporting the fact that module xyz employs JNI without 
telling in its module-info at runtime. The resolution should be that the module author should 
correct module-info to incorporate that information.

---rony

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/jdk-dev/attachments/20230831/1c2283fc/attachment-0001.htm>


More information about the jdk-dev mailing list