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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user