Having implemented SecurityManager and Policy providers, I'd like to comment on some of the assessments, some thoughts:

 * Poor performance, this is specific to the Java Policy
   implementation, I have addressed this in my implementations,
   performance impact is imperceptible, I know how to address it.
 * Brittle permission model - Agreed, it is brittle.
     o Developers should use doPrivileged blocks to make security
       sensitive calls, so only one domain is on the call stack. Agreed
       when they don't do this it causes viral permission expansion.
     o Implementing Deny would address the example given.
     o Un-trusted code should never be run on the JVM, however some
       code is more trusted, or well audited, so we may wish to limit
       code that doesn't require privileges, based on principle of
       least privilege.
     o Is there a way to simplify Permission's?  We can write tools to
       generate policy files (I have).
 * Difficult programming model
     o If the library developer uses doPrivileged blocks and documents
       the permissions, then the application code doesn't require those
       permissions, as it is not on the call stack.
     o Agreed that most developers don't do this.
     o I use a tool to generate policy files that capture the viral
       growth of permissions, these still require some editing, eg to
       add system properties.

Is there a simpler way to limit permissions of library code?

I have gotten so used to secure coding, because we use it, I don't find it difficult, writing non blocking or good concurrent code is more difficult and developers make lots of mistakes with race conditions, visibility and synchronization.

There are good static code analysis tools that identify poor coding practices, the same tools could be updated to include secure coding practices as well, to address viral permission expansion.

Perhaps if we instead address the performance and usability issues, we could improve adoption,so it adds to Java's appeal, rather than detracting from it?

Regards,

Peter.

Comments and code from one of my policy implementations (I have a few policy implementations that use the decorator pattern to add functionality, like dynamic permission grants):

* If there is sufficient interest, we can implement a DENY clause,
 * in this case DENY cannot apply to GRANT clauses that contain
 * {@link java.security.AllPermission}, the domains to which a DENY clause
 * would apply will be a less privileged domain.  For example a user could be
 * granted SocketPermission("*", "connect"), while a DENY clause might
 * list specific SocketPermission domains that are disallowed, where a DENY  * clause has precedence over all GRANT clause Permissions except for AllPermission.


@Override
    public boolean implies(ProtectionDomain domain, Permission permission) {         if (permission == null) throw new NullPointerException("permission not allowed to be null");
        if (domain == myDomain) {
            PermissionCollection pc = myPermissions;
            return pc.implies(permission);
        }
        Class klass = permission.getClass();
        // Need to have a list of Permission's we can sort if permission is SocketPermission.         NavigableSet<Permission> perms = new TreeSet<Permission>(comparator);
        PermissionGrant [] grantRefCopy = grantArray;
        int l = grantRefCopy.length;
        /* Check for privileged grants first to avoid recursion when
         * privileged domains become involved in policy decisions */
        for (int j = 0; j < l; j++){
            PermissionGrant ge = grantRefCopy[j];
            if (ge.isPrivileged()){
                if (ge.implies(domain)){
                    return true;
                }
            }
        }
        /* Merge the static Permissions, check for Privileged */
        PermissionCollection staticPC = null;
        if (domain != null) {
            staticPC =domain.getPermissions();
            if (staticPC != null){
                Enumeration<Permission> e = staticPC.elements();
                while (e.hasMoreElements()){
                    Permission p = e.nextElement();
                    // return early if possible.
                    if (p instanceof AllPermission ) return true;
                    // Only add relevant permissions to minimise size.
                    if (klass.isInstance(permission) || permission instanceof UnresolvedPermission){
                        perms.add(p);
                    }
                }
            }
        }
        /* Check less privileged grants */
        for ( int j =0; j < l; j++ ){
            PermissionGrant ge = grantRefCopy[j];
            if (!ge.isPrivileged()){
                if (ge.implies(domain)){
                    Collection<Permission> c = ge.getPermissions();
                    Iterator<Permission> i = c.iterator();
                    while (i.hasNext()){
                        Permission p = i.next();
                        // Only add relevant permissions to minimise size.
                        if (klass.isInstance(permission) || permission instanceof UnresolvedPermission){
                            perms.add(p);
                        }
                    }
                }
            }
        }
        return convert(perms).implies(permission);
    }

On 28/04/2021 8:19 pm, Lim wrote:
On Wed, Apr 21, 2021 at 8:38 PM Ron Pressler <ron.press...@oracle.com> wrote:
Its current events might be not have everything you want, but will be expanded, 
in
part to address the functionality that will be lost with the removal of 
Security Manager.
I agree that monitoring needs to be improved since there is a lack of
monitoring APIs except for JFR. Until those monitoring APIs are on par
with the usage of SM "monitoring", it makes no sense to remove without
providing alternatives.

Libraries that can disable the Security Manager aren’t able to circumvent 
OS-level
sandboxing. If you’re not afraid of that, then they’re trusted and JFR is 
superior;
if they’re untrusted, then configuring the Security Manager correctly for 
untrusted rich
libraries is very difficult.
Since you said that it cannot circumvent OS-level sandboxing, what
will prevent those
libraries to monitor if there is JFR active and become dormant until
there is no JFR
present, then it will execute the malicious behavior; Or, the library
attempts to hide
or render the JFR useless so that it will not be recorded and noticed?

On Wed, Apr 21, 2021 at 8:55 PM Ron Pressler <ron.press...@oracle.com> wrote:
For rich libraries and applications, your best bet is an OS-level sandbox. The 
Security Manager
might give you a false sense of security.
Yes, OS-level sandbox is good but can it be scalable for many types of end
users that have different OS and hardware environments? In addition, how many
end users out there have used sandbox to isolate their desktop applications
except if the program has built-in sandbox such as web browsers? Programs
such as Docker does not count.

Reply via email to