Disable File.getCanonicalPath caches.

File.getCanonicalPath has to always return accurate
results in all cases, not doing so has potential
security implications. Caches may have stale data
if underlaying files were modified by another process
or code that's not aware of cannonical path cache.

Test: vogar ojluni/src/main/java/java/io/FileSystem.java
Bug: 62301183
Change-Id: I76b0ca606405a958ebbc57a8a6c08deb53ea1dfc
(cherry picked from commit caed7373b2ed858c864a0c108cffd65d051534f7)
(cherry picked from commit fef885586207ca90b7e7b717017075a7afaa3974)
diff --git a/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java b/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java
index 5a84c8e..87c3096 100644
--- a/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java
+++ b/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java
@@ -87,7 +87,7 @@
         // Hardcode MessagePattern apostrophe mode to be default. b/27265238
         { "android.icu.text.MessagePattern.ApostropheMode", null },
 
-        // Hardcode "sun.io.useCanonCaches" to use the default (on). b/28174137
+        // Hardcode "sun.io.useCanonCaches" to use the default (off). b/28174137, b/62301183
         { "sun.io.useCanonCaches", null },
         { "sun.io.useCanonPrefixCache", null },
 
@@ -111,4 +111,3 @@
         { "java.util.logging.manager", null },
     };
 }
-
diff --git a/luni/src/test/java/libcore/java/io/FileTest.java b/luni/src/test/java/libcore/java/io/FileTest.java
index 9226e02..05b66c1 100644
--- a/luni/src/test/java/libcore/java/io/FileTest.java
+++ b/luni/src/test/java/libcore/java/io/FileTest.java
@@ -393,4 +393,22 @@
             fail();
         } catch (InvalidPathException expected) {}
     }
+
+    // http://b/62301183
+    public void test_canonicalCachesAreOff() throws Exception {
+        File f1 = File.createTempFile("testCannonCachesOff1", "tmp");
+        File f2 = File.createTempFile("testCannonCachesOff2", "tmp");
+        File symlinkFile = new File("test_sl");
+
+        // Create a symlink from symlink to f1 and populate canonical path cache
+        assertEquals(0, Runtime.getRuntime().exec("ln -s " + f1.getAbsolutePath() + " " + symlinkFile.getAbsolutePath()).waitFor());
+        assertEquals(symlinkFile.getCanonicalPath(), f1.toString());
+
+        // Remove it and replace it with a symlink to f2 (using java File/Files would flush caches).
+        assertEquals(0, Runtime.getRuntime().exec("rm " + symlinkFile.getAbsolutePath()).waitFor());
+        assertEquals(0, Runtime.getRuntime().exec("ln -s " + f2.getAbsolutePath() + " " + symlinkFile.getAbsolutePath()).waitFor());
+
+        // Did we cache canonical path results? hope not!
+        assertEquals(symlinkFile.getCanonicalPath(), f2.toString());
+    }
 }
diff --git a/ojluni/src/main/java/java/io/FileSystem.java b/ojluni/src/main/java/java/io/FileSystem.java
index 4b0260d..86d8fff 100644
--- a/ojluni/src/main/java/java/io/FileSystem.java
+++ b/ojluni/src/main/java/java/io/FileSystem.java
@@ -226,8 +226,11 @@
 
     // Flags for enabling/disabling performance optimizations for file
     // name canonicalization
-    static boolean useCanonCaches      = true;
-    static boolean useCanonPrefixCache = true;
+    // Android-changed: Disabled caches for security reasons (b/62301183)
+    //static boolean useCanonCaches      = true;
+    //static boolean useCanonPrefixCache = true;
+    static boolean useCanonCaches      = false;
+    static boolean useCanonPrefixCache = false;
 
     private static boolean getBooleanProperty(String prop, boolean defaultVal) {
         String val = System.getProperty(prop);