[cp-patches] Re: Security manager problem

2005-12-22 Thread Mark Wielaard
Hi Gary (and moved to classpath-patches),

On Thu, 2005-12-22 at 15:15 +, Gary Benson wrote:
  Aha! There is your clue. libgcj hasn't merged in the new nio charset
  provider setup. And indeed creating a new CharsetProvider requires a
  RuntimePermission(charsetProvider). Even for creating the default
  provider. Which obviously should always be created, otherwise
  nothing works. It is safe in this case since we know the default
  provider doesn't do nasty things (or at least we hope so). So you
  need the attached patch to gnu/java/nio/charset/Provider.java.
 
 Works perfectly, thanks.

And so this will be checked in:

2005-12-22  Mark Wielaard  [EMAIL PROTECTED]

* gnu/java/nio/charset/Provider.java (provider): Wrap initialization
of standard provider in a PrivilegedAction.

Cheers,

Mark
Index: gnu/java/nio/charset/Provider.java
===
RCS file: /cvsroot/classpath/classpath/gnu/java/nio/charset/Provider.java,v
retrieving revision 1.6
diff -u -r1.6 Provider.java
--- gnu/java/nio/charset/Provider.java	2 Jul 2005 20:32:13 -	1.6
+++ gnu/java/nio/charset/Provider.java	13 Dec 2005 18:38:18 -
@@ -39,6 +39,8 @@
 
 import java.nio.charset.Charset;
 import java.nio.charset.spi.CharsetProvider;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -232,8 +234,16 @@
 
   public static synchronized Provider provider ()
   {
+// The default provider is safe to instantiate.
 if (singleton == null)
-  singleton = new Provider ();
+  singleton = (Provider) AccessController.doPrivileged
+	(new PrivilegedAction()
+	  {
+	public Object run()
+	{
+	  return new Provider();
+	}
+	  });
 return singleton;
   }
 }


signature.asc
Description: This is a digitally signed message part
___
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches


Re: Security manager problem

2005-12-22 Thread Gary Benson
Hi Mark,

Thanks for your quick reply, and apologies for my egregiously slow
one...

Mark Wielaard wrote:
 On Mon, 2005-12-12 at 17:55 +, Gary Benson wrote:
  Gary Benson wrote:
   Robert Lougher wrote:
Do you have a testcase?
   
   If you build and run the attached testcase you ought to see
   only one checkPermission() between Calling checkRead() and
   Done. ... In reality, JamVM chokes on it pretty hard.  I
   _think_ what is happening is that the System.out.println in
   checkPermission() is itself doing some initialisation which
   causes security checks, causing an infinite loop.
  
  The initialisation in question turns out to be:
  
   1. Loading java.lang.StringBuffer to build the message.
   2. Loading java.io.PrintStream to print it out.
   3. Converting the message to bytes using String.getBytes(encoding).
  
  Any one of them will trigger a security check and hence an infinite
  loop.
 
 Aha! There is your clue. libgcj hasn't merged in the new nio charset
 provider setup. And indeed creating a new CharsetProvider requires a
 RuntimePermission(charsetProvider). Even for creating the default
 provider. Which obviously should always be created, otherwise
 nothing works. It is safe in this case since we know the default
 provider doesn't do nasty things (or at least we hope so). So you
 need the attached patch to gnu/java/nio/charset/Provider.java.

Works perfectly, thanks.

 But even then you need some more workaround.
[snip]
 
 All this seems to come from having a user defined security
 manager loaded by a user defined class loader (the default
 System/Application class loader). We need to do ClassLoader.
 loadClass() checks in that case. But as shown in this example
 that leads very easily to recursive checkPermission() calls.
 
 I don't have a good idea how to make this easier. Any ideas?

Not really.  It'd be interesting to see how other JVMs handle this,
but I doubt it matters much as extending SecurityManager isn't really
necessary these days.

Cheers (and Merry Christmas!)
Gary


___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-13 Thread Mark Wielaard
Hi Gary,

On Mon, 2005-12-12 at 17:55 +, Gary Benson wrote:
 Gary Benson wrote:
  Robert Lougher wrote:
   Do you have a testcase?
  
  If you build and run the attached testcase you ought to see only one
  checkPermission() between Calling checkRead() and Done. ... In
  reality, JamVM chokes on it pretty hard.  I _think_ what is
  happening is that the System.out.println in checkPermission() is
  itself doing some initialisation which causes security checks,
  causing an infinite loop.
 
 The initialisation in question turns out to be:
 
  1. Loading java.lang.StringBuffer to build the message.
  2. Loading java.io.PrintStream to print it out.
  3. Converting the message to bytes using String.getBytes(encoding).
 
 Any one of them will trigger a security check and hence an infinite
 loop.

