Security Managers and the Java SE JDK (original) (raw)

First and foremost, we highly recommend analyzing all your custom security manager methods before running your security manager under the JDK. Failure to do so could result in a security hole or prevent the proper operation of the JDK. This is due to the fragile nature of 1.1-style security managers.

Where possible, you should just use the default implementation of the 1.2 SecurityManager. This helps give users and administrators consistent behavior. If this is not possible, then you should at least try to call super.checkXXX in yourcheckXXX method before throwing a security exception. Doing so will allow the access controller algorithm to be used, and will allow the JDK itself to function correctly.

In the JDK, any existing code that used to call any of theSecurityManager check methods continues to do so. For new code that requires a security check, calls are made toSecurityManager.checkPermission instead of adding a new SecurityManager check method. For example, the newjava.lang.System.setProperty method callscheckPermission with ajava.util.PropertyPermission permission.

When extending the SecurityManager class and overriding existing methods, some care should be taken. For example, if you override the checkRead(String file) method so it always throws a security exception, then the JDK itself may fail to operate properly. That is, if some JDK code needs to open a file (to read a properties file, load a JAR file, etc.) then throwing a security exception for every read attempt would cause such opens to always fail.

In general, you should only override the default methods if you intend to loosen security, not to make it stronger. If you want to tighten security, you should modify the default policy files and/or install a customjava.security.Policy object. See the security guide on policy files for more information.

In general, when overriding security manager methods you should place a call to the super.checkXXX method at the point where your overridden checkXXX method would throw an exception. For example:

  public class MySecurityManager extends SecurityManager {

    public void checkRead(String file) {
      if (someCustomSecurityCheckFails()) {
         super.checkRead(file);
      }
    }
  }

If your custom security check fails, thensuper.checkRead gets called. The default implementation of checkRead invokescheckPermission, which by default consults theAccessController. By invoking theAccessController, system code that has done anAccessController.doPrivileged before trying to read a file will succeed in reading that file. All other code will be subjected to the current policy in effect, and an access control exception will be thrown if access to that file has not been granted.

Note, there are some checkXXX methods in which you should not call super.checkXXX methods when overriding them. That is because the default implementation of these methods may not be as strict as the policy you are implementing in the overridden method. For example, the defaultcheckAccess(ThreadGroup g) method only protects the system thread group. If you intend to protect threads in distinct thread groups from each other (for example applet thread groups), then you would not want to call super.checkAccess at the point you would normally throw a security exception, as that would defeat the purpose of your customized check. Instead, you could place a call to super.checkAccess as the first statement in your overridden method.

