Authorization layer API and low level access checks.

Peter Firmstone peter.firmstone at zeus.net.au
Thu Jun 24 01:03:12 UTC 2021


Hi Alan,

It is important to understand the reason for the inherited 
AccessControlContext, in order to consider alternatives.

The motivation for inherited context, was simply to avoid privilege 
escalation, prior to Executors.

Whenever a permission check is made, the DomainCombiner, combines the 
inherited context, with the thread's current context, in case there are 
any less privileged domains in the inherited context.

But there is an alternative, higher performance option, that avoids 
privilege escalation for executors as well.

A ProtectionDomain with a null CodeSource has AllPermission, while a 
ProtectionDomain that contains a CodeSource with a null URL has only the 
Permission's given to it when created, or to blanket grant statements in 
policy files.

Rather than inherit context from the calling thread, all threads upon 
creation could be initialized with one shared immutable unprivileged 
AccessControlContext, containing a single element array, with a 
ProtectionDomain, containing a CodeSource with a null URL.

Code cannot assume that calling code is privileged, hence the 
AccessController.doPrivileged method, so an unprivileged context could 
replace system threads inherited context as well.   There will be some 
minor impacts in older code where developers create a system thread for 
cleanup tasks or other things, but nothing that couldn't be worked 
around, until it can be addressed properly. This is an existential 
moment for Java authorization, as a developer with extensive use of Java 
authorization, I would most certainly welcome this change.

This would be a simplification that enhances security.   This is far 
more preferable than an inherited AccessControlContext as it eliminates 
any risk that Executor tasks present, where domains in the context that 
creates Callable or Runnable, may not be in the inherited thread 
context.  JEP 411, presents an opportunity to address it.

A use case:

I would like to use virtual threads, in executors, to make blocking 
secure network connections, so I don't consume too many system 
threads.   When network failures occur, the number of threads created 
increase significantly, as blocked threads waiting on network are no 
longer available to the executor.

All our executor tasks are wrapped, with AccessControlContext, using 
Executors::callable(PrivilegedAction), we do this to capture the 
Subject, and to grant SocketPermission (to Principles and CodeSource) to 
make secure network calls from one node to another.  Across the network, 
the user Subject's Principals are preserved, from the thread in the 
client to the thread in the server during authentication.  
DeserializationPermission is granted to the user Principal's and 
CodeSource in the server, so that the code cannot perform 
deserialization (not to be confused with Java serialization) without an 
authenticated user.   The authenticated user represents the domain from 
which data to be deserialized originates.

Personally I would like to see AccessController and AccessControlContext 
retained, and all threads modified to be initialized with a single 
shared immutable unprivileged AccessControlContext, rather than an 
inherited AccessControlContext in system threads and virtual threads 
that do not support any permissions at all.

-- 
Regards,
  
Peter Firmstone

On 23/06/2021 4:34 pm, Alan Bateman wrote:
> On 23/06/2021 04:02, Peter Firmstone wrote:
>>
>> Note: I'm not sure how to replace an inherited AccessControlContext 
>> (with a new implementation based on StackWalker functionality) at 
>> thread creation time, as it must be created when threads are created, 
>> possibly by using ThreadFactory everywhere, but this doesn't cover 
>> all threads. How to cater for virtual threads?
>>
> I don't think the inherited AccessControlContext is widely known or 
> even clearly specified. In any case, virtual threads do not want to be 
> burdened with this field. For now they are specified to not support 
> any permissions. The FJ common pool is another example, the threads 
> don't have any permissions either (see FJP class description has more 
> on that).
>
> -Alan




More information about the security-dev mailing list