Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f56f1c5c authored by Songchun Fan's avatar Songchun Fan
Browse files

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
parent a355c8c7
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -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);
        }
+4 −0
Original line number Diff line number Diff line
@@ -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;
+1 −4
Original line number Diff line number Diff line
@@ -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);
        }
+30 −19
Original line number Diff line number Diff line
@@ -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 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);
            result = new File(targetDir, packageName + "-" + suffix);
        } while (result.exists());
        return result;
        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;
                }
+18 −0
Original line number Diff line number Diff line
@@ -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);
        }
    }
}