I'm building a SWING application and also need to write a custom SecurityManager. If I write an empty class which extends SecurityManager like this
public class Sandbox extends SecurityManager {}
it works fine, meaning that the GUI is rendered correctly and all privileges like I/O are revoked.
However I need to customize the checkPermission method and whenever I override it nothing works anymore...
Why even something like this shouldn't work??
public class Sandbox extends SecurityManager {
#Overide
public void checkPermission(Permission perm) {
super.checkPermission(perm);
}
}
Update: a very basic example that shows the problem is this
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager() {
#Override
public void checkPermission(Permission p) {
if (some_condition_here) {
// Do something here
} else {
// Resort to default implementation
super.checkPermission(p);
}
}
});
new JFrame().setVisible(true);
}
Removing the "checkPermission" method the application works correctly, but I really can't get my head around this.
The permissions are granted based on all the code on the stack. All callers must have the required permission. If you override the method and call the superclass method, your code is on the stack as well which implies that your codebase (where your custom SecurityManager belongs to) must have the permission you (your callers) ask for.
That’s the difference between overriding or not. If you don’t override that method only the (possibly privileged) caller’s code is on the stack and it will get the requested permission. If you override that method your code is also on the stack and must have the permission as well.
So if you want to implement a custom SecurityManager which invokes the inherited check method you must configure the inherited (policy based) logic to give your SecurityManager all permissions it should be able to grant. It’s recommended to separate the SecurityManager from the rest of the application into a different codebase so only the SecurityManager and nothing else gets the generous permissions.
If you call the superclass' checkPermission(p) you didn't have to override the class in the first place. Comment it out, then it works.
The superclas' calls java.security.AccessController.checkPermission(perm) and that seems to throw a java.security.AccessControlException, when not invoked by java.lang.SecurityManager
in my case it says:
Could not load Logmanager "null"
java.security.AccessControlException: access denied (java.util.PropertyPermission java.util.logging.manager read)
etc.
public class SecurityManagerExample
{
public static void main(String[] args)
{
System.setSecurityManager(new SecurityManager()
{
#Override
public void checkPermission(Permission p)
{
//super.checkPermission(p);
}
});
new JFrame().setVisible(true);
}
}
I found a tutorial on how to write a security manager. I'd also recommend you to go through the java doc and the examples provided by oracle.
UPDATE
Take a look at the method summary and override the functionality you want to forbid.
As I found out you also need to explicitly allow the functionality you want to have.
Here an example:
public class SecurityManagerExample
{
public static void main(String[] args)
{
System.setSecurityManager(new SecurityManager()
{
#Override
public void checkWrite(String file) {
// no exception is thrown, i. e. creating files is allowed in general
}
#Override
public void checkDelete(String file)
{
if (file.equals("test.xml"))
{
throw new SecurityException("Not allowed to delete test.xml!");
}
}
});
File f = new File("test.xml");
try
{
f.createNewFile();
}
catch (IOException e)
{
}
f.delete();
}
}
OUTPUT
Exception in thread "main" java.lang.SecurityException: Not allowed to delete test.xml!
at main.SecurityManagerExample$1.checkDelete(SecurityManagerExample.java:60)
at java.io.File.delete(File.java:902)
at main.SecurityManagerExample.main(SecurityManagerExample.java:74)
Related
Head First Design Patterns say:
The Command Pattern encapsulates a request as an object, thereby
letting you parameterize other objects with different requests, queue
or log requests, and support undoable operations.
Later the book said:
The semantics of some applications require that we log all actions and
be able to recover after a crash by reinvoking those actions. The
Command Pattern can support these semantics with the addition of two
methods: store() and load(). In Java we could use object serialization
to implement these methods, but the normal caveats for using
serialization for persistence apply.
How does this work? As we execute commands, we store a history of them
on disk. When a crash occurs, we reload the command objects and invoke
their execute() methods in batch and in order.
I am trying to come up with an example code. The code I wrote till now is:
class Client {
public static void main(String[] args) {
Command enableCommand = new EnableCommand();
enableCommand.execute();
}
}
interface Command {
void execute();
void store();
void load();
}
class EnableCommand implements Command {
public EnableCommand() {
}
#Override
public void execute() {
store();
System.out.println("Execute Command");
}
#Override
public void store() {
System.out.println("Storing on Disk");
}
#Override
public void load() {
// TODO Auto-generated method stub
}
}
How the load() function is supposed to work?
Can anyone explain this code of HackerRank?
class DoNotTerminate {
public static class ExitTrappedException extends SecurityException {
private static final long serialVersionUID = 1;
}
public static void forbidExit() {
final SecurityManager securityManager = new SecurityManager() {
#Override
public void checkPermission(Permission permission) {
if (permission.getName().contains("exitVM")) {
throw new ExitTrappedException();
}
}
};
System.setSecurityManager(securityManager);
}
}
This following code will stop you from terminating the code using exit(0)!
When a program tries to stop the JVM by calling System.exit(...), then it first checks if this action is allowed by asking the security manager if the exitVM permission is granted.
The code you posted replaces the security manager with a custom security manager that will throw an ExitTrappedException when checking for the exitVM permission.
So, what happens is this:
User program calls System.exit(...)
The System.exit(...) method asks the security manager if the exitVM permission is allowed
The custom security manager throws an ExitTrappedException
System.exit(...) does not continue to stop the JVM, but passes the exception on the caller; the JVM keeps running
I am using a third party library that does a System.exit() if it encounters exceptions. I am using the APIs from a jar. Is there anyway that I can prevent the System.exit() call because it causes my application to shutdown? I cannot decompile and recompile the jar after removing the System.exit() because of a lot of other licensing issues. I once came across an answer [to some other question that I do not remember] in stackoverflow that we can use the SecurityManager in Java to do something like this.
You can install a security manager which disables System.exit():
private static class ExitTrappedException extends SecurityException { }
private static void forbidSystemExitCall() {
final SecurityManager securityManager = new SecurityManager() {
public void checkPermission( Permission permission ) {
if( "exitVM".equals( permission.getName() ) ) {
throw new ExitTrappedException() ;
}
}
} ;
System.setSecurityManager( securityManager ) ;
}
private static void enableSystemExitCall() {
System.setSecurityManager( null ) ;
}
Edit: Max points out in comments below that
as of Java 6, the permission name is actually "exitVM."+status, e.g. "exitVM.0".
However, the permission exitVM.* refers to all exit statuses, and exitVM is retained as a shorthand for exitVM.*, so the above code still works (see the documentation for RuntimePermission).
See my reply to How to avoid JFrame EXIT_ON_CLOSE operation to exit the entire application?.
Edit 1: The source that was linked. Demonstrates how to use a SecurityManager to prevent System.exit(n).
import java.awt.*;
import java.awt.event.*;
import java.security.Permission;
/** NoExit demonstrates how to prevent 'child'
applications from ending the VM with a call
to System.exit(0).
#author Andrew Thompson */
public class NoExit extends Frame implements ActionListener {
Button frameLaunch = new Button("Frame"),
exitLaunch = new Button("Exit");
/** Stores a reference to the original security manager. */
ExitManager sm;
public NoExit() {
super("Launcher Application");
sm = new ExitManager( System.getSecurityManager() );
System.setSecurityManager(sm);
setLayout(new GridLayout(0,1));
frameLaunch.addActionListener(this);
exitLaunch.addActionListener(this);
add( frameLaunch );
add( exitLaunch );
pack();
setSize( getPreferredSize() );
}
public void actionPerformed(ActionEvent ae) {
if ( ae.getSource()==frameLaunch ) {
TargetFrame tf = new TargetFrame();
} else {
// change back to the standard SM that allows exit.
System.setSecurityManager(
sm.getOriginalSecurityManager() );
// exit the VM when *we* want
System.exit(0);
}
}
public static void main(String[] args) {
NoExit ne = new NoExit();
ne.setVisible(true);
}
}
/** This example frame attempts to System.exit(0)
on closing, we must prevent it from doing so. */
class TargetFrame extends Frame {
static int x=0, y=0;
TargetFrame() {
super("Close Me!");
add(new Label("Hi!"));
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.out.println("Bye!");
System.exit(0);
}
});
pack();
setSize( getPreferredSize() );
setLocation(++x*10,++y*10);
setVisible(true);
}
}
/** Our custom ExitManager does not allow the VM
to exit, but does allow itself to be replaced by
the original security manager.
#author Andrew Thompson */
class ExitManager extends SecurityManager {
SecurityManager original;
ExitManager(SecurityManager original) {
this.original = original;
}
/** Deny permission to exit the VM. */
public void checkExit(int status) {
throw( new SecurityException() );
}
/** Allow this security manager to be replaced,
if fact, allow pretty much everything. */
public void checkPermission(Permission perm) {
}
public SecurityManager getOriginalSecurityManager() {
return original;
}
}
The previous code sample is partially correct, but I found that it ended up blocking my code's access to files. To get around that problem, I wrote my SecurityManager a little differently:
public class MySecurityManager extends SecurityManager {
private SecurityManager baseSecurityManager;
public MySecurityManager(SecurityManager baseSecurityManager) {
this.baseSecurityManager = baseSecurityManager;
}
#Override
public void checkPermission(Permission permission) {
if (permission.getName().startsWith("exitVM")) {
throw new SecurityException("System exit not allowed");
}
if (baseSecurityManager != null) {
baseSecurityManager.checkPermission(permission);
} else {
return;
}
}
}
In my case, I needed to prevent a 3rd party library from terminating the VM. But there were also some grails tests that were calling System.exit. So, I wrote my code so that it only activated the custom security manager immediately before the call to the 3rd party library (not a common event) and then immediately restored the original security manager, if any, afterwards.
It's all a little ugly. Ideally, I would have preferred to simply remove the System.exit code, but I do not have access to the 3rd party library's source code.
Using SecurityManager to disallow System.exit() calls is not perfect, for at least 2 reasons:
Java applications running with and without SecurityManager enabled are very different. That's why it needs to be turned off eventually, but it cannot be done with System.setSecurityManager(null). This call will lead to another security permission check, that will inevitably fail, because application code (SecurityManager subclass) is on the top of the calling stack.
All the Java applications are multi-threaded, and other threads can do various things between forbidSystemExitCall() and enableSystemExitCall(). Some of these things can be protected with security permission checks, which will fail for the very same reasons as described above. If checkExit() is overridden instead of [much more generic] checkPermission(), it will cover most of the cases, though.
The only way (that I know) to resolve this is to grant all the privileged to the SecurityManager subclass. It will very likely require it to be loaded by a separate class loader, e.g. bootstrap (null) class loader.
I have create a simple plugin system that allows others upload their plugin's jar, and the plugin system will load it and execute some code in it.
the plugin system will get a subclass of Function<Input, Output> to execute the loaded plugin logic, but I do not want that Function to create new Thread or do some danger action like System.exit. how can I forbid this action?
I have found the AccessController or SecurityManager in Java, how to use it to implement my intent.
Like you said, you can add a security Manager. Something like below: You can put your code in try catch block and catch your custom security exception thrown. This code below runs in loop and keeps on calling System.exit(1);
import java.security.Permission;
public class TestPreventSystemExit {
public static void main(String[] args) {
forbidSystemExitCall();
while (true) {
try {
System.exit(1);
} catch (Exception ex) {
}
}
}
private static class PreventExitException extends SecurityException {
}
private static void forbidSystemExitCall() {
final SecurityManager securityManager = new SecurityManager() {
public void checkPermission(Permission permission) {
if (permission.getName().indexOf("exitVM") >= 0) {
System.out.println("Why you did this to me? :)");
throw new PreventExitException();
}
}
};
System.setSecurityManager(securityManager);
}
}
For System.exit() - see the other answer.
For preventing the starting of threads: possible, but requires to extend the SecurityManager class - see here.
AccessController is more about how a client would write code that is potentially checked. It is not something that you, as the "owner" of the JVM can make usage of (see here). So it doesn't help with your problem.
I am using a third party library that does a System.exit() if it encounters exceptions. I am using the APIs from a jar. Is there anyway that I can prevent the System.exit() call because it causes my application to shutdown? I cannot decompile and recompile the jar after removing the System.exit() because of a lot of other licensing issues. I once came across an answer [to some other question that I do not remember] in stackoverflow that we can use the SecurityManager in Java to do something like this.
You can install a security manager which disables System.exit():
private static class ExitTrappedException extends SecurityException { }
private static void forbidSystemExitCall() {
final SecurityManager securityManager = new SecurityManager() {
public void checkPermission( Permission permission ) {
if( "exitVM".equals( permission.getName() ) ) {
throw new ExitTrappedException() ;
}
}
} ;
System.setSecurityManager( securityManager ) ;
}
private static void enableSystemExitCall() {
System.setSecurityManager( null ) ;
}
Edit: Max points out in comments below that
as of Java 6, the permission name is actually "exitVM."+status, e.g. "exitVM.0".
However, the permission exitVM.* refers to all exit statuses, and exitVM is retained as a shorthand for exitVM.*, so the above code still works (see the documentation for RuntimePermission).
See my reply to How to avoid JFrame EXIT_ON_CLOSE operation to exit the entire application?.
Edit 1: The source that was linked. Demonstrates how to use a SecurityManager to prevent System.exit(n).
import java.awt.*;
import java.awt.event.*;
import java.security.Permission;
/** NoExit demonstrates how to prevent 'child'
applications from ending the VM with a call
to System.exit(0).
#author Andrew Thompson */
public class NoExit extends Frame implements ActionListener {
Button frameLaunch = new Button("Frame"),
exitLaunch = new Button("Exit");
/** Stores a reference to the original security manager. */
ExitManager sm;
public NoExit() {
super("Launcher Application");
sm = new ExitManager( System.getSecurityManager() );
System.setSecurityManager(sm);
setLayout(new GridLayout(0,1));
frameLaunch.addActionListener(this);
exitLaunch.addActionListener(this);
add( frameLaunch );
add( exitLaunch );
pack();
setSize( getPreferredSize() );
}
public void actionPerformed(ActionEvent ae) {
if ( ae.getSource()==frameLaunch ) {
TargetFrame tf = new TargetFrame();
} else {
// change back to the standard SM that allows exit.
System.setSecurityManager(
sm.getOriginalSecurityManager() );
// exit the VM when *we* want
System.exit(0);
}
}
public static void main(String[] args) {
NoExit ne = new NoExit();
ne.setVisible(true);
}
}
/** This example frame attempts to System.exit(0)
on closing, we must prevent it from doing so. */
class TargetFrame extends Frame {
static int x=0, y=0;
TargetFrame() {
super("Close Me!");
add(new Label("Hi!"));
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.out.println("Bye!");
System.exit(0);
}
});
pack();
setSize( getPreferredSize() );
setLocation(++x*10,++y*10);
setVisible(true);
}
}
/** Our custom ExitManager does not allow the VM
to exit, but does allow itself to be replaced by
the original security manager.
#author Andrew Thompson */
class ExitManager extends SecurityManager {
SecurityManager original;
ExitManager(SecurityManager original) {
this.original = original;
}
/** Deny permission to exit the VM. */
public void checkExit(int status) {
throw( new SecurityException() );
}
/** Allow this security manager to be replaced,
if fact, allow pretty much everything. */
public void checkPermission(Permission perm) {
}
public SecurityManager getOriginalSecurityManager() {
return original;
}
}
The previous code sample is partially correct, but I found that it ended up blocking my code's access to files. To get around that problem, I wrote my SecurityManager a little differently:
public class MySecurityManager extends SecurityManager {
private SecurityManager baseSecurityManager;
public MySecurityManager(SecurityManager baseSecurityManager) {
this.baseSecurityManager = baseSecurityManager;
}
#Override
public void checkPermission(Permission permission) {
if (permission.getName().startsWith("exitVM")) {
throw new SecurityException("System exit not allowed");
}
if (baseSecurityManager != null) {
baseSecurityManager.checkPermission(permission);
} else {
return;
}
}
}
In my case, I needed to prevent a 3rd party library from terminating the VM. But there were also some grails tests that were calling System.exit. So, I wrote my code so that it only activated the custom security manager immediately before the call to the 3rd party library (not a common event) and then immediately restored the original security manager, if any, afterwards.
It's all a little ugly. Ideally, I would have preferred to simply remove the System.exit code, but I do not have access to the 3rd party library's source code.
Using SecurityManager to disallow System.exit() calls is not perfect, for at least 2 reasons:
Java applications running with and without SecurityManager enabled are very different. That's why it needs to be turned off eventually, but it cannot be done with System.setSecurityManager(null). This call will lead to another security permission check, that will inevitably fail, because application code (SecurityManager subclass) is on the top of the calling stack.
All the Java applications are multi-threaded, and other threads can do various things between forbidSystemExitCall() and enableSystemExitCall(). Some of these things can be protected with security permission checks, which will fail for the very same reasons as described above. If checkExit() is overridden instead of [much more generic] checkPermission(), it will cover most of the cases, though.
The only way (that I know) to resolve this is to grant all the privileged to the SecurityManager subclass. It will very likely require it to be loaded by a separate class loader, e.g. bootstrap (null) class loader.