For example:

  public class AppletSecurityManager extends SecurityManager {

    public void checkAccess(ThreadGroup g) {
      // a call to super will throw an exception if someone
      // is trying to modify the system thread group
      super.checkAccess(g);
      ...
      // now perform checks based on which applet thread group
      // the current caller is in to see if they can modify thread group g.
      ...
  }

We describe how to override each method in the following section.

This section lists changes made tojava.lang.SecurityManager methods in the JDK and provides suggestions regarding any overrides you may wish to make. Please see the Java documentation for theSecurityManager class for more information on these methods.

protected boolean inCheck

This field has been deprecated, and any uses of this field within the JDK itself have been removed. Instead of using inCheck, you should use checkPermission along withdoPrivileged.

public boolean getInCheck();

This method has also been deprecated.

public SecurityManager();

The constructor has been modified to allow multiple SecurityManagers to be created, assuming the caller has theRuntimePermission("createSecurityManager")permission.

protected native Class[] getClassContext();

No changes. This call can be used to emulate the 1.1 behavior of the methods that have been changed in the JDK (currentClassLoader, currentLoadedClass,classLoaderDepth, inClassLoader).

protected ClassLoader currentClassLoader();

The typical use of this method in JDK 1.1-style security managers was to see if there was a class loader on the stack, and if not, treat the code as "trusted" and allow it to do anything. This method has been modified in the JDK to allow trusted JDK code (actually any code grantedjava.security.AllPermission) that callsdoPrivileged to be treated as trusted by 1.1-style security managers. It has also been modified to skip system class loaders. A system class loader is defined as being a class loader that is equal to the system class loader (as returned by ClassLoader.getSystemClassLoader) or one of its ancestors.

This method will return null in the following three cases:

  1. All methods on the execution stack are from classes defined using the system class loader or one of its ancestors.
  2. All methods on the execution stack up to the first "privileged" caller (see java.security.AccessController.doPrivileged) are from classes defined using the system class loader or one of its ancestors.
  3. A call to checkPermission withjava.security.AllPermission does not result in a SecurityException.

This method has been deprecated. UsecheckPermission instead.

protected Class currentLoadedClass();

This method has been modified in the same fashion ascurrentClassLoader, and will return nullif the current security context has been grantedAllPermission or all the methods on the stack (up to the first privileged caller, if any) are from classes defined using the system class loader or one of its ancestors.

This method has been deprecated. UsecheckPermission instead.

protected int classDepth(String name);

No changes in behavior. This method has been deprecated. UsecheckPermission instead.

protected int classLoaderDepth();

This method has been modified in the same fashion ascurrentClassLoader, and will return -1 if the current security context has been grantedAllPermission or all the methods on the stack (up to the first privileged caller, if any) are from classes defined using the system class loader or one of its ancestors.

This method has been deprecated. UsecheckPermission instead.

protected boolean inClass(String name);

No changes in behavior. This method has been deprecated. UsecheckPermission instead.

protected boolean inClassLoader();

This method returns true if currentClassLoaderreturns a non-null class loader, so it follows the same semantics that currentClassLoader does.

This method has been deprecated. UsecheckPermission instead.

public Object getSecurityContext();

This method returns ajava.security.AccessControlContext object that is created with a call tojava.security.AccessController.getContext. In JDK1.1 it returned null by default.

public void checkPermission(Permission perm);

This method is new in the JDK. It callsjava.security.AccessController.checkPermission with the given permission. Internally, the JDK always callsSecurityManager.checkPermission instead of calling theAccessController directly. This allows people to override this method to provide additional functionality such as auditing and/or GUI dialogs.

public void checkPermission(Permission perm, Object context);

This method is new in the JDK. If context is an instance of AccessControlContext then theAccessControlContext.checkPermission method will be invoked on the given context with the specified permission.

If context is not an instance ofAccessControlContext then aSecurityException is thrown.

public void checkCreateClassLoader();

This method has been modified to callcheckPermission with theRuntimePermission("createClassLoader") permission.

If this method is overridden, then a call tosuper.checkCreateClassLoader should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkCreateClassLoader() { if (someCustomSecurityCheckFails()) { super.checkCreateClassLoader(); } } }

public void checkAccess(Thread t);

If the thread argument is a system thread (belongs to the thread group with a null parent) then this method callscheckPermission with theRuntimePermission("modifyThread") permission.

Applications that want a stricter policy should override this method.

If this method is overridden, thensuper.checkAccess should be called by the first statement in the overridden method, or the equivalent security check should be placed in the overridden method.

If this method is overridden, the method that overrides it should additionally check to see if the calling thread has theRuntimePermission("modifyThread") permission, and if so, return silently. This is to ensure that code granted that permission (such as the JDK itself) is allowed to manipulate any thread.

For example:

public class MySecurityManager extends SecurityManager {

public void checkAccess(Thread t) { // a call to super will throw an exception if someone // is trying to modify a system thread super.checkAccess(t); ... if (someCustomSecurityCheckForOtherThreadsFails()) { // if the check fails, instead of throwing an exception, // call checkPermission, which will throw an exception // if need be checkPermission(new RuntimePermission("modifyThread"));
} ... } }

public void checkAccess(ThreadGroup g);

If the thread group argument is the system thread group (has anull parent) then this method callscheckPermission with theRuntimePermission("modifyThreadGroup") permission.

Applications that want a stricter policy should override this method.

If this method is overridden, thensuper.checkAccess should be called by the first statement in the overridden method, or the equivalent security check should be placed in the overridden method.

