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

Commit a669ce68 authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi
Browse files

Disallow everyone to list files in the package dir

Only the system and the owner should be able to list the app
directory, both levels of it. Our code used the default mode
for them, making Incremental installations vulnerable to any
app that can see mounted filesystems: enumerating files in the
mounted incfs instance would give away the app package name.

This CL explicitly changes the mode to only allow reading
individual files in directory, but not listing them. Also now
we have code that fixes any originally installed packages to
make sure their mode is set properly as well

Bug: 261766355
Test: manual + an incremental CTS case
Change-Id: Ib084a3da95bd3e45463ee9e85e5b626495fd5486
parent c4a66af3
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ import android.content.pm.DataLoaderParams;
import android.content.pm.IPackageLoadingProgressCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
import android.util.Slog;
import android.util.SparseArray;

@@ -146,15 +149,29 @@ public final class IncrementalManager {
    @Nullable
    public IncrementalStorage createStorage(@NonNull String path,
            @NonNull IncrementalStorage linkedStorage, @CreateMode int createMode) {
        int id = -1;
        try {
            final int id = mService.createLinkedStorage(
            // Incremental service mounts its newly created storage on top of the supplied path,
            // ensure that the original mode remains the same after mounting.
            StructStat st = Os.stat(path);
            id = mService.createLinkedStorage(
                    path, linkedStorage.getId(), createMode);
            if (id < 0) {
                return null;
            }
            Os.chmod(path, st.st_mode & 07777);
            return new IncrementalStorage(mService, id);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (ErrnoException e) {
            if (id >= 0) {
                try {
                    mService.deleteStorage(id);
                } catch (RemoteException re) {
                    throw re.rethrowFromSystemServer();
                }
            }
            throw new RuntimeException(e);
        }
    }

+26 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ import android.annotation.Nullable;
import android.os.Environment;
import android.os.SystemClock;
import android.os.Trace;
import android.system.ErrnoException;
import android.system.Os;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Slog;
@@ -55,6 +57,7 @@ import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.utils.WatchedArrayMap;

import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
@@ -226,6 +229,24 @@ final class InitAppsHelper {
        }
    }

    /**
     * Fix up the previously-installed app directory mode - they can't be readable by non-system
     * users to prevent them from listing the dir to discover installed package names.
     */
    void fixInstalledAppDirMode() {
        try (var files = Files.newDirectoryStream(mPm.getAppInstallDir().toPath())) {
            files.forEach(dir -> {
                try {
                    Os.chmod(dir.toString(), 0771);
                } catch (ErrnoException e) {
                    Slog.w(TAG, "Failed to fix an installed app dir mode", e);
                }
            });
        } catch (Exception e) {
            Slog.w(TAG, "Failed to walk the app install directory to fix the modes", e);
        }
    }

    /**
     * Install apps/updates from data dir and fix system apps that are affected.
     */
@@ -234,6 +255,11 @@ final class InitAppsHelper {
            long startTime) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                SystemClock.uptimeMillis());

        if ((mScanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) == SCAN_FIRST_BOOT_OR_UPGRADE) {
            fixInstalledAppDirMode();
        }

        scanDirTracedLI(mPm.getAppInstallDir(), 0,
                mScanFlags | SCAN_REQUIRE_KNOWN, packageParser, mExecutorService);

+1 −1
Original line number Diff line number Diff line
@@ -1719,7 +1719,7 @@ final class InstallPackageHelper {
        final boolean onIncremental = mPm.mIncrementalManager != null
                && isIncrementalPath(beforeCodeFile.getAbsolutePath());
        try {
            makeDirRecursive(afterCodeFile.getParentFile(), 0775);
            makeDirRecursive(afterCodeFile.getParentFile(), 0771);
            if (onIncremental) {
                // Just link files here. The stage dir will be removed when the installation
                // session is completed.