From: Adam W. <li...@co...> - 2005-09-09 07:04:53
|
Hi Peter, Long time no Lisp. Since we last communicated I've been using your editor J while learning a lot about Java and its standard library, all the while hoping that I will soon be able to use a saner language. I've found the file selection panel in J fantastic for quickly switching between the files I'm working upon. My favourite theme is "Bright". I'd like ABCL is be available as a CL implementation for running untrusted Java Web Start applications using the Java Network Launching Protocol (JNLP): <http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/contents.html> <http://java.sun.com/j2se/1.5.0/docs/guide/javaws/jnlp/index.html> This imposes a number of onerous restrictions, though the JNLP API provides a number of services that can ask the user whether a particular resource may be accessed, e.g. when attempting to open a local file (including whether to no longer ask the question a subsequent time). JNLP applications primarily access their resources within jar files. The jar file can hold anything but it must be accessed via a corresponding getClass().getClassLoader().getResource(String s). For example in my program I'm accessing some PNG icons in a resources subdirectory of a nz.net.consulting package and a getResource string becomes, e.g., "nz/net/consulting/resources/minus13.png". If ABCL compiled Lisp programs to jar files I suspect ABCL running in an untrusted environment would be able to load those jar files without necessarily invoking security exceptions. I'm at the point where an untrusted application can invoke an instance of the ABCL interpreter. I'd appreciate any comments about the best way to approach/the complexity of loading a compiled hello-world.lisp without the JVM throwing a security exception. Firstly one needs to start with a jnlp file, abcl.jnlp: <?xml version="1.0" encoding="UTF-8"?> <jnlp codebase="file:." href="abcl.jnlp"> <information> <title>ABCL</title> <vendor>(vendor)</vendor> </information> <resources> <j2se version="1.6+"/> <jar href="file:/home/.../abcl-ext.jar"/> <jar href="file:/home/.../j.jar"/> </resources> <application-desc main-class="Abcl"/> </jnlp> abcl-ext.jar is the name of the jar file I'll be using to invoke ABCL. j.jar contains, of course, ABCL. The paths need to be fixed up. This jnlp file permits testing the Java Web Start application in the current directory without needing a web server. I've been using Mustang for testing. It includes significant changes to Java Web Start: <http://weblogs.java.net/blog/stanleyh/archive/2005/06/deployment_new_1.html> <http://download.java.net/jdk6/binaries/> This is my class file which invokes ABCL: import org.armedbear.lisp.*; public class Abcl { public static void main(String[] args) { Interpreter interpreter=Interpreter.createInstance(); } } As you can see it just creates an instance of the interpreter. It is transformed into a jar file via the commands: javac -cp /path/to/j.jar Abcl.java && jar cf abcl-ext.jar Abcl.class Following are the modifications I made to ABCL to avoid a security exception from trying to read the user directory. I add an :UNTRUSTED keyword to the features to inform a Lisp program that it is running in an untrusted environment. I moved the location of the *features* code to achieve this. $ diff -ru ../../../../../upstream/src/org/armedbear/lisp/ ./ | grep -v 'Only in \./' diff -ru ../../../../../upstream/src/org/armedbear/lisp/Keyword.java ./Keyword.java --- ../../../../../upstream/src/org/armedbear/lisp/Keyword.java 2005-03-20 02:29:34.000000000 +1200 +++ ./Keyword.java 2005-09-09 15:58:47.000000000 +1200 @@ -102,6 +102,7 @@ TYPE = internKeyword("TYPE"), UNIX = internKeyword("UNIX"), UNSPECIFIC = internKeyword("UNSPECIFIC"), + UNTRUSTED = internKeyword("UNTRUSTED"), UP = internKeyword("UP"), UPCASE = internKeyword("UPCASE"), USE = internKeyword("USE"), diff -ru ../../../../../upstream/src/org/armedbear/lisp/Lisp.java ./Lisp.java --- ../../../../../upstream/src/org/armedbear/lisp/Lisp.java 2005-09-09 06:29:40.000000000 +1200 +++ ./Lisp.java 2005-09-09 16:48:26.000000000 +1200 @@ -1734,11 +1734,56 @@ symbol.setConstant(true); return symbol; } + + // ### *features* + public static final Symbol _FEATURES_ = + exportSpecial("*FEATURES*", PACKAGE_CL, null); + static { + String osName = System.getProperty("os.name"); + if (osName.startsWith("Linux")) { + _FEATURES_.setSymbolValue(list6(Keyword.ARMEDBEAR, + Keyword.ABCL, + Keyword.COMMON_LISP, + Keyword.ANSI_CL, + Keyword.UNIX, + Keyword.LINUX)); + } else if (osName.startsWith("SunOS")) { + _FEATURES_.setSymbolValue(list6(Keyword.ARMEDBEAR, + Keyword.ABCL, + Keyword.COMMON_LISP, + Keyword.ANSI_CL, + Keyword.UNIX, + Keyword.SUNOS)); + } else if (osName.startsWith("Mac OS X")) { + _FEATURES_.setSymbolValue(list6(Keyword.ARMEDBEAR, + Keyword.ABCL, + Keyword.COMMON_LISP, + Keyword.ANSI_CL, + Keyword.UNIX, + Keyword.DARWIN)); + } else if (osName.startsWith("Windows")) { + _FEATURES_.setSymbolValue(list5(Keyword.ARMEDBEAR, + Keyword.ABCL, + Keyword.COMMON_LISP, + Keyword.ANSI_CL, + Keyword.WINDOWS)); + } else { + _FEATURES_.setSymbolValue(list4(Keyword.ARMEDBEAR, + Keyword.ABCL, + Keyword.COMMON_LISP, + Keyword.ANSI_CL)); + } + } public static final Symbol _DEFAULT_PATHNAME_DEFAULTS_ = exportSpecial("*DEFAULT-PATHNAME-DEFAULTS*", PACKAGE_CL, null); static { - String userDir = System.getProperty("user.dir"); + String userDir=""; + try {userDir = System.getProperty("user.dir");} + catch(SecurityException e) { + _FEATURES_.setSymbolValue( + new Cons(Keyword.UNTRUSTED, _FEATURES_.getSymbolValue())); + } if (userDir != null && userDir.length() > 0) { if (userDir.charAt(userDir.length() - 1) != File.separatorChar) userDir = userDir.concat(File.separator); @@ -1858,46 +1903,6 @@ public static final Symbol _READ_EVAL_ = exportSpecial("*READ-EVAL*", PACKAGE_CL, T); - // ### *features* - public static final Symbol _FEATURES_ = - exportSpecial("*FEATURES*", PACKAGE_CL, null); - static { - String osName = System.getProperty("os.name"); - if (osName.startsWith("Linux")) { - _FEATURES_.setSymbolValue(list6(Keyword.ARMEDBEAR, - Keyword.ABCL, - Keyword.COMMON_LISP, - Keyword.ANSI_CL, - Keyword.UNIX, - Keyword.LINUX)); - } else if (osName.startsWith("SunOS")) { - _FEATURES_.setSymbolValue(list6(Keyword.ARMEDBEAR, - Keyword.ABCL, - Keyword.COMMON_LISP, - Keyword.ANSI_CL, - Keyword.UNIX, - Keyword.SUNOS)); - } else if (osName.startsWith("Mac OS X")) { - _FEATURES_.setSymbolValue(list6(Keyword.ARMEDBEAR, - Keyword.ABCL, - Keyword.COMMON_LISP, - Keyword.ANSI_CL, - Keyword.UNIX, - Keyword.DARWIN)); - } else if (osName.startsWith("Windows")) { - _FEATURES_.setSymbolValue(list5(Keyword.ARMEDBEAR, - Keyword.ABCL, - Keyword.COMMON_LISP, - Keyword.ANSI_CL, - Keyword.WINDOWS)); - } else { - _FEATURES_.setSymbolValue(list4(Keyword.ARMEDBEAR, - Keyword.ABCL, - Keyword.COMMON_LISP, - Keyword.ANSI_CL)); - } - } - // ### *modules* public static final Symbol _MODULES_ = exportSpecial("*MODULES*", PACKAGE_CL, NIL); The JNLP application can then be invoked with the command $JAVA_HOME/bin/javaws abcl.jnlp (within the same directory as abcl.jnlp). The program will start up, be verified, execute an Interpreter instance and close without throwing a security exception. I suspect that if the components of a compiled lisp file (._ and .cls) were a valid jar file then ABCL could load them via the getResource mechanism without a security exception being throw for trivial cases. Could ABCL perhaps support this? Many thanks, Adam |
From: Peter G. <pe...@ar...> - 2005-09-09 16:46:43
|
On Fri, 09 Sep 2005 at 19:02:43 +1200, Adam Warner wrote: > I suspect that if the components of a compiled lisp file (._ and .cls) > were a valid jar file then ABCL could load them via the getResource > mechanism without a security exception being throw for trivial cases. > Could ABCL perhaps support this? First of all, the changes you made to abcl itself seem trivial and impose no performance penalty, so I'm not opposed to applying them, but I'd rather not do it unless we end up going somewhere with this, just to avoid introducing gratuitous obscurities in the code. That said, I'm not quite sure what you're suggesting. A compiled Lisp file foo.abcl _is_ a jar file, without the .jar extension. foo._ is a Lisp source file, albeit a rather specialized one. The foo*.cls files are normal Java class files, with the extension =2Ecls instead of .class. You seem to be saying that you'd like foo._ and foo*.cls to be separate =2Ejar files, so that foo.abcl would be a jar file containing a whole bunch of jar files inside it, which seems a tad insane. Before going any further, do I understand you correctly here? [The current code in Lisp.java supports three situations, if I recall correctly: 1. Loading an uncompressed (old-style) .abcl file from j.jar or abcl.jar 2. Loading an uncompressed (old-style) .abcl file from the file system 3. Loading a compressed (new-style) .abcl file from the file system When I added support for compressed .abcl files, I considered the possibility of putting compressed .abcl files in j.jar and abcl.jar (which now contain only uncompressed .abcl and .cls files). That looked like it would be make the implementation of loadCompiledFunction() even more complicated than it is now, and very likely it would make things slower as well, so I gave up on the idea. I mention this because I think any new scheme we come up with needs to continue to support those three situations, at least for the near future.] Please excuse me if I've totally misunderstood what you're suggesting, which I think is quite likely. -Peter |
From: Adam W. <li...@co...> - 2005-09-10 09:37:16
|
On Fri, 09 Sep 2005 09:46:34 -0700, Peter Graves wrote: > On Fri, 09 Sep 2005 at 19:02:43 +1200, Adam Warner wrote: >> I suspect that if the components of a compiled lisp file (._ and .cls) >> were a valid jar file then ABCL could load them via the getResource >> mechanism without a security exception being throw for trivial cases. >> Could ABCL perhaps support this? > > First of all, the changes you made to abcl itself seem trivial and > impose no performance penalty, so I'm not opposed to applying them, but > I'd rather not do it unless we end up going somewhere with this, just > to avoid introducing gratuitous obscurities in the code. > > That said, I'm not quite sure what you're suggesting. > > A compiled Lisp file foo.abcl _is_ a jar file, without the .jar > extension. foo._ is a Lisp source file, albeit a rather specialized > one. The foo*.cls files are normal Java class files, with the extension > .cls instead of .class. Thanks for your response Peter! This is excellent news. I've got a broken demo running that should indicate what's needed: <http://consulting-net-nz.vpsland.com:8080/> Everything is compiled for Java 5.0. I'm still using a Mustang (6.0 beta) client though this should not be critical. As it stands if I execute <http://consulting-net-nz.vpsland.com:8080/abcl-app.jnlp> via javaws everything downloads but this exception is thrown: java.security.AccessControlException: access denied (java.io.FilePermission /message.abcl read) This is obviously correct because I need to load message.abcl from <http://consulting-net-nz.vpsland.com:8080/message.abcl>, not the local filesystem. I see two potential solutions: 1. An interface to Load to open the jar file resource message._ (instead of checking the local file system for message.abcl). 2. Load.load to also accept java.net.URL references to compiled programs. I suspect 1 will be easier to implement than 2 because 1 leverages the fact that compressed .abcl files are already jar files. Note a namespace issue with solution 1: All compressed .abcl files simultaneously referenced as jar files will have to be uniquely named (even if they are at different URLs) since the resource names are based upon the file name and they are currently compressed without a package path. Here's a description of what's available at <http://consulting-net-nz.vpsland.com:8080/abcl-app.jnlp>: abcl-app.jnlp: This XML file specifies the jar files to download and the static Message.main() method to execute. Message.java: The static main method is supposed to load message.abcl. message.abcl will call Message(String s) with a custom message. Message.java is compiled into message-launcher.jar via the build.sh script. j.jar is built from the slightly modified source code I described yesterday. message.lisp is the source code to message.abcl. When Message.main() loads the resources correctly a message will be displayed that ABCL is running as an untrusted application. Regards, Adam |
From: Peter G. <pe...@ar...> - 2005-09-10 16:43:22
|
On Sat, 10 Sep 2005 at 21:35:05 +1200, Adam Warner wrote: > I see two potential solutions: > > 1. An interface to Load to open the jar file resource message._ > (instead of checking the local file system for message.abcl). > > 2. Load.load to also accept java.net.URL references to compiled programs. > > I suspect 1 will be easier to implement than 2 because 1 leverages the > fact that compressed .abcl files are already jar files. Note a namespace > issue with solution 1: All compressed .abcl files simultaneously > referenced as jar files will have to be uniquely named (even if they are > at different URLs) since the resource names are based upon the file name > and they are currently compressed without a package path. Right now, .abcl files are in fact .jar files, but I'm not sure that will always be the case, so I'd rather not base anything on that premise. An implementation's fasl format is not a public interface. The stuff in Load.java is not intended to be a public interface either. (This makes me realize that I've clearly created the wrong impression by having a lot of "public" methods in the org.armedbear.lisp package. All these methods are public as a matter of convenience and/or laziness on my part, rather than out of a deliberate decision that they are part of abcl's public interface. Some of them may eventually become part of the documented public interface, but I haven't audited any of them with that in mind. This is part of the work that still needs to be done on the road to ABCL 0.1.) I'd rather approach the problem at the level of CL:LOAD, or maybe CL:OPEN. CL:LOAD is already specified by ANSI to accept a stream argument as well as a pathname designating a local file, and abcl supports this (although it hasn't been tested much and is likely to be buggy). So if you have a stream, you're good to go, modulo bugs. Currently you can use CL:OPEN or EXT:MAKE-SOCKET to get a stream, but there's no reason why we couldn't add EXT:MAKE-STREAM-FROM-RESOURCE, which would wrap java.lang.Class.getResourceAsStream() to return a Lisp stream. (I'm not sure I like that exact name, but that's a minor problem.) There's also some code in Pathname.java that provides a tiny bit of support for a jar device. Right now I think it's only used for display purposes, to indicate which files came from abcl.jar, as opposed to the local file system, when *COMPILE-VERBOSE* and/or *AUTOLOAD-VERBOSE* is true. But the concept could be extended, and CL:OPEN could learn how to open files within a jar file and return a proper Lisp stream. As a proof of concept, something like the following (which I haven't even tried to compile, let alone run) might work right now, or at least expose the bugs that would need to be fixed: public static void main(String[] args) { Class c = Message.class; String name = "message.abcl"; try { Symbol.LOAD.execute( new org.armedbear.lisp.Stream(c.getResourceAsStream(name), Lisp.UNSIGNED_BYTE_8))); } catch (Throwable t) {} } -Peter |
From: Adam W. <li...@co...> - 2005-09-10 23:43:39
|
On Sat, 10 Sep 2005 09:43:15 -0700, Peter Graves wrote: > On Sat, 10 Sep 2005 at 21:35:05 +1200, Adam Warner wrote: >> I see two potential solutions: >> >> 1. An interface to Load to open the jar file resource message._ >> (instead of checking the local file system for message.abcl). >> >> 2. Load.load to also accept java.net.URL references to compiled programs. >> >> I suspect 1 will be easier to implement than 2 because 1 leverages the >> fact that compressed .abcl files are already jar files. Note a namespace >> issue with solution 1: All compressed .abcl files simultaneously >> referenced as jar files will have to be uniquely named (even if they are >> at different URLs) since the resource names are based upon the file name >> and they are currently compressed without a package path. > > Right now, .abcl files are in fact .jar files, but I'm not sure that > will always be the case, so I'd rather not base anything on that > premise. An implementation's fasl format is not a public interface. > > The stuff in Load.java is not intended to be a public interface either. > > (This makes me realize that I've clearly created the wrong impression > by having a lot of "public" methods in the org.armedbear.lisp package. > All these methods are public as a matter of convenience and/or laziness > on my part, rather than out of a deliberate decision that they are part > of abcl's public interface. Some of them may eventually become part of > the documented public interface, but I haven't audited any of them with > that in mind. This is part of the work that still needs to be done on > the road to ABCL 0.1.) I'm fine with this. I've already experienced how non-public methods can be a hassle to work with, especially when debugging. > I'd rather approach the problem at the level of CL:LOAD, or maybe > CL:OPEN. > > CL:LOAD is already specified by ANSI to accept a stream argument as > well as a pathname designating a local file, and abcl supports this > (although it hasn't been tested much and is likely to be buggy). So if > you have a stream, you're good to go, modulo bugs. > > Currently you can use CL:OPEN or EXT:MAKE-SOCKET to get a stream, but > there's no reason why we couldn't add EXT:MAKE-STREAM-FROM-RESOURCE, > which would wrap java.lang.Class.getResourceAsStream() to return a Lisp > stream. (I'm not sure I like that exact name, but that's a minor > problem.) > > There's also some code in Pathname.java that provides a tiny bit of > support for a jar device. Right now I think it's only used for display > purposes, to indicate which files came from abcl.jar, as opposed to the > local file system, when *COMPILE-VERBOSE* and/or *AUTOLOAD-VERBOSE* is > true. But the concept could be extended, and CL:OPEN could learn how to > open files within a jar file and return a proper Lisp stream. > > As a proof of concept, something like the following (which I haven't > even tried to compile, let alone run) might work right now, or at least > expose the bugs that would need to be fixed: > > public static void main(String[] args) > { > Class c = Message.class; > String name = "message.abcl"; > try { > Symbol.LOAD.execute( > new org.armedbear.lisp.Stream(c.getResourceAsStream(name), > Lisp.UNSIGNED_BYTE_8))); > } > catch (Throwable t) {} > } Thanks Peter, this does expose a bug. Here's my new Message.java: import javax.swing.*; import org.armedbear.lisp.*; public class Message { public Message(String s) { JFrame frame=new JFrame(); JLabel label=new JLabel(s); frame.getContentPane().add(label); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { Interpreter interpreter=Interpreter.createInstance(); Class cls=Message.class; String name="message.abcl"; java.io.InputStream inputStream=cls.getResourceAsStream(name); org.armedbear.lisp.Stream lispStream= new org.armedbear.lisp.Stream(inputStream, Lisp.UNSIGNED_BYTE_8); try { Symbol.LOAD.execute(lispStream); } catch(Throwable e) { throw new RuntimeException(e); } } } The result is this stack trace (j.jar is now compiled with debugging info): java.lang.RuntimeException: org.armedbear.lisp.ConditionThrowable at Message.main(Message.java:26) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at com.sun.javaws.Launcher.executeApplication(Launcher.java:1167) at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1113) at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:964) at com.sun.javaws.Launcher.run(Launcher.java:104) at java.lang.Thread.run(Thread.java:608) Caused by: org.armedbear.lisp.ConditionThrowable at org.armedbear.lisp.Primitives$72.execute(Primitives.java:1405) at org.armedbear.lisp.Primitive.execute(Primitive.java:83) at org.armedbear.lisp.Symbol.execute(Symbol.java:847) at org.armedbear.lisp.Lisp.signal(Lisp.java:312) at org.armedbear.lisp.Symbol.signalNPE(Symbol.java:959) at org.armedbear.lisp.Symbol.execute(Symbol.java:850) at Message.main(Message.java:23) ... 9 more The failure arises in line 850 of Symbol.java caused by the method public LispObject execute(LispObject arg) throws ConditionThrowable { try { return function.execute(arg); } catch (NullPointerException e) { return signalNPE(e); } } This indicates an error in the object dispatch. It is unlikely an org.armedbear.lisp.Stream object would have defined a LispObject function slot to execute. Maybe execute needs to be overloaded with an org.armedbear.lisp.Stream argument? The great news is that this is the first exception that Java Web Start throws (in particular, building the lisp Stream from the fasl file did not throw a security exception!) Thanks again, Adam |
From: Peter G. <pe...@ar...> - 2005-09-11 05:40:34
|
On Sun, 11 Sep 2005 at 11:42:02 +1200, Adam Warner wrote: > Thanks Peter, this does expose a bug. Here's my new Message.java: > > import javax.swing.*; > import org.armedbear.lisp.*; > > public class Message { > > public Message(String s) { > JFrame frame=new JFrame(); > JLabel label=new JLabel(s); > frame.getContentPane().add(label); > frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); > frame.pack(); > frame.setVisible(true); > } > > public static void main(String[] args) { > Interpreter interpreter=Interpreter.createInstance(); > Class cls=Message.class; > String name="message.abcl"; > java.io.InputStream inputStream=cls.getResourceAsStream(name); > org.armedbear.lisp.Stream lispStream= > new org.armedbear.lisp.Stream(inputStream, Lisp.UNSIGNED_BYTE_8); > try { > Symbol.LOAD.execute(lispStream); > } > catch(Throwable e) { > throw new RuntimeException(e); > } > } > } > > The result is this stack trace (j.jar is now compiled with debugging info): > > java.lang.RuntimeException: org.armedbear.lisp.ConditionThrowable > at Message.main(Message.java:26) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) > at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) > at java.lang.reflect.Method.invoke(Method.java:585) > at com.sun.javaws.Launcher.executeApplication(Launcher.java:1167) > at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1113) > at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:964) > at com.sun.javaws.Launcher.run(Launcher.java:104) > at java.lang.Thread.run(Thread.java:608) > Caused by: org.armedbear.lisp.ConditionThrowable > at org.armedbear.lisp.Primitives$72.execute(Primitives.java:1405) > at org.armedbear.lisp.Primitive.execute(Primitive.java:83) > at org.armedbear.lisp.Symbol.execute(Symbol.java:847) > at org.armedbear.lisp.Lisp.signal(Lisp.java:312) > at org.armedbear.lisp.Symbol.signalNPE(Symbol.java:959) > at org.armedbear.lisp.Symbol.execute(Symbol.java:850) > at Message.main(Message.java:23) > ... 9 more > > The failure arises in line 850 of Symbol.java caused by the method > > public LispObject execute(LispObject arg) throws ConditionThrowable > { > try { > return function.execute(arg); > } > catch (NullPointerException e) { > return signalNPE(e); > } > } > > This indicates an error in the object dispatch. It is unlikely an > org.armedbear.lisp.Stream object would have defined a LispObject function > slot to execute. Maybe execute needs to be overloaded with an > org.armedbear.lisp.Stream argument? No, execute() takes a LispObject argument, and a Stream is a LispObject, so the function dispatch is correct. The NPE occurs because the function slot of the LOAD symbol is null. You need to call Interpreter.initializeLisp(false) right after Interpreter.createInstance(). initializeLisp() loads boot.lisp, which loads autoloads.lisp, which initializes the function slots of all the symbols to be autoloaded, of which LOAD is one. All of this stuff needs to be cleaned up and documented, and it's on the list of things to be done for 0.1; you're just a bit ahead of the game... :) -Peter |
From: Adam W. <li...@co...> - 2005-09-11 07:41:01
|
On Sat, 10 Sep 2005 22:40:15 -0700, Peter Graves wrote: > No, execute() takes a LispObject argument, and a Stream is a > LispObject, so the function dispatch is correct. > > The NPE occurs because the function slot of the LOAD symbol is null. > > You need to call Interpreter.initializeLisp(false) right after > Interpreter.createInstance(). initializeLisp() loads boot.lisp, which > loads autoloads.lisp, which initializes the function slots of all the > symbols to be autoloaded, of which LOAD is one. > > All of this stuff needs to be cleaned up and documented, and it's on > the list of things to be done for 0.1; you're just a bit ahead of the > game... :) (Thanks, I trust you'll let me know if this is becoming too distracting) Interpreter.initializeLisp(false) appears insufficient for autoloading the function slots (the identical NPE@Symbol.java:850 occurs). The interpreter method run(String[] args) includes a lot more initialisation, including a call to Interpreter.initializeTopLevel(). I subsequently added this call (after recompiling it as a public method) and the same NPE occurs. I've tried to import other functionality from run(String[] args). Here is my final attempt at the time of writing this reply: import javax.swing.*; import org.armedbear.lisp.*; public class Message { public Message(String s) { JFrame frame=new JFrame(); JLabel label=new JLabel(s); frame.getContentPane().add(label); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { Interpreter interpreter=Interpreter.createInstance(); final LispThread thread = LispThread.currentThread(); Interpreter.initializeLisp(false); Interpreter.initializeTopLevel(); try { thread.execute(Lisp.PACKAGE_SYS.intern("PRELOAD-PACKAGE"), Lisp.PACKAGE_CL); thread.execute(Lisp.PACKAGE_CL.intern("REQUIRE"), new SimpleString("LOOP")); thread.execute(Lisp.PACKAGE_SYS.intern("PRELOAD-PACKAGE"), Lisp.PACKAGE_SYS); } catch(org.armedbear.lisp.ConditionThrowable e) { throw new RuntimeException(e); } Class cls=Message.class; String name="message.abcl"; java.io.InputStream inputStream=cls.getResourceAsStream(name); org.armedbear.lisp.Stream lispStream= new org.armedbear.lisp.Stream(inputStream, Lisp.UNSIGNED_BYTE_8); try { Symbol.LOAD.execute(lispStream); } catch(Throwable e) { throw new RuntimeException(e); } } } A similar exception occurs: java.lang.RuntimeException: org.armedbear.lisp.ConditionThrowable at Message.main(Message.java:29) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at com.sun.javaws.Launcher.executeApplication(Launcher.java:1167) at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1113) at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:964) at com.sun.javaws.Launcher.run(Launcher.java:104) at java.lang.Thread.run(Thread.java:608) Caused by: org.armedbear.lisp.ConditionThrowable at org.armedbear.lisp.Primitives$72.execute(Primitives.java:1405) at org.armedbear.lisp.Primitive.execute(Primitive.java:83) at org.armedbear.lisp.Symbol.execute(Symbol.java:847) at org.armedbear.lisp.Lisp.signal(Lisp.java:312) at org.armedbear.lisp.Symbol.signalNPE(Symbol.java:959) at org.armedbear.lisp.Symbol.execute(Symbol.java:850) at org.armedbear.lisp.LispThread.execute(LispThread.java:604) at Message.main(Message.java:21) ... 9 more Regards, Adam |
From: Peter G. <pe...@ar...> - 2005-09-11 13:17:04
|
On Sun, 11 Sep 2005 at 19:39:28 +1200, Adam Warner wrote: > Interpreter.initializeLisp(false) appears insufficient for autoloading the > function slots (the identical NPE@Symbol.java:850 occurs). The interpreter > method run(String[] args) includes a lot more initialisation, including a > call to Interpreter.initializeTopLevel(). I subsequently added this call > (after recompiling it as a public method) and the same NPE occurs. Which suggests that the additional initialization you added isn't helping. I think initializeLisp(false) should be enough. > I've tried to import other functionality from run(String[] args). Here is > my final attempt at the time of writing this reply: > > import javax.swing.*; > import org.armedbear.lisp.*; > > public class Message { > > public Message(String s) { > JFrame frame=new JFrame(); > JLabel label=new JLabel(s); > frame.getContentPane().add(label); > frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); > frame.pack(); > frame.setVisible(true); > } > > public static void main(String[] args) { > Interpreter interpreter=Interpreter.createInstance(); > final LispThread thread = LispThread.currentThread(); > Interpreter.initializeLisp(false); > Interpreter.initializeTopLevel(); > try { > thread.execute(Lisp.PACKAGE_SYS.intern("PRELOAD-PACKAGE"), > Lisp.PACKAGE_CL); > thread.execute(Lisp.PACKAGE_CL.intern("REQUIRE"), > new SimpleString("LOOP")); > thread.execute(Lisp.PACKAGE_SYS.intern("PRELOAD-PACKAGE"), > Lisp.PACKAGE_SYS); > } > catch(org.armedbear.lisp.ConditionThrowable e) { > throw new RuntimeException(e); > } > Class cls=Message.class; > String name="message.abcl"; > java.io.InputStream inputStream=cls.getResourceAsStream(name); > org.armedbear.lisp.Stream lispStream= > new org.armedbear.lisp.Stream(inputStream, Lisp.UNSIGNED_BYTE_8); > try { > Symbol.LOAD.execute(lispStream); > } > catch(Throwable e) { > throw new RuntimeException(e); > } > } > } > > > A similar exception occurs: > > java.lang.RuntimeException: org.armedbear.lisp.ConditionThrowable > at Message.main(Message.java:29) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) > at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) > at java.lang.reflect.Method.invoke(Method.java:585) > at com.sun.javaws.Launcher.executeApplication(Launcher.java:1167) > at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1113) > at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:964) > at com.sun.javaws.Launcher.run(Launcher.java:104) > at java.lang.Thread.run(Thread.java:608) > Caused by: org.armedbear.lisp.ConditionThrowable > at org.armedbear.lisp.Primitives$72.execute(Primitives.java:1405) > at org.armedbear.lisp.Primitive.execute(Primitive.java:83) > at org.armedbear.lisp.Symbol.execute(Symbol.java:847) > at org.armedbear.lisp.Lisp.signal(Lisp.java:312) > at org.armedbear.lisp.Symbol.signalNPE(Symbol.java:959) > at org.armedbear.lisp.Symbol.execute(Symbol.java:850) > at org.armedbear.lisp.LispThread.execute(LispThread.java:604) > at Message.main(Message.java:21) > ... 9 more The line numbers in the Java backtrace seems to suggest that the error is happening in this line of code: thread.execute(Lisp.PACKAGE_SYS.intern("PRELOAD-PACKAGE"), Lisp.PACKAGE_CL); And it's a signalNPE(), so that probably means that the function slot of the symbol SYS::PRELOAD-PACKAGE hasn't been initialized. SYS::PRELOAD-PACKAGE is defined at line 307 of boot.lisp, and boot.lisp should be loaded by initializeLisp(false). So it appears that either boot.lisp isn't getting loaded at all, or possibly some other error (which for reasons unknown isn't getting reported at the Java level) is occurring during the loading of boot.lisp which prevents the loading of boot.lisp from reaching line 307. It's also possible (but less likely, I think) that SYS::PRELOAD-PACKAGE is initialized correctly, but some other symbol that is used when PRELOAD-PACKAGE runs is not. If you can figure out a way to capture stdout (maybe it just works, since you've got some way to see the Java backtraces), you might try enabling more verbose output at the top of boot.lisp: (setq *autoload-verbose* t) (setq *load-verbose* t) and/or add a line to signalNPE() in Symbol.java to print out the name of the uninitialized symbol: private final LispObject signalNPE(NullPointerException e) throws ConditionThrowable { + Debug.trace("signalNPE symbol = " + symbol.getName()); if (function == null) return signal(new UndefinedFunction(this)); Debug.trace(e); return signal(new LispError("Null pointer exception")); } By the way, you shouldn't need to be doing the PRELOAD-PACKAGE stuff at all, and in fact I should probably just get rid of it. That code was added at a time before abcl could build sbcl and I suspected that some malfunction in the autoload mechanism might be the problem, but that turned out not to be the case. I haven't used PRELOAD-PACKAGE in months and abcl builds sbcl just fine without it. But on the other hand PRELOAD-PACKAGE shouldn't cause any problems, either, and I just verified that it works correctly with the current code in my tree (you can test that for yourself by starting abcl with the --preload option). -Peter |
From: Adam W. <li...@co...> - 2005-09-12 07:47:30
|
On Sun, 11 Sep 2005 06:16:55 -0700, Peter Graves wrote: > The line numbers in the Java backtrace seems to suggest that the error > is happening in this line of code: > > thread.execute(Lisp.PACKAGE_SYS.intern("PRELOAD-PACKAGE"), > Lisp.PACKAGE_CL); > > And it's a signalNPE(), so that probably means that the function slot > of the symbol SYS::PRELOAD-PACKAGE hasn't been initialized. > > SYS::PRELOAD-PACKAGE is defined at line 307 of boot.lisp, and boot.lisp > should be loaded by initializeLisp(false). > > So it appears that either boot.lisp isn't getting loaded at all, or > possibly some other error (which for reasons unknown isn't getting > reported at the Java level) is occurring during the loading of > boot.lisp which prevents the loading of boot.lisp from reaching line > 307. > > It's also possible (but less likely, I think) that SYS::PRELOAD-PACKAGE > is initialized correctly, but some other symbol that is used when > PRELOAD-PACKAGE runs is not. > > If you can figure out a way to capture stdout (maybe it just works, > since you've got some way to see the Java backtraces), you might try > enabling more verbose output at the top of boot.lisp: Java Web Start applications don't have a console. The backtrace I pasted in comes from the Details tab of the application termination dialogue box. > (setq *autoload-verbose* t) > (setq *load-verbose* t) > > and/or add a line to signalNPE() in Symbol.java to print out the name > of the uninitialized symbol: > > private final LispObject signalNPE(NullPointerException e) > throws ConditionThrowable > { > + Debug.trace("signalNPE symbol = " + symbol.getName()); This didn't compile. Did you mean name.writeToString()? Once you update me with the code I can have another go. I'm building a label to display the message: private final LispObject signalNPE(NullPointerException e) throws ConditionThrowable { java.awt.Toolkit.getDefaultToolkit().beep(); javax.swing.JFrame frame=new javax.swing.JFrame(); javax.swing.JLabel label=new javax.swing.JLabel("signalNPE symbol = " + name.writeToString()); frame.getContentPane().add(label); frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); Debug.trace("signalNPE symbol = " + name.writeToString()); if (function == null) return signal(new UndefinedFunction(this)); Debug.trace(e); return signal(new LispError("Null pointer exception")); } The message is currently symbolNPE symbol = "PRELOAD-PACKAGE". > By the way, you shouldn't need to be doing the PRELOAD-PACKAGE stuff at > all, and in fact I should probably just get rid of it. That code was > added at a time before abcl could build sbcl and I suspected that some > malfunction in the autoload mechanism might be the problem, but that > turned out not to be the case. I haven't used PRELOAD-PACKAGE in months > and abcl builds sbcl just fine without it. But on the other hand > PRELOAD-PACKAGE shouldn't cause any problems, either, and I just > verified that it works correctly with the current code in my tree (you > can test that for yourself by starting abcl with the --preload option). Right. No problem here: $ java org.armedbear.lisp.Main --preload --noinit Armed Bear Common Lisp 0.0.8+ (built Mon Sep 12 2005 19:23:16 NZST) Java 1.5.0_04 Sun Microsystems Inc. Java HotSpot(TM) Client VM Low-level initialization completed in 1.013 seconds. Startup completed in 3.188 seconds. Preloading #<PACKAGE "COMMON-LISP"> Preloading #<PACKAGE "SYSTEM"> Type :HELP for a list of available commands. CL-USER(1): Regards, Adam |
From: Peter G. <pe...@ar...> - 2005-09-12 10:25:23
|
On Mon, 12 Sep 2005 at 19:44:23 +1200, Adam Warner wrote: > On Sun, 11 Sep 2005 06:16:55 -0700, Peter Graves wrote: > > If you can figure out a way to capture stdout (maybe it just works, > > since you've got some way to see the Java backtraces), you might try > > enabling more verbose output at the top of boot.lisp: > > Java Web Start applications don't have a console. The backtrace I pasted > in comes from the Details tab of the application termination dialogue box. I was afraid of that. > > (setq *autoload-verbose* t) > > (setq *load-verbose* t) > > > > and/or add a line to signalNPE() in Symbol.java to print out the name > > of the uninitialized symbol: > > > > private final LispObject signalNPE(NullPointerException e) > > throws ConditionThrowable > > { > > + Debug.trace("signalNPE symbol = " + symbol.getName()); > > This didn't compile. Did you mean name.writeToString()? > Once you update me with the code I can have another go. I'm building a > label to display the message: > > private final LispObject signalNPE(NullPointerException e) > throws ConditionThrowable > { > java.awt.Toolkit.getDefaultToolkit().beep(); > javax.swing.JFrame frame=new javax.swing.JFrame(); > javax.swing.JLabel label=new javax.swing.JLabel("signalNPE symbol = " + > name.writeToString()); > frame.getContentPane().add(label); > frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); > frame.pack(); > frame.setVisible(true); > Debug.trace("signalNPE symbol = " + name.writeToString()); > if (function == null) > return signal(new UndefinedFunction(this)); > Debug.trace(e); > return signal(new LispError("Null pointer exception")); > } Sorry, what I intended was: Debug.trace("signalNPE symbol = " + getName()); But name.writeToString() should amount to the same thing. > The message is currently symbolNPE symbol = "PRELOAD-PACKAGE". So indeed the code at the bottom of boot.lisp where PRELOAD-PACKAGE is defined isn't being executed. We need to figure out why that's happening. Since you don't have a console, you might want to write your own non- console version of Debug.trace(), which would basically be the code you added to signalNPE(), and then use that to add some debugging output to the version of loadSystemFile() that starts at Load.java:197. Note that boot.lisp, and the system files that it loads, are loaded by loadSystemFile() rather than by load(). -Peter |
From: Adam W. <li...@co...> - 2005-09-13 11:08:09
|
On Mon, 12 Sep 2005 03:24:39 -0700, Peter Graves wrote: > Since you don't have a console, you might want to write your own non- > console version of Debug.trace(), which would basically be the code you > added to signalNPE(), and then use that to add some debugging output to > the version of loadSystemFile() that starts at Load.java:197. Note that > boot.lisp, and the system files that it loads, are loaded by > loadSystemFile() rather than by load(). Many thanks Peter for the excellent advice and this debugging plan. I now know how to proceed when I have an opportunity to tackle this. Thanks again, Adam |
From: Adam W. <li...@co...> - 2005-09-15 05:44:00
|
On Mon, 12 Sep 2005 03:24:39 -0700, Peter Graves wrote: > On Mon, 12 Sep 2005 at 19:44:23 +1200, Adam Warner wrote: >> On Sun, 11 Sep 2005 06:16:55 -0700, Peter Graves wrote: >> > If you can figure out a way to capture stdout (maybe it just works, >> > since you've got some way to see the Java backtraces), you might try >> > enabling more verbose output at the top of boot.lisp: >> >> Java Web Start applications don't have a console. The backtrace I pasted >> in comes from the Details tab of the application termination dialogue box. > > I was afraid of that. There is a console. Even better--since the console locks up once the application is about to be terminated--there's logging (including trace logging). Start javaws without arguments Edit/Preferences Advanced tab Settings/{Debugging | Java Console} The logs are in .java/deployment/log > Since you don't have a console, you might want to write your own non- > console version of Debug.trace(), which would basically be the code you > added to signalNPE(), and then use that to add some debugging output to > the version of loadSystemFile() that starts at Load.java:197. Note that > boot.lisp, and the system files that it loads, are loaded by > loadSystemFile() rather than by load(). Through my own rudimentary console I discovered that "autoloads", "early-defuns" and "load" completed to the exit of loadStream (note: I never got to "backquote") However with Java's logging I have discovered the exact problem: java.security.AccessControlException: access denied (java.lang.RuntimePermission createClassLoader) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264) at java.security.AccessController.checkPermission(AccessController.java:427) at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:594) at java.lang.ClassLoader.<init>(ClassLoader.java:201) at org.armedbear.lisp.JavaClassLoader.<init>(JavaClassLoader.java:47) at org.armedbear.lisp.Lisp.loadCompiledFunction(Lisp.java:923) at org.armedbear.lisp.CompiledFunction$1.execute(CompiledFunction.java:174) at org.armedbear.lisp.LispThread.execute(LispThread.java:604) at org.armedbear.lisp.Lisp.evalCall(Lisp.java:425) at org.armedbear.lisp.Lisp.eval(Lisp.java:397) at org.armedbear.lisp.Lisp.evalCall(Lisp.java:427) at org.armedbear.lisp.Lisp.eval(Lisp.java:397) at org.armedbear.lisp.Load.faslLoadStream(Load.java:463) at org.armedbear.lisp.Load.access$100(Load.java:34) at org.armedbear.lisp.Load$1.execute(Load.java:344) at org.armedbear.lisp.LispThread.execute(LispThread.java:622) at org.armedbear.lisp.Lisp.evalCall(Lisp.java:431) at org.armedbear.lisp.Lisp.eval(Lisp.java:397) at org.armedbear.lisp.Load.loadStream(Load.java:438) at org.armedbear.lisp.Load.loadFileFromStream(Load.java:405) at org.armedbear.lisp.Load.loadSystemFile(Load.java:286) at org.armedbear.lisp.Load$3.execute(Load.java:540) at org.armedbear.lisp.LispThread.execute(LispThread.java:604) at org.armedbear.lisp.Lisp.evalCall(Lisp.java:425) at org.armedbear.lisp.Lisp.eval(Lisp.java:397) at org.armedbear.lisp.Load.loadStream(Load.java:438) at org.armedbear.lisp.Load.loadFileFromStream(Load.java:405) at org.armedbear.lisp.Load.loadSystemFile(Load.java:286) at org.armedbear.lisp.Interpreter.initializeLisp(Interpreter.java:98) at Message.main(Message.java:19) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at com.sun.javaws.Launcher.executeApplication(Launcher.java:1108) at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1055) at com.sun.javaws.Launcher.continueLaunch(Launcher.java:898) at com.sun.javaws.Launcher.handleApplicationDesc(Launcher.java:469) at com.sun.javaws.Launcher.handleLaunchFile(Launcher.java:217) at com.sun.javaws.Launcher.run(Launcher.java:164) at java.lang.Thread.run(Thread.java:595) Error: unhandled condition: #<ERROR {145F0E3}> java.security.AccessControlException: access denied (java.lang.RuntimePermission createClassLoader) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264) at java.security.AccessController.checkPermission(AccessController.java:427) at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:594) at java.lang.ClassLoader.<init>(ClassLoader.java:201) at org.armedbear.lisp.JavaClassLoader.<init>(JavaClassLoader.java:47) at org.armedbear.lisp.Lisp.loadCompiledFunction(Lisp.java:923) at org.armedbear.lisp.CompiledFunction$1.execute(CompiledFunction.java:174) at org.armedbear.lisp.LispThread.execute(LispThread.java:604) at org.armedbear.lisp.Lisp.evalCall(Lisp.java:425) at org.armedbear.lisp.Lisp.eval(Lisp.java:397) at org.armedbear.lisp.Lisp.evalCall(Lisp.java:427) at org.armedbear.lisp.Lisp.eval(Lisp.java:397) at org.armedbear.lisp.Load.faslLoadStream(Load.java:463) at org.armedbear.lisp.Load.access$100(Load.java:34) at org.armedbear.lisp.Load$1.execute(Load.java:344) at org.armedbear.lisp.LispThread.execute(LispThread.java:622) at org.armedbear.lisp.Lisp.evalCall(Lisp.java:431) at org.armedbear.lisp.Lisp.eval(Lisp.java:397) at org.armedbear.lisp.Load.loadStream(Load.java:438) at org.armedbear.lisp.Load.loadFileFromStream(Load.java:405) at org.armedbear.lisp.Load.loadSystemFile(Load.java:286) at org.armedbear.lisp.Load.loadSystemFile(Load.java:181) at org.armedbear.lisp.Autoload.load(Autoload.java:118) at org.armedbear.lisp.Autoload.execute(Autoload.java:144) at org.armedbear.lisp.Symbol.execute(Symbol.java:848) at Message.main(Message.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at com.sun.javaws.Launcher.executeApplication(Launcher.java:1108) at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1055) at com.sun.javaws.Launcher.continueLaunch(Launcher.java:898) at com.sun.javaws.Launcher.handleApplicationDesc(Launcher.java:469) at com.sun.javaws.Launcher.handleLaunchFile(Launcher.java:217) at com.sun.javaws.Launcher.run(Launcher.java:164) at java.lang.Thread.run(Thread.java:595) It appears untrusted applications are not allowed to create their own class loaders: <http://www.mail-archive.com/jbo...@li.../msg07439.html> And even with all permissions (which defeats the purpose of ABCL in a sandbox) there are bugs that still result in these access control exceptions being thrown: <http://sources.redhat.com/ml/kawa/2004-q4/msg00026.html> <http://sources.redhat.com/ml/kawa/2004-q4/msg00033.html> Here's the official word from the Java(TM) Network Launching Protocol & API Specification (JSR-56) Version 1.5: "An application running with all-permissions can create its own classloader to, e.g., install code downloaded from the network." The code insertion and on-the-fly bytecode generation that ABCL performs may be fundamentally incompatible with Java's security model for running untrusted code. Yet when running with all permissions the JNLP API is nothing more than a glorified cross platform ActiveX clone. Regards, Adam |
From: Peter G. <pe...@ar...> - 2005-09-15 17:16:50
|
On Thu, 15 Sep 2005 at 17:41:43 +1200, Adam Warner wrote: > The code insertion and on-the-fly bytecode generation that ABCL performs > may be fundamentally incompatible with Java's security model for running > untrusted code. Yet when running with all permissions the JNLP API is > nothing more than a glorified cross platform ActiveX clone. So it seems like the whole idea is unworkable. Or maybe there is some glimmer of hope in this sentence: A general solution would probably entail using the SecureClassLoader stuff. (at the end of http://sources.redhat.com/ml/kawa/2004-q4/msg00033.html). I'm afraid I don't know enough about the Java security model to have anything further to offer. -Peter |
From: Adam W. <li...@co...> - 2005-09-16 03:53:24
|
On Thu, 15 Sep 2005 10:16:43 -0700, Peter Graves wrote: > On Thu, 15 Sep 2005 at 17:41:43 +1200, Adam Warner wrote: >> The code insertion and on-the-fly bytecode generation that ABCL >> performs may be fundamentally incompatible with Java's security model >> for running untrusted code. Yet when running with all permissions the >> JNLP API is nothing more than a glorified cross platform ActiveX clone. > > So it seems like the whole idea is unworkable. > > Or maybe there is some glimmer of hope in this sentence: > > A general solution would probably entail using the SecureClassLoader > stuff. > > (at the end of http://sources.redhat.com/ml/kawa/2004-q4/msg00033.html). > > I'm afraid I don't know enough about the Java security model to have > anything further to offer. Unfortunately there is no glimmer of hope. The JNLP API provides a number of services that untrusted JNLP applications can access: <http://java.sun.com/j2se/1.5.0/docs/guide/javaws/jnlp/index.html> Creating a class loader isn't one of them. Therefore ABCL would need to run as a trusted application. This is where the JNLP specification is poor. Only two trusted environments are provided, "all-permissions" and "j2ee-application-client-permissions". Both these trusted environments provide "unrestricted access to the network and local disk" (refer 5.6 Trusted Environments of the JNLP 1.5 specification). Alternative permissions could be specified by the user/system administrator in a policy file but this fine grained permission framework is not exposed to the JNLP application developer. As a consequence, any application that needs slightly more permissions than the untrusted environment provides will effectively request all permissions (i.e. at least unrestricted access to the network and local disk). Sun is downgrading the warnings about running trusted Java Web Start applications. Check out this permission screenshot when running the Java 6.0 Mustang beta: <http://weblogs.java.net/blog/stanleyh/archive/2005/04/deployment_good_1.html> It's not obvious to me that the application is requesting full user permissions. I've looked at the "More information..." boxes myself and they read "This application will be run without the security restrictions normally provided by Java". Stanley Ho, architect for the Java Deployment team, writes that the "current [pre-Mustang] security warning UI in Java Web Start is simply too scary looking". Regards, Adam |