If this method is overridden, the method that overrides it should additionally check to see if the caller has theRuntimePermission("modifyThreadGroup") permission, and if so, return silently. This is to ensure that code granted that permission (such as the JDK itself) is allowed to manipulate any thread group.

For example:

public class MySecurityManager extends SecurityManager {

public void checkAccess(ThreadGroup g) { // a call to super will throw an exception if someone // is trying to modify the system thread group super.checkAccess(g); ... if (someCustomSecurityCheckForOtherThreadGroupsFails()) { // if the check fails, instead of throwing an exception, // call checkPermission, which will throw an exception // if need be checkPermission(new RuntimePermission("modifyThreadGroup"));
} ... } }

public void checkExit(int status);

This method has been modified to callcheckPermission with theRuntimePermission("exitVM") permission.

If this method is overridden, then a call tosuper.checkExit should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkExit(int status) { if (someCustomSecurityCheckFails()) { super.checkExit(status); } } }

public void checkExec(String cmd);

This method has been modified to callcheckPermission with a FilePermission. If the cmd is an absolute path (seejava.io.File.isAbsolute) then it is passed as-is as the target for the FilePermission. If cmdis not absolute, then the special target "<>" is used. This target is used because it is difficult to determine the actual path of the command that will be executed on an individual platform due to things such as environment variables, etc.

If this method is overridden, then a call tosuper.checkExec should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkExec(String cmd) { if (someCustomSecurityCheckFails()) { super.checkExec(cmd); } } }

public void checkLink(String lib);

This method has been modified to callcheckPermission with theRuntimePermission("loadLibrary."+lib) permission.

If this method is overridden, then a call tosuper.checkLink should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkLink(String lib) { if (someCustomSecurityCheckFails()) { super.checkLink(lib); } } }

public void checkRead(FileDescriptor fd);

This method has been modified to callcheckPermission with theRuntimePermission("readFileDescriptor")permission.

If this method is overridden, then a call tosuper.checkRead should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkRead(FileDescriptor fd) { if (someCustomSecurityCheckFails()) { super.checkRead(fd); } } }

public void checkRead(String file);

This method has been modified to callcheckPermission with theFilePermission(file,"read") permission.

If this method is overridden, then a call tosuper.checkRead should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkRead(String file) { if (someCustomSecurityCheckFails()) { super.checkRead(file); } } }

public void checkRead(String file, Object context);

This method has been modified. If context is an instance of AccessControlContext then theAccessControlContext.checkPermission method will be invoked on the given context with theFilePermission(file,"read") permission.

If context is not an instance ofAccessControlContext then aSecurityException is thrown.

If this method is overridden, then a call tosuper.checkRead should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkRead(String file, Object context) { if (someCustomSecurityCheckFails()) { super.checkRead(file, context); } } }

public void checkWrite(FileDescriptor fd);

This method has been modified to callcheckPermission with theRuntimePermission("writeFileDescriptor")permission.

If this method is overridden, then a call tosuper.checkWrite should be made at the point the overridden method would normally throw an exception. For Example:

public class MySecurityManager extends SecurityManager {

public void checkWrite(FileDescriptor fd) { if (someCustomSecurityCheckFails()) { super.checkWrite(fd); } } }

public void checkWrite(String file);

This method has been modified to callcheckPermission with theFilePermission(file,"write") permission.

If this method is overridden, then a call tosuper.checkWrite should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkWrite(String file) { if (someCustomSecurityCheckFails()) { super.checkWrite(file); } } }

public void checkDelete(String file);

This method has been modified to callcheckPermission with theFilePermission(file,"delete") permission.

If this method is overridden, then a call tosuper.checkDelete should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkDelete(String file) { if (someCustomSecurityCheckFails()) { super.checkDelete(file); } } }

public void checkConnect(String host, int port);

This method has been modified to callcheckPermission with theSocketPermission(host+":"+port,"connect") permission if the port is not equal to -1. If the port is equal to -1, then it calls checkPermission with theSocketPermission(host,"resolve") permission.

