Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6203047

Inconsistency in FilePermission

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 6
    • 5.0
    • security-libs
    • beta
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.5.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
      Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Linux 2.6.4
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      The FilePermission does not work consistently on Windows, causing issues when porting an application to run on Linux. On Windows when I compare this permission:

      FilePermission("\\-", "read")

      to this one (using the implies approach):

      FilePermission("/-", "read")

      The permission is granted. However, when I reverse the comparison the permission is not granted. Combined with that, on Windows the File("/temp.file") and File("\\temp.file") are considered the same but on Linux they are considered different. If I write my software on Windows, I am surprised by a number of bugs on Linux.

      The FilePermission object does work as advertised on Linux, but not on Windows.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create a MockPolicy object to act as the java.security.Policy for your system, and set the permissions you want to test, for example: FilePermission("\\-", "read");

      Use the java.security.AccessController to check for the expected permission, for example: AccessController.checkPermission( new FilePermission"/-", "read");

      On Windows the above example will pass, but according to the documentation it should not. On Linux it does not pass--creating a cross platform issue.

      NOTE: the reverse behaves as designed.

      NOTE 2: I believe the design should be changed so that both the File object and the FilePermission object translate the path to the operating system's File.separatorChar. This will mitigate most migration issues reguarding File and FilePermission objects.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      According to the documentation I expect this to happen:

      testSimulateLinuxProblem: failed (assertion error in exception clause)
      testSimulateWindowsProblem: failed (assertion error in exception clause)

      However, ideally I would like the FilePermission object to behave the same way the File object does in respect to File.separatorChar translation. It would make sense to have both FilePermission and File object to automatically translate the existing separator character to the platform's native format. If that were the case, then I would expect to see this:

      testSimulateLinuxProblem: pass
      testSimulateWindowsProblem: pass
      ACTUAL -
      On Linux, I get the expected test failures in both test cases based on the current specification. However, on Windows I get this result:

      testSimulateLinuxProblem: pass
      testSimulateWindowsProblem: fail (expected exception in catch section)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package org.d_haven.j5sec.test;

      import junit.framework.TestCase;
      import org.d_haven.j5sec.mocks.MockPolicy;

      import java.security.Policy;
      import java.security.Permissions;
      import java.security.AccessController;
      import java.io.FilePermission;
      import java.io.File;
      import java.io.IOException;

      public class TestFilePermissionError extends TestCase
      {
          public TestFilePermissionError(final String name)
          {
              super(name);
          }

          public void setUp() throws Exception
          {
              super.setUp();

              final File testFile = new File("test.file");
              testFile.createNewFile();
          }

          public void tearDown() throws Exception
          {
              super.tearDown();

              final File testFile = new File("test.file");
              testFile.delete();
          }

          public void testSimulateLinuxProblem() throws IOException
          {
              // Set up problem
              final MockPolicy policy = new MockPolicy();
              Policy.setPolicy( policy );

              final Permissions perms = new Permissions();
              perms.add( new FilePermission(".\\-", "read"));

              policy.setPermissions( perms );

              // make fail
              try
              {
                  AccessController.checkPermission( new FilePermission("./test","read"));
                  assertTrue(new File("./test.file").exists());
                  assertTrue(new File(".\\test.file").exists());
              }
              catch(SecurityException se)
              {
                  assertTrue(new File("./test.file").exists());
                  assertTrue(new File(".\\test.file").exists());
                  fail("Threw an exception that should not have been thrown.");
              }
          }

          public void testSimulateWindowsProblem()
          {
              // Set up problem
              final MockPolicy policy = new MockPolicy();
              Policy.setPolicy( policy );

              final Permissions perms = new Permissions();
              perms.add( new FilePermission("/-", "read"));

              policy.setPermissions( perms );

              // make fail
              try
              {
                  AccessController.checkPermission( new FilePermission("\\test","read"));
                  assertTrue(new File("./test.file").exists());
                  assertTrue(new File(".\\test.file").exists());
              }
              catch(SecurityException se)
              {
                  assertTrue(new File("./test.file").exists());
                  assertTrue(new File(".\\test.file").exists());
                  fail("Threw an exception that should not have been thrown.");
              }
          }
      }

      package org.d_haven.j5sec.mocks;

      import java.security.Policy;
      import java.security.PermissionCollection;
      import java.security.CodeSource;
      import java.security.Permissions;

      public class MockPolicy extends Policy
      {
          private Permissions m_permissions;

          public PermissionCollection getPermissions( final CodeSource codesource )
          {
              return m_permissions;
          }

          public void refresh()
          {
              //do nothing
          }

          public void setPermissions(final Permissions perms)
          {
              m_permissions = perms;
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Specify both ways of declaring a path in java.policy files:

      grant java.io.FilePermission "/-" "read"
      grant java.io.FilePermission "\\-" "read"

      This has to be done for each and every FilePermission granted in the java.policy file. Without awareness of this issue, it will cause delays late in the cycle of several development shops when they should be deploying, not fixing platform related bugs.

            claisunw Charlie Lai (Inactive)
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: