diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java index 9c8ee562849cd..80041437d6b82 100644 --- a/core/java/android/os/incremental/IncrementalManager.java +++ b/core/java/android/os/incremental/IncrementalManager.java @@ -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); } } diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java index 12b5ab8a3160c..823bc71229438 100644 --- a/services/core/java/com/android/server/pm/InitAppsHelper.java +++ b/services/core/java/com/android/server/pm/InitAppsHelper.java @@ -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); diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 7553370bf4c62..c959b4724b93a 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -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.