This behavior is consistent with JDK 1.1, where a port equal to -1 indicates that an IP address lookup is being performed.

If this method is overridden, then a call tosuper.checkConnect should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkConnect(String host, int port) { if (someCustomSecurityCheckFails()) { super.checkConnect(host, port); } } }

public void checkConnect(String host, int port, Object context);

This method has been modified. If context is an instance of AccessControlContext then theAccessControlContext.checkPermission method will be invoked on the given context with theSocketPermission(host+":"+port,"connect") permission if the port is not equal to -1. If the port is equal to -1, then it calls checkPermission with theSocketPermission(host,"resolve") permission.

If context is not an instance ofAccessControlContext then aSecurityException is thrown.

If this method is overridden, then a call tosuper.checkConnect should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkConnect(String host, int port, Object context) { if (someCustomSecurityCheckFails()) { super.checkConnect(host, port, context); } } }

public void checkListen(int port)

This method has been modified. If port is not 0, it callscheckPermission with theSocketPermission("localhost:"+port,"listen"). If port is zero, it calls checkPermission withSocketPermission("localhost:1024-","listen").

If this method is overridden, then a call tosuper.checkListen should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkListen(int port) { if (someCustomSecurityCheckFails()) { super.checkListen(port); } } }

public void checkAccept(String host, int port);

This method has been modified to callcheckPermission with theSocketPermission(host+":"+port,"accept")permission.

If this method is overridden, then a call tosuper.checkAccept should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkAccept(String host, int port) { if (someCustomSecurityCheckFails()) { super.checkAccept(host, port); } } }

public void checkMulticast(InetAddress maddr);

This method has been modified to callcheckPermission with theSocketPermission(maddr.getHostAddress(),"accept,connect")permission.

If this method is overridden, then a call tosuper.checkMulticast should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkMultiCast(InetAddress maddr) { if (someCustomSecurityCheckFails()) { super.checkMultiCast(maddr); } } }

public void checkMulticast(InetAddress maddr, byte ttl);

This method has been modified to callcheckPermission with theSocketPermission(maddr.getHostAddress(),"accept,connect")permission.

If this method is overridden, then a call tosuper.checkMulticast should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkMultiCast(InetAddress maddr, byte ttl) { if (someCustomSecurityCheckFails()) { super.checkMultiCast(maddr, ttl); } } }

public void checkPropertiesAccess();

This method has been modified to callcheckPermission with the PropertyPermission("*", "read,write") permission.

If this method is overridden, then a call tosuper.checkPropertiesAccess should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkPropertiesAccess() { if (someCustomSecurityCheckFails()) { super.checkPropertiesAccess(); } } }

public void checkPropertyAccess(String key);

This method has been modified to callcheckPermission with the PropertyPermission(key, "read") permission.

If this method is overridden, then a call tosuper.checkPropertyAccess should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkPropertyAccess(String key) { if (someCustomSecurityCheckFails()) { super.checkPropertiesAccess(key); } } }

public boolean checkTopLevelWindow(Object window);

This method has been modified to callcheckPermission with theAWTPermission("showWindowWithoutWarningBanner")permission, and returns true if an SecurityException is not thrown, otherwise it returns false.

If this method is overridden, then a call tosuper.checkTopLevelWindow should be made at the point the overridden method would normally return false, and the value ofsuper.checkTopLevelWindow should be returned. For example:

public class MySecurityManager extends SecurityManager {

public void checkTopLevelWindow(Object window) { if (someCustomSecurityCheckFails()) { return super.checkTopLevelWindow(window); } else { return true; } } }

public void checkPrintJobAccess();

This method has been modified to callcheckPermission with theRuntimePermission("queuePrintJob") permission.

If this method is overridden, then a call tosuper.checkPrintJobAccess should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkPrintJobAccess() { if (someCustomSecurityCheckFails()) { super.checkPrintJobAccess(); } } }

public void checkSystemClipboardAccess();

This method has been modified to callcheckPermission with theAWTPermission("accessClipboard") permission.

