Bug 34229 - Need ability to intercept calls to System.setSecurityManager() from embedded environment
Summary: Need ability to intercept calls to System.setSecurityManager() from embedded ...
Status: NEW
Alias: None
Product: Ant
Classification: Unclassified
Component: Core tasks (show other bugs)
Version: 1.6.2
Hardware: All All
: P3 normal (vote)
Target Milestone: ---
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks: 33361
  Show dependency tree
 
Reported: 2005-03-30 00:04 UTC by Jesse Glick
Modified: 2013-01-21 19:19 UTC (History)
3 users (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jesse Glick 2005-03-30 00:04:32 UTC
Any kind of container which runs Ant in-VM, such as the NetBeans IDE, that has
its own SecurityManager already will need a way to intercept calls to
System.setSecurityManager() made from Ant's Permissions class, since the VM can
have only one global SM at a time. Currently attempting to use <java
fork="false"> in any mode which uses Permissions (incl. failonerror="true" in
Ant 1.6.x and always in 1.7) will just break with a SecurityException when run
in an embedded environment like this. Could be solved by providing a hook in Ant
letting the container manage some of the permissions, e.g. delegating from the
VM-wide master SM to a thread/threadgroup-specific SM provided by Ant.
Comment 1 Jesse Glick 2005-03-30 00:06:02 UTC
Cf. NetBeans bug:

http://www.netbeans.org/issues/show_bug.cgi?id=47645
Comment 2 Jesse Glick 2005-03-31 18:32:54 UTC
Cf. Java #5101798.
Comment 3 Steve Loughran 2005-04-01 00:00:25 UTC
Alternatively, we could try and set the security manager, catch the exception
and back off from the attempt, opting to fork the jvm instead. 
Comment 4 Kev Jackson 2005-04-01 04:01:32 UTC
> Alternatively, we could try and set the security manager, catch the exception
> and back off from the attempt, opting to fork the jvm instead. 
I know that this kind of "catch a semi-expected exception and alter behaviour"
is used frequently in the code, but is there no other way?  I personally feel
that using exceptions as a flow control mechanism is a code smell.

I'd prefer an adapter approach mentioned in the report

just my opinion
Kev
Comment 5 Steve Loughran 2005-04-01 12:01:03 UTC
Maybe both: an override for containers that know what they are doing, a
probe+backoff for containers that dont do anything clever.

Jesse, what kind of control mechanism do you propose? 
Comment 6 Jesse Glick 2005-04-01 22:17:35 UTC
Not sure yet. Maybe in Permissions:

public class Permissions {
    // ...
    /**
     * For containers which wish to intercept
     * {@link System.setSecurityManager} safely.
     */
    public interface SecurityManagerDelegator {
        void registerSecurityManager(SecurityManager);
        void unregisterSecurityManager();
    }
    public static void installSecurityManagerDelegator(SecurityManagerDelegator)
{...}
}

If P.iSMD were not called, Ant would do what it does now. If it were called,
Permissions.{set,restore}SecurityManager would delegate to the new interface.
This would - I hope - permit a container to manage Ant's SM implementation
intelligently, say by having the real global SM delegate to Ant's SM according
to the current thread group. But I would need to try writing a real P.SMD
implementation, say for NetBeans, to confirm that it can really work.

Note that the current code in Ant is not actually correct to begin with. You
might expect that the following script:

<?xml version="1.0"?>
<project name="34229-demo" default="x">
    <target name="x">
        <echo file="Pause.java">
public class Pause {
    public static void main(String[] args) throws Exception {
        int status = Integer.parseInt(args[0]);
        System.out.println("Will pause... (status: " + status + ")");
        Thread.sleep(2000);
        System.out.println("Done. (status: " + status + ")");
        System.exit(status);
    }
}
        </echo>
        <javac srcdir="." destdir="." includes="Pause.java"/>
        <parallel>
            <sequential>
                <java fork="false" classpath="." failonerror="true"
classname="Pause">
                    <arg value="0"/>
                </java>
            </sequential>
            <sequential>
                <sleep milliseconds="1000"/>
                <java fork="false" classpath="." failonerror="true"
classname="Pause">
                    <arg value="1"/>
                </java>
            </sequential>
        </parallel>
        <echo>OK??</echo>
    </target>
</project>

would when run from the command line (Ant 1.6.2) print

Will pause... (status: 0)
Will pause... (status: 1)
Done. (status: 0)
Done. (status: 1)
BUILD FAILED
/tmp/build.xml:24: Java returned: 1

since the second process finishes second and with a nonzero error code which
should throw a BuildException.

Instead, it prints only

Will pause... (status: 0)
Will pause... (status: 1)
Done. (status: 0)
Done. (status: 1)

and then exits *Ant's* VM abruptly (with code 1). That is because the sequence
of events is

- System.sSM(MySM) for process #0 before it starts
- System.sSM(MySM) for process #1 (overwriting #0's!) before it starts
- System.exit(0) from #0, which is trapped and causes <java> to finish
- System.sSM(null) (as stored by Permissions #0) after #0 finishes
- System.exit(1) from #1, which is not trapped since there is no SM

A contrived case, perhaps, but it shows that the logic in Permissions is wrong
already - it should be installing a multiplexing SM itself, and perhaps checking
the Thread of the caller.

Switching to forked mode as an option of last resort might be an option; perhaps
it would be a reasonable hot fix for Ant 1.6.3 until we can do better. I guess
ExecuteJava would need to catch SecurityException from Permissions.sSM and
switch to calling Java.fork(...) or something like that, and a similar fix for
JUnitTestRunner. The main problem is that running the app forked is not
completely transparent to the user; besides a performance hit, there might be
some specific behavior which the user needs unforked mode for, and it might be
confusing to magically switch to forked mode in some environments.
Comment 7 Jesse Glick 2009-07-30 06:43:23 UTC
BTW this is currently worked around in NetBeans by switching <java> to forked mode in all cases. While I'm sure this causes problems for somebody somewhere, I haven't heard any complaints yet.
Comment 8 Stock 2013-01-20 19:25:33 UTC
Hi all,

I'm using Ant, embedded in my application. Unfortunately when a JAVA task is executed, I'm not able to maintain my SecurityManager, during the java task execution.

Inside of my SecMan I've got all my logics to check if you are authorized or not.

Going into code, I've seen that everything should work the Permissions instance is null but it's initialized during the checkConfiguration method of Java class.

I think SecurityManagerDelegator could be the great solution, but I haven't seen anything in the code.

Have you planned it? Or is there any other workaround (not fork=true ..)

Of ocurse I can try to change by myself but I should change my ANT at every new release...

Thanks a lot!
Comment 9 Stock 2013-01-20 19:27:47 UTC
Hi all,

I'm using Ant, embedded in my application. Unfortunately when a JAVA task is executed, I'm not able to maintain my SecurityManager, during the java task execution.

Inside of my SecMan I've got all my logics to check if you are authorized or not.

Going into code, I've seen that everything should work the Permissions instance is null but it's initialized during the checkConfiguration method of Java class.

I think SecurityManagerDelegator could be the great solution, but I haven't seen anything in the code.

Have you planned it? Or is there any other workaround (not fork=true ..)

Of ocurse I can try to change by myself but I should change my ANT at every new release...

Thanks a lot!
Comment 10 Jesse Glick 2013-01-21 15:30:23 UTC
I am afraid there is no fix for this yet.
Comment 11 Stock 2013-01-21 19:19:17 UTC
Thanks a lot Jesse.

In the meantime I changed my class so now works perfectly!

CU