summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Songchun Fan <schfan@google.com> 2020-01-22 17:10:50 -0800
committer Songchun Fan <schfan@google.com> 2020-01-31 09:14:16 -0800
commitf56f1c5c587ed5af452ed1b339218dabc12c9f93 (patch)
treececbb499c4defba76d76d4afb6fb5ebc0d675b57
parenta355c8c76e89c5b05369459252863d57ed2b3c33 (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
-rw-r--r--core/java/android/content/pm/PackageParser.java9
-rw-r--r--core/java/android/content/pm/parsing/ApkLiteParseUtils.java4
-rw-r--r--core/java/android/content/pm/parsing/ApkParseUtils.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java49
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java18
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);
+ }
+ }
}