Re: JEP 411: Missing use-case: user functions in an RDBMS
We have updated the JEP with a few changes to the "Issue Warnings" section [1], summarized as follows: If the Java runtime is started without setting the system property 'java.security.manager' then a custom Security Manager can be installed dynamically by calling System::setSecurityManager, just as in Java 16. No UnsupportedOperationException will be thrown. This call will, however, issue a warning message explaining that the Security Manager is deprecated and will be removed in a future release. We plan to change the default value of the 'java.security.manager' system property to "disallow" in the next release, i.e., Java 18. That will cause System::setSecurityManager to throw an UnsupportedOperationException in Java 18. With these changes, the process of deprecating and eventually removing the Security Manager will be consistent with our treatment of past breaking changes such as, e.g., the strong encapsulation of internal APIs. Maintainers of libraries and applications will be given fair warning before any existing code is broken. https://mail.openjdk.java.net/pipermail/jdk-dev/2021-May/005616.html On Sat, May 29, 2021 at 12:04 AM Peter Firmstone < peter.firmst...@zeus.net.au> wrote: > While I accept that my particular use case will no longer be supported > in future, it's difficult to see the value of a sandbox, because > developers will always want to relax it in some way and people fall into > the trap of thinking that trust is black and white; this is trusted, > that is not. > > Nowadays, there's a lot more interest in the Principle of Least > Privilege, especially in health care regulations, now I'm going to use > the meaning implied in "Inside Java 2 Platform Security, Second > Edition", so that we aren't arguing whether that applies with the JVM or > external to it. > > The reason POLP is simpler, is that it can be automated with tooling, > then the development / deployment team may choose to relax it, they can > certainly test it and validate it. Then we are simply focused on what > we need to do, rather than what we might want to restrict, which is > always unknown and subject to change. > > The problem is that this is not how developers have been taught to use > SecurityManager, instead they are told that trusted code can be given > AllPermission because it's trusted and that's an approach which has > proven largely ineffective and the OpenJDK development team carry's the > cost as a result, with little benefit. > > I just thought I'd provide you with a different perspective, so > hopefully the mistake isn't repeated. > > Peter. > > On 28/05/2021 8:09 pm, Ron Pressler wrote: > > > > 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 > >
Re: JEP 411: Missing use-case: user functions in an RDBMS
While I accept that my particular use case will no longer be supported in future, it's difficult to see the value of a sandbox, because developers will always want to relax it in some way and people fall into the trap of thinking that trust is black and white; this is trusted, that is not. Nowadays, there's a lot more interest in the Principle of Least Privilege, especially in health care regulations, now I'm going to use the meaning implied in "Inside Java 2 Platform Security, Second Edition", so that we aren't arguing whether that applies with the JVM or external to it. The reason POLP is simpler, is that it can be automated with tooling, then the development / deployment team may choose to relax it, they can certainly test it and validate it. Then we are simply focused on what we need to do, rather than what we might want to restrict, which is always unknown and subject to change. The problem is that this is not how developers have been taught to use SecurityManager, instead they are told that trusted code can be given AllPermission because it's trusted and that's an approach which has proven largely ineffective and the OpenJDK development team carry's the cost as a result, with little benefit. I just thought I'd provide you with a different perspective, so hopefully the mistake isn't repeated. Peter. On 28/05/2021 8:09 pm, Ron Pressler wrote: 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
Re: JEP 411: Missing use-case: user functions in an RDBMS
On Thu, May 27, 2021 at 8:36 PM Chapman Flack 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 posted this alternative proposal over on jdk-dev, I suppose I should have CC'd this list as well. The idea is that maybe the SecurityManager could stay with enough scaffolding for a third party (say, your extension) to be able to use their own stack-based access checker (made practical thanks to the new-ish StackWalker API). Anyway here it is: -- Forwarded message - From: David Lloyd Date: Sat, May 22, 2021 at 9:11 AM Subject: Re: JEP proposed to target JDK 17: 411: Deprecate the Security Manager for Removal To: Cc: jdk-dev On Fri, May 21, 2021 at 6:04 PM wrote: > The following JEP is proposed to target JDK 17: > > 411: Deprecate the Security Manager for Removal >https://openjdk.java.net/jeps/411 I'm not a committer or reviewer, so perhaps my feedback is unwelcome - but one can't help but note the amount of heated discussion on this topic, and the determination of whether or not the problematic points have been addressed satisfactorily is probably pretty subjective. I have a bit of experience in this area, having either designed or having had a major part of the design of the authentication and authorization APIs presently in use in WildFly [1], as well as the WildFly security manager [2] (and a significant number of other security-related APIs), so I thought I'd give some feedback and also offer a possible compromise. The security manager defines a variety of behaviors. Some of these have clearly been supplanted by other APIs (like getClassContext() vs StackWalker) or security mechanisms (checkPackageAccess() and friends vs the new encapsulation protections). There are also however other APIs on the security manager which clearly have no replacement. These include socket and file access checking APIs, and of course the general permission check methods. In addition, the JEP proposes deprecation of the access controller and policy classes which are the mechanism of stack-based access checking, and finally unavoidably bumps against JAAS, which itself is a very difficult and problematic API which also uses the same stack-based access mechanism (and which we here at Red Hat have for the most part long since abandoned). A large part of this deprecated machinery relates to the stack-based access controller (not to mention, I believe, a nontrivial number of CVEs). The idea, of course, was that one can authenticate untrusted or semi-trusted code. It is definitely clear through years of experience on all sides though that one cannot truly rely on this mechanism to protect against malicious code; it is as easy as an infinite loop to cause massive undesired CPU usage (and, in this modern $/cpu world, cost) for example. However, one other undeniably useful function of the security manager is to authorize basic native operations *not* in the context of what code is executing, but what person or principal is executing it. In other words, the use case of *trusted* code running on behalf of one of many potentially untrusted users - probably the widest application of server-side Java in existence today. It cannot be argued that removing all of the above security checks does not weaken security of such users, when they could have a narrower authorization applied to them to limit the possibility of impact of server exploitation. On the other hand, the cost of the SecurityManager mechanism as it stands is undeniably too high; there is absolutely no point in arguing otherwise, in my view. Leaving aside the substantial CVE load, the access controller and policy APIs are very difficult to use correctly by containers and frameworks, for one thing, and are cumbersome for users as well. Many users and frameworks get doPrivileged() wrong, and combining JAAS subjects into the same mechanism historically doesn't even work consistently between otherwise-compliant JDK implementations. What I would propose then is a compromise aimed at maximizing the amount of value retained and minimizing the amount of cost incurred, by *only* retaining permission checks that specifically pertain to or are useful for user authorization, while *also* deprecating (for removal) the existing problem-prone stack-based access checking mechanism, policy, and security manager implementation. Thus I would suggest not deprecating all of SecurityManager, rather just the following: * java.lang.SecurityManager#getClassContext - it is replaced by StackWalker * java.lang.SecurityManager#getSecurityContext * java.lang.SecurityManager#checkCreateClassLoader *
Re: JEP 411: Missing use-case: user functions in an RDBMS
On 05/28/21 10:03, Chapman Flack wrote: > I still think it would be highly desirable for the JDK itself to > adopt some such mechanism, if it can be made sufficiently non-cumbersome, > and perhaps limited just to file operations ... and Process / ProcessHandle operations I am trying to enumerate, in my head, how many kinds of operations there really needs to be some API for applying filters to, in a post-SM, JPMS encapsulated world. As far as effects a JVM can have on the observable outside world, there are: native actions (and --enable-native-access), file operations (and there is -Djava.nio.file.spi.DefaultFileSystemProvider), socket operations (and there are SocketFactories, though how to set them is undocumented and might fall victim to JEP 403), and process operations (how to filter those? only instrumentation?). Am I missing some? It seems to me that a lot of the complexity of the permission model in the pre-JPMS-encapsulation world involved protecting actions that you might not otherwise care about except that they were all needed to make "self-protecting managers" possible, without which the manager could be defeated and then allow actions you'd care about. If JPMS encapsulation can take over most of that busy-work, does that perhaps mean the set of JDK operations that an application might want/need to intercept and filter shrinks down to some concisely-enumerable set of operations that have external effects? I am not sure ... thinking aloud. Regards, -Chap
Re: JEP 411: Missing use-case: user functions in an RDBMS
Hi, On 05/28/21 06:09, Ron Pressler wrote: > 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. It seems to me that PostgreSQL's trusted/untrusted distinction (which is a distinction baked into the core PostgreSQL project and therefore common to all of the different programming-language supporting extensions like the Java one that I maintain) is aimed at a sort of intermediate threat model. The key consequence of whether a PL is declared to PostgreSQL with or without the TRUSTED keyword is which database user identities will be able to CREATE FUNCTION in that language. If it is not declared trusted, only the database superuser can create functions using it. If it is declared trusted, the database superuser will be able to GRANT USAGE ON LANGUAGE ... to other database user identities, and they will then be able to CREATE FUNCTION in that language. Here it matters that "database user identities" are usually a pretty small set. Acme Corp's customers won't all have database logins; they probably interact with it through a web app that uses its own credentials for a db connection. The few people with database logins are probably all on Acme payroll, and relatively trusted. If Acme's DBA has said GRANT USAGE ON LANGUAGE java TO bob; then probably Bob is not expected to go installing malicious Java functions. Bob is probably a developer and expected to apply reasonable skill at writing safe ones. The functions, once installed, may be /executed/ by a larger number of database IDs, including possibly via the web apps, so might be executed with /inputs/ crafted as maliciously as external attackers can dream up. So I think it might be said (perhaps the core PostgreSQL devs would hold otherwise) that it's /essential/ for the mechanism to be adequate to protect against oversights and mistakes in Bob's code or the libraries he relies on, including mistakes that might be exposed to malicious external inputs. It's /desirable/ for the mechanism to be robust against a malicious Bob himself, but I'm not sure how many, if any, of PostgreSQL's available PLs could be rigorously proven to be so. > 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 It's possible a new design in a green field would be able to take that approach. One thing I should have mentioned, and forgot to, is that there's an actual ISO standard, ISO 9075-13, SQL Routines and Types Using the Java™ Programming Language, constraining how this stuff has to work. That's kind of unique among the extension languages; the maintainers of PL/Python or PL/Ruby, lucky devils, can follow their own visions of what SQL functions in those languages should look like. 9075-13 certainly doesn't say anything about a limited or special API that the function will be required to use. That would be a disruptive change to arbitrary amounts of standard-compliant code. (Naturally, as the standard was developed back when nobody thought the J2SE security architecture would be going away, it would have been assumed that the regular API could be used and permissions would control it.) That said, it might be about time for working group 3 to convene for another look at 9075-13; it hasn't been updated in a while, and I don't think it groks JPMS yet either; user code is treated as classpath code. The PostgreSQL core team has a rep on that working group, so maybe it will be possible to plant that idea. I don't think these things move very quickly. Still, I think a change as drastic as "you must now change the API you use to be some different limited version" could be a tough sell. > 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, Well, the chief cause of that problem has historically been that the third-party library devs have been sloppy about getting doPrivileged where it belongs ... or, to put it more charitably, they haven't been given any way less cumbersome than
Re: JEP 411: Missing use-case: user functions in an RDBMS
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 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