Hi. Before getting into alternatives and the vision for what would be possible post-SecurityManager, it would help to explain what the use-case and requirements are.
When we talk about untrusted code we usually mean code that you believe might be malicious and intentionally try to break through any restrictions you place on it and attack you by any means, including denial-of-service, while trusted code is assumed to not be malicious. From what you’ve written I gather that you only intend to run trusted “plugins", but wish to restrict their operations so that they don’t break some application invariants and accidentally interfere with its operation. If that is the case, would a “shallow” sandbox, that restricts which APIs are available to the plugin (e.g. only expose special APIs to interact with files that go through filtering mechanisms) rather than restrict low-level operations where they “bottom out” before being passed to the OS, suffice (*not* the one in my article, which is just intended for inspiration, and allows reflection without actually fully isolating it)? Deep sandboxes, simple or stack-dependent, are useful for very “rich” code, that is potentially very big and possibly contains arbitrary third-party libraries, while shallow sandboxes are more suitable to limited plugins. While a complex, stack-dependent, deep sandbox *could* be used for plugins, permissions that don’t specify what is forbidden but what is allowed effectively also severely limit the use of third-party libraries, that for example, might want to do benign operations with their own files, and so effectively only allow very limited plugins. The result is a costly mechanism that is overkill for what it’s used for. — Ron > On 28 May 2021, at 02:35, Chapman Flack <c...@anastigmatix.net> wrote: > > 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.