From 6d99f796711882ba60977c211d0f92252fe7ad4a Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Mon, 16 May 2016 17:34:48 +0100 Subject: [PATCH] PackageManager: Fix reference profile canonicalization. Foreign dex markers are named in the runtime by calling realpath(3) on the input dexfile path and replacing "/" with "@". On the Java side, we're using File.getCanonicalPath, which is similar but isn't quite the same. It tries to call realpath() directly, but if that fails, it resorts to a series of increasingly desperate measures to calculate a "canonical path". We just use realpath instead. Also, don't attempt to delete a profile if canonicalization fails. bug: 28740848 Change-Id: Ie5d5af590187e793db633342a42b923865e5c005 --- .../android/server/pm/PackageDexOptimizer.java | 3 ++- .../server/pm/PackageManagerService.java | 3 ++- .../server/pm/PackageManagerServiceUtils.java | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 89747b5f79b73..26a840da094b6 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -328,10 +328,11 @@ class PackageDexOptimizer { for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) { try { - apkPath = new File(apkPath).getCanonicalPath(); + apkPath = PackageManagerServiceUtils.realpath(new File(apkPath)); } catch (IOException e) { // Log an error but continue without it. Slog.w(TAG, "Failed to get canonical path", e); + continue; } String useMarker = apkPath.replace('/', '@'); final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index faec8443c7222..488645dd65586 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7603,10 +7603,11 @@ public class PackageManagerService extends IPackageManager.Stub { for (String path : pkg.getAllCodePathsExcludingResourceOnly()) { try { - path = new File(path).getCanonicalPath(); + path = PackageManagerServiceUtils.realpath(new File(path)); } catch (IOException e) { // TODO: Should we return early here ? Slog.w(TAG, "Failed to get canonical path", e); + continue; } final String useMarker = path.replace('/', '@'); diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 67cbcd88ead16..b305ba71863b4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -25,9 +25,13 @@ import android.content.pm.PackageParser; import android.content.pm.ResolveInfo; import android.os.RemoteException; import android.os.UserHandle; +import android.system.ErrnoException; import android.util.ArraySet; import android.util.Log; +import libcore.io.Libcore; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -163,4 +167,16 @@ public class PackageManagerServiceUtils { return result; } -} \ No newline at end of file + + /** + * Returns the canonicalized path of {@code path} as per {@code realpath(3)} + * semantics. + */ + public static String realpath(File path) throws IOException { + try { + return Libcore.os.realpath(path.getAbsolutePath()); + } catch (ErrnoException ee) { + throw ee.rethrowAsIOException(); + } + } +}