One thing that springs to mind. Some allowance would have to be made for domain combiners and JAAS Subject propagation: this mechanism also uses access control contexts, to its own great detriment. I would say that the JAAS domain combiner strategy should be dropped in favor of a simple thread local holding the Subject, regardless of what else is decided.
I do personally believe that using a security manager as some kind of proof against untrusted Java code is a mistake. However I think one important use case of security managers is where the Java code being run actually _is_ trusted, but you want to avoid "weird machine" effects where server code could be exploited (by way of malformed requests or whatever) to perform actions that are unexpected but also technically allowed (for example, if your file management abstraction is only ever intended to modify "/app/user-storage/-" then you don't want it to be able to access "/app-server/secret-passwords", and if that happens, you maybe want to start yelling a lot). In this case it's an extra layer of protection. I don't see this use case going away or being invalidated in any way; an application server request _is_ code, in a way, that must be interpreted and "executed" after a fashion in order to do something useful for the user. In terms of approach: back when the discussion around StackWalker design was still going on, it seemed to me that the performance costs of the security manager could be mostly shifted to the security manager itself (thus solving the problem in a different way), if it would walk the stack to do access checking directly, like this: • An "acc" field on Thread is used to hold the inherited access control context • AccessController.doPrivileged(task) becomes empty other than to clear the acc field and delegate to the called block (and restore the acc field after) • AccessController.doPrivileged(task, acc) becomes empty other than to set the acc field to the given ACC argument and delegate to the called block (and restore the acc field after) • AccessController.checkPermission() iterates the call stack until it hits one-frame-lower-than-doPrivileged or the bottom of the stack, checking access along the way for each protection domain (with some simple duplicate elimination as it walks), and once it hits the end, it calls checkPermission on the inherited acc field in Thread (if any). • Creating a new thread still captures the caller acc but then copies it into the new thread's inherited acc field • Construction/compilation of the ACC could possibly be moved to userspace, which will reduce any memory overhead of having it baked in to the native JVM code when it's not actually used • The doPrivileged(action, acc, perms) case could be handled with another Thread field which could be checked before or after the primary check (in this case all the doPrivileged methods would have to stash and set this field as well, and restore it after) • A "shared secret" is added to let AccessController access the two Thread cache field(s) This way the cost of doPrivileged is greatly minimized (two Thread field reads and writes before the block, and two Thread field writes after the block, assuming the aforementioned second field for array permissions) without affecting security manager functionality should it happen to be enabled in software. Also it's easy to improve the security manager debug output, such that you could get a report on _all_ classes or modules or codeSources or whatever which would do not grant a given permission (instead of just the first one), which is greatly useful in reducing iterations in the design and debug stages. When the security manager is actually enabled, only testing would reveal the comparative performance of a stack walker based approach versus the current native ACC optimization code (maybe C2 can work some magic here). There's probably some kind of disgusting weirdness around method handles and reflection things on the call stack that would have to be examined as well. Finally, it will (as always) be a challenge to craft a Stream-consuming Function that doesn't allocate scads of objects when actually iterating the thread stack. Maybe we could allow an Iterator-based StackWalker method. Maybe I'll keep dreaming. Anyway I never got a chance to prototype this, but it might be a fun option worth exploring. I found the idea of moving this stuff all to user space to be very appealing (due in no small part to the idea that it could potentially be examined and analyzed by a much larger audience, being Java code). It also hints at the possibility of a fully "user space" replacement of the security manager concept (much of the remaining cost lives in the structure of AccessControlContext, which is based on an array of ProtectionDomain objects; this is definitely non-ideal and could possibly be hidden behind a smarter abstraction). I really firmly believe that domain combiners should be ultimately eliminated regardless of whatever else happens as they add a lot of complexity in an area where you really don't want complexity, and I think we've already seen specific negative effects of this that have needed fixing in various ways (recently even). On Mon, Nov 20, 2017 at 7:18 AM, Alan Bateman <alan.bate...@oracle.com> wrote: > > One of the long standing issues with the security manager support is that > the overhead when there is no security manager is non-zero. Two specific > examples are (i) the overhead of defineClass (assuming the defining loader > is a SecureClassLoader) as it involves a callback to get the permissions for > the protection domain and (ii) the overhead of AccessController.doPrivileged > in order to execute an action on a privileged stack. > > The bigger question is of course whether it is interesting to run with a > security manager in 2017. It's clearly still important for environments that > download potentially malicious code to execute in a sandox but that isn't > most applications these days. We have seen a few cases where applications > set a security manager in order to enforce some policy, like preventing > plugins calling System.exit but these are cases that would be better served > with other solutions. > > I would like to explore changes to the API and implementation that would > allow us to eliminate some of the overhead when not running with a security > manager. Long term then it would be interesting to explore degrading and > eventually dropping the security manager but that is beyond the scope of > what I would like to discuss here. Sean Mullan and Jeff Nisewanger ran an > interesting BOF at JavaOne 2017 on this topic and I believe are planning to > do a survey at some point to understand the current usage of the security > manager. > > For now I would like to explore what it would take to eliminate some of the > overhead. A big challenge is the System.setSecurityManager API as allows a > security manager to be set in a running VM. This means that classes loaded > before a security manager is set may be involved in permission checks that > happen after a security manager is set. Similarly, privileged actions may > have started before the security manager is set. The complications around > this go away if there was some way to know that a security manager can never > be turned on in a running system. > > To get started, I've put a prototype of an initial proposal on the cr site > [1]. The summary of the proposal is: > > 1. A "disallow security manager" mode that is opt-in to disallow > setSecurityManager being used to set a security manager in a running VM. > Opt-in means it has not impact on existing code. > > 2. Deprecates setSecurityManager to discourage further usage and allow for > the possibility of making "disallow security manager" the default in the > future. If that were to become the default then it would have no impact on > deployments that set the security manager on the command line at startup. > > 3. When running in "disallow security manager" mode, > AccessController.doPrivileged invokes actions directly and > SecureClassLoader.defineClass skips the callback to get permissions for the > protection domain. This part helps startup and runtime performance. > > It's important not to get hung up on the details in the webrev, the > important thing is understand if the security folks on this mailing list are > open to a run mode that prevents a security manager being set in a running > system. > > -Alan. > > [1] http://cr.openjdk.java.net/~alanb/8191053/webrev/ -- - DML