Hello, I see I am another person relatively late to stumble on this
"well publicized" JEP. (I am not sure how to recommend the publicity
could have been better handled, but apparently the avenues that were
used aren't ones that reached me.)

I maintain, on a volunteer basis, the extension for Java server-side
functions in the PostgreSQL RDBMS [1].

I got the news of this JEP through occasionally visiting the JDK 17
page to see what JEPs are proposed and targeted that might be of use
in the project, and one day I visited (could have been as late as May 17
according to the Wayback Machine) and there was nothing of great
interest (though I have some pleasant ideas for sealed classes and I
really wish JEP 412 were done incubating!), and I didn't check back
until just recently, and then I looked and saw this JEP.

I've read through the very long "Missing use-case: monitoring/
restricting libraries" thread, and some of the points raised there
have echoes here.

Any PostgreSQL server-side function implementation for a language foo
will be expected to say it is a "trusted" or "untrusted" language (or
provide both) as defined in the PostgreSQL docs [2].

A "trusted" one is expected to restrict certain actions (access to the
server filesystem, perhaps network connections, etc.).

OS-level controls are too coarse because the RDBMS process that the
language extension gets dlopened into certainly has reasons of its own
to manipulate files and sockets.

It might, perhaps, be shown that every available trusted language for
PostgreSQL could be imperfect or exploitable in some way; I think that's
beside the point, which is that they all are meant to take credible
steps to supply the expected layer of cheese with whatever small holes
may be present.

In the current architecture, Java backend functions can be restricted
with very fine grain, anything that a PolicyFile can specify.

It looks as if I will have to do a maintenance release, which will
have to supply the extra -Djava.security.manager=allow when running
on 17 (and spam the RDBMS log file with the apparently unsuppressable
warning every time a JVM starts [3]), and then I will have to detect
whatever subsequent Java release "degrades" the classes, and refuse to
execute trusted functions on that release or later.

Beyond that, I'll need to begin on some rearchitected major release
to be able to meet the requirements some other way.

Suppose I relax the requirements to merely restricting filesystem
and network operations. Will there be any simple, reliable way for
me to install some handler to filter those? I have seen JVMTI
instrumentation suggested. I suppose an interposing FileSystemProvider
could be an option for filesystem operations. SocketFactory and
ServerSocketFactory might offer ways to interpose on network
operations, except that there seems to be no documentation of how
the default factories are to be set: "specified by environment-specific
configuration mechanisms ... a framework could use a factory customized
for its own purposes" doesn't seem quite sufficient. I could be considered
to be providing a framework: is the expectation that I must read the
source and then JNI-poke an undocumented static in order to set a factory?

Assuming that hurdle cleared, socket restrictions might not be too bad.
The JRE probably doesn't do a lot of network operations on its own behalf,
so a "simple deep sandbox" in Ron's taxonomy is sufficient there; whatever
operations are being initiated will be coming from the application code.

That's not even remotely true for file operations though: the Java runtime
does stuff with files! Early PL/Java versions that tried to make do with a
"simple" SecurityManager (devoid of the AccessController and stack
awareness) clearly demonstrated the problem, falling over because the
runtime needed to open /dev/random to make an SSL connection, or timezone
files to print a date, or write temporary files in compiling a Templates
object, or load agent classes to accept a visualvm connection.

Those problems all were solved by axing the "simple" SecurityManager and
reverting to the J2SE one with stack awareness. All those things then
Just Worked.

The reason, of course, is that those doPrivileged calls throughout
the implementation are carriers of vital information about which operations
are "taint-free" Java runtime internal details and which ones are coming
from the application. It isn't the application developer's business to know
that TransformerFactory.newTemplates() needs to scribble transparently
in some files. That vital information is known by the developers working
on the JDK and is still needed for any sane out-of-JDK reimplementation
of filesystem access controls.

I'm sensitive to the argument that lots of third-partly libraries have
always whiffed on putting their own doPrivileged calls in the right
places, so application developers have had to clean up after them anyway,
and that will only get worse after this JEP. But it still seems to me that
the JDK itself is a different story.

Suppose we simplify the problem to only preserving the information needed
to enable implementation of filesystem access controls. All the doPrivileged
calls in there because of other obscure permissions that will be abandoned,
never mind those. Can there be some way to retain the information that's
represented by the ones around taint-free filesystem operations?

- some kind of annotation?

- some very lightweight doPrivileged replacement that sets a thread-local
  flag that a filesystem-access filter, if present, could check?

- a set of openTaintFree()/deleteTaintFree()/... methods added to the
  filesystem APIs and used in place of the methods currently called within
  doPrivileged? Some mechanism like JEP 412's --enable-native-access could
  allow selected modules to call those methods, and a filter, if supplied,
  could just leave those alone.

Could some idea like this be a manageably-small burden for the JDK devs
to keep up to date? Much of the affected code is already very mature and
has the doPrivileged()s in the right places. It would be a sort of
mechanical transformation of those sites, plus a simple need to be aware
in new API development of where the file operations are on tainted values
or not. Isn't that already something devs need to be aware of?

Regards,
Chapman Flack


[1] https://tada.github.io/pljava/use/policy.html

[2]
https://www.postgresql.org/docs/13/sql-createlanguage.html#SQL-CREATELANGUAGE-PARAMETERS

[3] Say ... will that unsuppressable warning be written via the vfprintf
    hook? That would be nice, I could suppress it there then.

Reply via email to