JEP draft: Prepare to Restrict The Use of JNI

Ron Pressler ron.pressler at oracle.com
Tue Aug 29 13:18:14 UTC 2023



> On 28 Aug 2023, at 22:24, Ron Pressler <ron.pressler at oracle.com> wrote:
> 
> 
> 
>> On 27 Aug 2023, at 12:39, Remi Forax <forax at univ-mlv.fr> wrote:
>> 
>> 
>> I disagree.
>> I do not like the fact that you are promoting the idea that the JDK code is not superior to other libraries of the ecosystem.
>> Also the Java ecosystem is massive so even if it is true that the majority of applications do not do native call apart the JNI calls of the JDK, there are a lot of middleware libraries that do native access, so there are a lot of applications built on top of those middlewares that do native access. Those applications are not unsafe.  
>> 
>> Let's take an example, Netty [1], the server and all it's protocol/transport supports are using JNI.
>> Netty acts as a middleware, encapsulating unsafe JNI calls in a safe way. For example, you can use OpenSSL for HTTPv2, something the JDK does not do.
>> 
>> Why Java SE should consider the JDK code is more safe than the Netty code, given that both are using JNI ?
>> 
>> Why the user of one Netty libraries or one of the libraries that is using Netty libraries (for example, a JDBC driver [2]) need to be aware that Netty is using JNI ?
>> 
>> If you think that Java has an integrity problem, I would prefer a solution including the Java ecosystem than a strawman solution where the JDK is good and everything else is bad. And don't get me wrong, I have no problem with having more protection to the JDK code (note JDK) but, this is not what we are discussing here.
> 
> 
> What’s different about the JDK is not its use as a library, but the fact that when you run the `java` launcher, you are running an *executable* given to you by the JDK. The launcher distributed with the JDK knows about the JDK modules, so it gives them permission. If, rather than asking users to add a flag, a library wants to distribute a launcher that grants it permissions and ask users to use that launcher — as the JDK does — it can do so, and that’s ok. The user now knows they’re running a different program that possibly makes different guarantees than `java`.
> 
> But the program called `java` wants to make certain guarantees to its users, and it can’t do that if any library can override any contract it may want to make. Changing the contract has to be visible to the user, either as a flag or as running a different launcher. It’s not that the code in the JDK is necessarily safer, but it’s included in the contract the JDK is trying to make. Thanks to modules and jlink, anyone else can make their own contracts for their own programs.
> 
> Notice that without the integrity in the JDK *no one* can make any contacts. Suppose Alice authors a library, `foo`, that has some powerful invariants, while Bob writes a library `bar`, that uses JNI and, intentionally or not, can break `foo`’s invariants. Requiring an application author to enable native access to use `bar` could certainly inconvenience Bob, but not requiring it would inconvenience Alice. Someone’s “rights” will be reduced; the *only* decision we can make is: whose?
> 
> — Ron

P.S.

Funny that you should bring up Netty because that library quite consciously makes security choices that are substantially different from those of the JDK. I’m not sure whether it still does it, but last I looked Netty allows allocating uninitialised buffers in the name of performance while not requiring them to be fully written before being sent over the wire (there are methods that skip over bytes). When using the public Netty API, care must be taken not to send secret data over the wire (again, I don’t know if that’s still the case, but it was last time I looked). Using official JDK APIs does not (or at least should not) allow you to do that.

So yes, some libraries certainly do prefer to offer laxer security than the JDK, and so, if you opt to use the JDK-provided launcher, we’d like you to know about that and acknowledge it. However, any library or framework that wants to offer different defaults can provide its own launcher and have their users use it. But if you’re using the JDK’s stock launcher, we want to be able to make certain promises and have you know when a library can override them.

Now, you may say that even a pure Java library could reuse ordinary byte arrays without re-initialising them before reuse and we don’t stop that. To which I’d say that 1. re-sending one user’s data over the wire to another is really bad but not quite as bad as sending private keys, and 2. still, if we ever find a way to prevent that and all it would take is a change as minor as requiring an additional flag then perhaps we’ll do that, too someday (BTW, as far as I know, another integrity-conscious language, though not nearly as big and as popular as Java — Rust — also fails to fully guard against a problem of reusing live objects).

— Ron



More information about the jdk-dev mailing list