If this method is overridden, then a call tosuper.checkSystemClipboardAccess should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkSystemClipboardAccess() { if (someCustomSecurityCheckFails()) { super.checkSystemClipboardAccess(); } } }

public void checkAwtEventQueueAccess();

This method has been modified to callcheckPermission with theAWTPermission("accessEventQueue") permission.

If this method is overridden, then a call tosuper.checkAwtEventQueueAccess should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkAwtEventQueueAccess() { if (someCustomSecurityCheckFails()) { super.checkAwtEventQueueAccess(); } } }

public void checkPackageAccess(String pkg);

This method has been modified. It first gets a list of restricted packages by obtaining a comma-separated list from a call tojava.security.Security.getProperty("package.access"), and checks to see if pkg starts with or equals any of the restricted packages. If it does, thencheckPermission gets called with theRuntimePermission("accessClassInPackage."+pkg)permission.

If this method is overridden, thensuper.checkPackageAccess should be called as the first line in the overridden method. For example:

public class MySecurityManager extends SecurityManager {

public void checkPackageAccess(String pkg) { super.checkPackageAccess(pkg); ... someCustomSecurityCheck(); ... } }

public void checkPackageDefinition(String pkg);

This method has been modified. It first gets a list of restricted packages by obtaining a comma-separated list from a call tojava.security.Security.getProperty("package.definition"), and checks to see if pkg starts with or equals any of the restricted packages. If it does, thencheckPermission gets called with theRuntimePermission("defineClassInPackage."+pkg)permission.

If this method is overridden, thensuper.checkPackageDefinition should be called as the first line in the overridden method. For example:

public class MySecurityManager extends SecurityManager {

public void checkPackageDefinition(String pkg) { super.checkPackageDefinition(pkg); ... someCustomSecurityCheck(); ... } }

public void checkSetFactory();

This method has been modified to callcheckPermission with theRuntimePermission("setFactory") permission.

If this method is overridden, then a call tosuper.checkSetFactory should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkSetFactory() { if (someCustomSecurityCheckFails()) { super.checkSetFactory(); } } }

public void checkMemberAccess(Class clazz, int which);

This method has been modified. The default policy is to allow access to PUBLIC members, as well as access to classes that have the same class loader as the caller. In all other cases callcheckPermission with theRuntimePermission("accessDeclaredMembers")permission.

If this method is overridden, then a call tosuper.checkMemberAccess cannot be made, as the default implementation of checkMemberAccess relies on the code being checked being at a stack depth of 4. For example:

someCaller[3]
java.lang.Class.someReflectionAPI [2]
java.lang.Class.checkMemberAccess [1]
SecurityManager.checkMemberAccess [0]

In order to emulate this behavior, you would need to callgetClassContext, and examine the class loader of the class at index 3, just as the defaultcheckMemberAccess method does:

if (which != Member.PUBLIC) { Class stack[] = getClassContext(); /* * stack depth of 4 should be the caller of one of the * methods in java.lang.Class that invoke checkMember * access. The stack should look like: * * someCaller [3] * java.lang.Class.someReflectionAPI [2] * java.lang.Class.checkMemberAccess [1] * MySecurityManager.checkMemberAccess [0] * */ if ((stack.length<4) || (stack[3].getClassLoader() != clazz.getClassLoader())) { if (checkMemberAccessPermission == null) checkMemberAccessPermission = new RuntimePermission("accessDeclaredMembers"); checkPermission(checkMemberAccessPermission); } }

This is the only security manager method in the JDK that is still based on a caller's depth. This is to allow a caller to reflect on classes from the same class loader it came from.

public void checkSecurityAccess(String target);

This method has been modified to create aSecurityPermission object for the given permission target name and calls checkPermission with it.

If this method is overridden, then a call tosuper.checkSecurityAccess should be made at the point the overridden method would normally throw an exception. For example:

public class MySecurityManager extends SecurityManager {

public void checkSecurityAccess(String target) { if (someCustomSecurityCheckFails()) { super.checkSecurityAccess(target); } } }

public ThreadGroup getThreadGroup();

This method has not been changed.