Aha! There is your clue. libgcj hasn't merged in the new nio charset
provider setup. And indeed creating a new CharsetProvider requires a
RuntimePermission(charsetProvider). Even for creating the default
provider. Which obviously should always be created, otherwise nothing
works. It is safe in this case since we know the default provider
doesn't do nasty things (or at least we hope so). So you need the
attached patch to gnu/java/nio/charset/Provider.java.

But even then you need some more workaround. There are two steps needed:
- Before the SecurityManager is installer we make sure that the whole
  System.out pipeline gets initialized.
- In the user defined TestSecurityManager we make sure that all classes
  that are used in the checkPermission() method are loaded before it
  gets installed. That is System and StringBuffer (because we use +).
Modified Test.java attached.

All this seems to come from having a user defined security manager
loaded by a user defined class loader (the default System/Application
class loader). We need to do ClassLoader.loadClass() checks in that
case. But as shown in this example that leads very easily to recursive
checkPermission() calls.

I don't have a good idea how to make this easier. Any ideas?

Cheers,

Mark
import java.security.*;

class Test
{
  static class TestSecurityManager extends SecurityManager
  {
TestSecurityManager()
{
	// Make sure the classes needed by checkPermission() are loaded.
	Class c = System.class;
	c = StringBuffer.class;
}

public void checkPermission(Permission perm) {
  System.out.println(  checkPermission( + perm + ));
}
  }
	
  public static void main(String[] args) {
try {
  // Make sure System is loaded
  // and the full System.out pipeline is initialized.
  System.out.println(Installing TestSecurityManager);

  SecurityManager sm = new TestSecurityManager();
  System.setSecurityManager(sm);
  System.out.println(Calling checkRead());
  sm.checkRead(/);
  System.out.println(Done);
}
catch (Throwable t) {
  t.printStackTrace();
}
  }
}
Index: gnu/java/nio/charset/Provider.java
===
RCS file: /cvsroot/classpath/classpath/gnu/java/nio/charset/Provider.java,v
retrieving revision 1.6
diff -u -r1.6 Provider.java
--- gnu/java/nio/charset/Provider.java	2 Jul 2005 20:32:13 -	1.6
+++ gnu/java/nio/charset/Provider.java	13 Dec 2005 18:38:18 -
@@ -39,6 +39,8 @@
 
 import java.nio.charset.Charset;
 import java.nio.charset.spi.CharsetProvider;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -232,8 +234,16 @@
 
   public static synchronized Provider provider ()
   {
+// The default provider is safe to instantiate.
 if (singleton == null)
-  singleton = new Provider ();
+  singleton = (Provider) AccessController.doPrivileged
+	(new PrivilegedAction()
+	  {
+	public Object run()
+	{
+	  return new Provider();
+	}
+	  });
 return singleton;
   }
 }


signature.asc
Description: This is a digitally signed message part
___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-12 Thread Gary Benson
Gary Benson wrote:
 Robert Lougher wrote:
  Do you have a testcase?
 
 If you build and run the attached testcase you ought to see only one
 checkPermission() between Calling checkRead() and Done. ... In
 reality, JamVM chokes on it pretty hard.  I _think_ what is
 happening is that the System.out.println in checkPermission() is
 itself doing some initialisation which causes security checks,
 causing an infinite loop.

The initialisation in question turns out to be:

 1. Loading java.lang.StringBuffer to build the message.
 2. Loading java.io.PrintStream to print it out.
 3. Converting the message to bytes using String.getBytes(encoding).

Any one of them will trigger a security check and hence an infinite
loop.  There's an awful lot I still don't undertstand here, but I'm
a step closer...  MaƱana.

In case anyone's interested I've attached a patched testcase and a
patch for classpath which together work on JamVM.

Cheers,
Gary
import java.security.Permission;

class Test
{
  static class TestSecurityManager extends SecurityManager
  {
public void checkPermission(Permission perm) {
  System.out.println(  checkPermission( + perm + ));
}
  }

