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)
diff --git a/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java b/libart/src/main/java/java/lang/AndroidHardcodedSystemProperties.java
index 13e9317..7e79e28 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 },
 
@@ -108,4 +108,3 @@
         { "com.sun.security.preserveOldDCEncoding", null },
     };
 }
-
diff --git a/luni/src/test/java/libcore/java/io/FileTest.java b/luni/src/test/java/libcore/java/io/FileTest.java
index 5d5317a..be28f60 100644
--- a/luni/src/test/java/libcore/java/io/FileTest.java
+++ b/luni/src/test/java/libcore/java/io/FileTest.java
@@ -368,4 +368,22 @@
         assertEquals("/foo/bar", new File("/foo/", "/bar/").getPath());
         assertEquals("/foo/bar", new File("/foo", "/bar//").getPath());
     }
+
+    // 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 aa00fa9..7db1651 100755
--- a/ojluni/src/main/java/java/io/FileSystem.java
+++ b/ojluni/src/main/java/java/io/FileSystem.java
@@ -232,8 +232,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);