diff options
author | 2020-01-22 17:10:50 -0800 | |
---|---|---|
committer | 2020-01-31 09:14:16 -0800 | |
commit | f56f1c5c587ed5af452ed1b339218dabc12c9f93 (patch) | |
tree | cecbb499c4defba76d76d4afb6fb5ebc0d675b57 | |
parent | a355c8c76e89c5b05369459252863d57ed2b3c33 (diff) |
Change app code path
Incremental (go/incremental-apk) requires bind-mounting on /data/app/...
directories. The purpose of this change is to avoid leaking package names in
/proc/mounts.
Default apk path of an installed app:
Before: /data/app/[packageName]-[randomString]/base.apk
After: /data/app/~~[randomStringA]/[packageName]-[randomStringB]/base.apk
BUG: b/147371381 b/148237378
Test: manual
Change-Id: Ib05b187dc006272603709a95534c40744cd62f0c
5 files changed, 58 insertions, 27 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index fd4c26569873..b3db92cd894f 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -953,6 +953,10 @@ public class PackageParser { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); } + // Apk directory is directly nested under the current directory + if (files.length == 1 && files[0].isDirectory()) { + return parseClusterPackageLite(files[0], flags); + } String packageName = null; int versionCode = 0; @@ -1325,12 +1329,9 @@ public class PackageParser { } } - pkg.setCodePath(packageDir.getCanonicalPath()); + pkg.setCodePath(lite.codePath); pkg.setUse32bitAbi(lite.use32bitAbi); return pkg; - } catch (IOException e) { - throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, - "Failed to get path: " + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index 6639b3d5c0b5..f3dc0df959dd 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -97,6 +97,10 @@ public class ApkLiteParseUtils { throw new PackageParser.PackageParserException( PackageManager.INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); } + // Apk directory is directly nested under the current directory + if (files.length == 1 && files[0].isDirectory()) { + return parseClusterPackageLite(files[0], flags); + } String packageName = null; int versionCode = 0; diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java index 3018230fac27..99f50e8d6458 100644 --- a/core/java/android/content/pm/parsing/ApkParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkParseUtils.java @@ -205,11 +205,8 @@ public class ApkParseUtils { } } - return parsingPackage.setCodePath(packageDir.getCanonicalPath()) + return parsingPackage.setCodePath(lite.codePath) .setUse32BitAbi(lite.use32bitAbi); - } catch (IOException e) { - throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, - "Failed to get path: " + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index afd9e0956048..6a975d655677 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -115,6 +115,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.dumpCriticalInfo; import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFiles; import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime; import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; +import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive; import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures; import android.Manifest; @@ -124,8 +125,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; -import android.app.ApplicationPackageManager; import android.app.AppOpsManager; +import android.app.ApplicationPackageManager; import android.app.BroadcastOptions; import android.app.IActivityManager; import android.app.ResourcesManager; @@ -358,7 +359,6 @@ import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -647,6 +647,8 @@ public class PackageManagerService extends IPackageManager.Stub private static final String[] INSTANT_APP_BROADCAST_PERMISSION = new String[] { android.Manifest.permission.ACCESS_INSTANT_APPS }; + private static final String RANDOM_DIR_PREFIX = "~~"; + final ServiceThread mHandlerThread; final PackageHandler mHandler; @@ -2978,9 +2980,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - //delete tmp files - deleteTempPackageFiles(); - final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get(); // Remove any shared userIDs that have no associated packages @@ -3563,8 +3562,7 @@ public class PackageManagerService extends IPackageManager.Stub getNextCodePath(Environment.getDataAppDirectory(null), packageName); int ret = PackageManager.INSTALL_SUCCEEDED; try { - Os.mkdir(dstCodePath.getAbsolutePath(), 0755); - Os.chmod(dstCodePath.getAbsolutePath(), 0755); + makeDirRecursive(dstCodePath, 0755); for (File srcFile : compressedFiles) { final String srcFileName = srcFile.getName(); final String dstFileName = srcFileName.substring( @@ -9819,8 +9817,12 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mInstallLock") void removeCodePathLI(File codePath) { if (codePath.isDirectory()) { + File codePathParent = codePath.getParentFile(); try { mInstaller.rmPackageDir(codePath.getAbsolutePath()); + if (codePathParent.getName().startsWith(RANDOM_DIR_PREFIX)) { + mInstaller.rmPackageDir(codePathParent.getAbsolutePath()); + } } catch (InstallerException e) { Slog.w(TAG, "Failed to remove code path", e); } @@ -14881,7 +14883,9 @@ public class PackageManagerService extends IPackageManager.Stub final boolean onIncremental = mIncrementalManager != null && isIncrementalPath(beforeCodeFile.getAbsolutePath()); try { + makeDirRecursive(afterCodeFile.getParentFile(), 0775); if (onIncremental) { + // TODO(b/147371381): fix incremental installation mIncrementalManager.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath()); } else { @@ -15093,16 +15097,29 @@ public class PackageManagerService extends IPackageManager.Stub } } + /** + * Given {@code targetDir}, returns {@code targetDir/~~[randomStrA]/[packageName]-[randomStrB].} + * Makes sure that {@code targetDir/~~[randomStrA]} directory doesn't exist. + * Notice that this method doesn't actually create any directory. + * + * @param targetDir Directory that is two-levels up from the result directory. + * @param packageName Name of the package whose code files are to be installed under the result + * directory. + * @return File object for the directory that should hold the code files of {@code packageName}. + */ private File getNextCodePath(File targetDir, String packageName) { - File result; SecureRandom random = new SecureRandom(); byte[] bytes = new byte[16]; + File firstLevelDir; do { random.nextBytes(bytes); - String suffix = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP); - result = new File(targetDir, packageName + "-" + suffix); - } while (result.exists()); - return result; + String dirName = RANDOM_DIR_PREFIX + + Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP); + firstLevelDir = new File(targetDir, dirName); + } while (firstLevelDir.exists()); + random.nextBytes(bytes); + String suffix = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP); + return new File(firstLevelDir, packageName + "-" + suffix); } static class PackageInstalledInfo { @@ -17097,12 +17114,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - private void deleteTempPackageFiles() { - // TODO: Is this used? - final FilenameFilter filter = - (dir, name) -> name.startsWith("vmdl") && name.endsWith(".tmp"); - } - @Override public void deletePackageAsUser(String packageName, int versionCode, IPackageDeleteObserver observer, int userId, int flags) { @@ -21434,7 +21445,7 @@ public class PackageManagerService extends IPackageManager.Stub final int absoluteCodePathCount = absoluteCodePaths.size(); for (int i = 0; i < absoluteCodePathCount; i++) { String absoluteCodePath = absoluteCodePaths.get(i); - if (absolutePath.startsWith(absoluteCodePath)) { + if (absoluteCodePath.startsWith(absolutePath)) { pathValid = true; break; } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index ded9a9c58c5e..71a5545c4131 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -83,6 +83,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; +import java.nio.file.Path; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.text.SimpleDateFormat; @@ -918,4 +919,21 @@ public class PackageManagerServiceUtils { } return packageSetting.getPermissionsState(); } + + /** + * Recursively create target directory + */ + public static void makeDirRecursive(File targetDir, int mode) throws ErrnoException { + final Path targetDirPath = targetDir.toPath(); + final int directoriesCount = targetDirPath.getNameCount(); + File currentDir; + for (int i = 1; i <= directoriesCount; i++) { + currentDir = targetDirPath.subpath(0, i).toFile(); + if (currentDir.exists()) { + continue; + } + Os.mkdir(currentDir.getAbsolutePath(), mode); + Os.chmod(currentDir.getAbsolutePath(), mode); + } + } } |