  public static void main(String[] args) {
java.lang.StringBuffer XXX1 = new java.lang.StringBuffer();
java.io.PrintStream XXX2 = new java.io.PrintStream(null);
try {
  SecurityManager sm = new TestSecurityManager();
  System.setSecurityManager(sm);
  System.out.println(Calling checkRead());
  sm.checkRead(/);
  System.out.println(Done);
}
catch (Throwable t) {
  t.printStackTrace();
}
  }
}
Index: java/lang/String.java
===
RCS file: /cvsroot/classpath/classpath/java/lang/String.java,v
retrieving revision 1.77
diff -u -r1.77 String.java
--- java/lang/String.java   6 Dec 2005 18:52:25 -   1.77
+++ java/lang/String.java   12 Dec 2005 17:40:55 -
@@ -680,35 +680,9 @@
*/
   public byte[] getBytes(String enc) throws UnsupportedEncodingException
   {
-try 
-  {
-   CharsetEncoder cse = Charset.forName(enc).newEncoder();
-   cse.onMalformedInput(CodingErrorAction.REPLACE);
-   cse.onUnmappableCharacter(CodingErrorAction.REPLACE);
-   ByteBuffer bbuf = cse.encode(CharBuffer.wrap(value, offset, count));
-   if(bbuf.hasArray())
- return bbuf.array();
-   
-   // Doubt this will happen. But just in case.
-   byte[] bytes = new byte[bbuf.remaining()];
-   bbuf.get(bytes);
-   return bytes;
-  } 
-catch(IllegalCharsetNameException e)
-  {
-   throw new UnsupportedEncodingException(Encoding:  + enc
-  +  not found.);
-  } 
-catch(UnsupportedCharsetException e)
-  {
-   throw new UnsupportedEncodingException(Encoding:  + enc
-  +  not found.);
-  } 
-catch(CharacterCodingException e)
-  {
-   // This shouldn't ever happen.
-   throw (InternalError) new InternalError().initCause(e);
-  }  
+byte[] bytes = new byte[length()];
+getBytes(0, length(), bytes, 0);
+return bytes;
   }
 
   /**
___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-07 Thread Gary Benson
Robert Lougher wrote:
 On 12/6/05, Gary Benson [EMAIL PROTECTED] wrote:
  ...I was just looking at an some code in an
  AccessController.doPrivileged() that was doing security checks.
  Perhaps JamVM's AccessController.doPrivileged() is not in fact
  doing anything.
 
 What version of JamVM are you using?

I'm using cvs HEAD, with Classpath HEAD.

 As far as I'm aware, JamVMs implementation of VMAccessController is
 complete (it was provided by Casey Marshall, if I remember
 correctly).  I've made some recent changes to the native method that
 obtains the stack, so it _could_ have broken in 1.4.1.
 
 Do you have a testcase?

If you build and run the attached testcase you ought to see only one
checkPermission() between Calling checkRead() and Done.  GCJ (for
example) makes this of it:

  $ gij Test
  Calling checkRead()
checkPermission((java.io.FilePermission / read))
  Done
checkPermission((java.lang.RuntimePermission exitVM ))
checkPermission((java.lang.RuntimePermission exitVM ))

Based on what I'm seeing in Mauve you _should_ see a load of extra
stuff before the actual checkPermission you're interested in if you
run the testcase with JamVM:

  $ jamvm Test
  Calling checkRead()
checkPermission((java.io.FilePermission /path/to/JamVM.security read))
checkPermission((java.io.FilePermission /path/to/JamVM.security read))
checkPermission((java.io.FilePermission /path/to/classpath.security read))
checkPermission((java.io.FilePermission /path/to/classpath.security read))
checkPermission((java.io.FilePermission /path/to/classpath.security read))
checkPermission((java.util.PropertyPermission java.util.logging.manager 
read))
checkPermission(null)
checkPermission(null)
checkPermission(null)
checkPermission(null)
checkPermission((java.util.PropertyPermission 
java.util.logging.config.class read))
checkPermission((java.util.PropertyPermission java.util.logging.config.file 
read))
checkPermission((java.util.PropertyPermission gnu.classpath.home.url read))
checkPermission((java.io.FilePermission /path/to/logging.properties read))
checkPermission((java.io.FilePermission /path/to/logging.properties read))
checkPermission((java.util.logging.LoggingPermission control ))
checkPermission((java.util.logging.LoggingPermission control ))
checkPermission((java.security.SecurityPermission 
getProperty.package.access ))
checkPermission((java.io.FilePermission / read))
  Done
...

In reality, JamVM chokes on it pretty hard.  I _think_ what is
happening is that the System.out.println in checkPermission() is
itself doing some initialisation which causes security checks,
causing an infinite loop.  It's hard to say, though, not knowing
JamVM or Classpath particularly well.

Cheers,
Gary
import java.security.Permission;

class Test
{
  static class TestSecurityManager extends SecurityManager
  {
public void checkPermission(Permission perm) {
  System.out.println(  checkPermission( + perm + ));
}
  }

  public static void main(String[] args) {
try {
  SecurityManager sm = new TestSecurityManager();
  System.setSecurityManager(sm);
  System.out.println(Calling checkRead());
  sm.checkRead(/);
  System.out.println(Done);
}
catch (Throwable t) {
  t.printStackTrace();
}
  }
}
___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-06 Thread Anthony Green
On Tue, 2005-12-06 at 16:14 +, Gary Benson wrote:
 I'm having security manager problems, with JamVM at least.  Various
 initialisations happen the first time a permission is checked,
 including java.security.Security's clinit method which reads the
 provider files $vendor.security and classpath.security.  By this time
 you are most likely running under a security manager, so if that
 doesn't allow those files to be read then you get SecurityExceptions
 you weren't expecting.

It's been a long time since I've read anything about this kind of stuff,
but my understanding is that you simply wrap things like this up in a
AccessController.doPrivileged(), since the access control context of the
bootstrap or system class loader will permit file I/O.

AG




___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-06 Thread Gary Benson
Anthony Green wrote:
 On Tue, 2005-12-06 at 16:14 +, Gary Benson wrote:
  I'm having security manager problems, with JamVM at least.
  Various initialisations happen the first time a permission is
  checked, including java.security.Security's clinit method which
  reads the provider files $vendor.security and classpath.security.
  By this time you are most likely running under a security manager,
  so if that doesn't allow those files to be read then you get
  SecurityExceptions you weren't expecting.
 
 It's been a long time since I've read anything about this kind of
 stuff, but my understanding is that you simply wrap things like this
 up in a AccessController.doPrivileged(), since the access control
 context of the bootstrap or system class loader will permit file
 I/O.

That's interesting, as I was just looking at an some code in an
AccessController.doPrivileged() that was doing security checks.
Perhaps JamVM's AccessController.doPrivileged() is not in fact doing
anything.

Cheers,
Gary



___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-06 Thread Tom Tromey
 Anthony == Anthony Green [EMAIL PROTECTED] writes:

Anthony Perhaps.  Implementing proper sandbox behaviour is easy to defer.  I
Anthony think it will take the kind of work you are doing to drive VMs to take
Anthony care of details like this.  Do we even do it properly in libgcj (being
Anthony careful to account for reflection, etc)?  I would be surprised.

Nope.  There is a big 'XXX' in AccessController.
See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13604

Tom


___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-06 Thread Tom Tromey
 Anthony == Anthony Green [EMAIL PROTECTED] writes:

Anthony It's been a long time since I've read anything about this
Anthony kind of stuff, but my understanding is that you simply wrap
Anthony things like this up in a AccessController.doPrivileged(),
Anthony since the access control context of the bootstrap or system
Anthony class loader will permit file I/O.

Yes.  Finding and solving all the instances of this problem in
Classpath is, unfortunately, a good part of the required security
work.  If you dig around a bit you'll find other places where this
treatment has already been applied.

Tom


___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath


Re: Security manager problem

2005-12-06 Thread Robert Lougher
Hi,

On 12/6/05, Gary Benson [EMAIL PROTECTED] wrote:
 Anthony Green wrote:
  It's been a long time since I've read anything about this kind of
  stuff, but my understanding is that you simply wrap things like this
  up in a AccessController.doPrivileged(), since the access control
  context of the bootstrap or system class loader will permit file
  I/O.

 That's interesting, as I was just looking at an some code in an
 AccessController.doPrivileged() that was doing security checks.
 Perhaps JamVM's AccessController.doPrivileged() is not in fact doing
 anything.


What version of JamVM are you using?  As far as I'm aware, JamVMs
implementation of VMAccessController is complete (it was provided by
Casey Marshall, if I remember correctly).   I've made some recent
changes to the native method that obtains the stack, so it _could_
have broken in 1.4.1.

Do you have a testcase?

Thanks,

Rob.

 Cheers,
 Gary


___
Classpath mailing list
Classpath@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath