summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/idmap2/libidmap2/ResourceContainer.cpp2
-rw-r--r--cmds/idmap2/tests/XmlParserTests.cpp2
-rw-r--r--core/java/android/app/LoadedApk.java4
-rw-r--r--core/java/android/app/ResourcesManager.java51
-rw-r--r--core/java/android/content/res/ApkAssets.java6
-rw-r--r--core/jni/android_content_res_ApkAssets.cpp37
-rwxr-xr-xlibs/androidfw/ApkAssets.cpp4
-rw-r--r--libs/androidfw/AssetsProvider.cpp16
-rw-r--r--libs/androidfw/TEST_MAPPING3
-rw-r--r--libs/androidfw/include/androidfw/AssetsProvider.h9
-rw-r--r--libs/androidfw/include/androidfw/LoadedArsc.h4
11 files changed, 106 insertions, 32 deletions
diff --git a/cmds/idmap2/libidmap2/ResourceContainer.cpp b/cmds/idmap2/libidmap2/ResourceContainer.cpp
index 9147ccaaa17a..c147f6a6024b 100644
--- a/cmds/idmap2/libidmap2/ResourceContainer.cpp
+++ b/cmds/idmap2/libidmap2/ResourceContainer.cpp
@@ -323,7 +323,7 @@ ApkResourceContainer::ApkResourceContainer(std::unique_ptr<ZipAssetsProvider> zi
Result<std::unique_ptr<ApkResourceContainer>> ApkResourceContainer::FromPath(
const std::string& path) {
- auto zip_assets = ZipAssetsProvider::Create(path);
+ auto zip_assets = ZipAssetsProvider::Create(path, 0 /* flags */);
if (zip_assets == nullptr) {
return Error("failed to load zip assets");
}
diff --git a/cmds/idmap2/tests/XmlParserTests.cpp b/cmds/idmap2/tests/XmlParserTests.cpp
index eaf10a7d9282..016c5c3a01a5 100644
--- a/cmds/idmap2/tests/XmlParserTests.cpp
+++ b/cmds/idmap2/tests/XmlParserTests.cpp
@@ -26,7 +26,7 @@
namespace android::idmap2 {
Result<XmlParser> CreateTestParser(const std::string& test_file) {
- auto zip = ZipAssetsProvider::Create(GetTestDataPath() + "/target/target.apk");
+ auto zip = ZipAssetsProvider::Create(GetTestDataPath() + "/target/target.apk", 0 /* flags */);
if (zip == nullptr) {
return Error("Failed to open zip file");
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 0733a3e7c51c..90a6f32b2344 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1289,6 +1289,10 @@ public final class LoadedApk {
throw new AssertionError("null split not found");
}
+ if (Process.myUid() == mApplicationInfo.uid) {
+ ResourcesManager.getInstance().initializeApplicationPaths(mResDir, splitPaths);
+ }
+
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
splitPaths, mLegacyOverlayDirs, mOverlayPaths,
mApplicationInfo.sharedLibraryFiles, null, null, getCompatibilityInfo(),
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 792336d9be9e..f28c760d54d9 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -39,6 +39,7 @@ import android.os.IBinder;
import android.os.Process;
import android.os.Trace;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
@@ -260,6 +261,12 @@ public class ResourcesManager {
*/
private final UpdateHandler mUpdateCallbacks = new UpdateHandler();
+ /**
+ * The set of APK paths belonging to this process. This is used to disable incremental
+ * installation crash protections on these APKs so the app either behaves as expects or crashes.
+ */
+ private final ArraySet<String> mApplicationOwnedApks = new ArraySet<>();
+
@UnsupportedAppUsage
public ResourcesManager() {
}
@@ -424,6 +431,32 @@ public class ResourcesManager {
}
}
+ /**
+ * Initializes the set of APKs owned by the application running in this process.
+ */
+ public void initializeApplicationPaths(@NonNull String sourceDir,
+ @Nullable String[] splitDirs) {
+ synchronized (mLock) {
+ if (mApplicationOwnedApks.isEmpty()) {
+ addApplicationPathsLocked(sourceDir, splitDirs);
+ }
+ }
+ }
+
+ /**
+ * Updates the set of APKs owned by the application running in this process.
+ *
+ * This method only appends to the set of APKs owned by this process because the previous APKs
+ * paths still belong to the application running in this process.
+ */
+ private void addApplicationPathsLocked(@NonNull String sourceDir,
+ @Nullable String[] splitDirs) {
+ mApplicationOwnedApks.add(sourceDir);
+ if (splitDirs != null) {
+ mApplicationOwnedApks.addAll(Arrays.asList(splitDirs));
+ }
+ }
+
private static String overlayPathToIdmapPath(String path) {
return "/data/resource-cache/" + path.substring(1).replace('/', '@') + "@idmap";
}
@@ -445,13 +478,17 @@ public class ResourcesManager {
}
}
- // We must load this from disk.
+ int flags = 0;
+ if (key.sharedLib) {
+ flags |= ApkAssets.PROPERTY_DYNAMIC;
+ }
+ if (mApplicationOwnedApks.contains(key.path)) {
+ flags |= ApkAssets.PROPERTY_DISABLE_INCREMENTAL_HARDENING;
+ }
if (key.overlay) {
- apkAssets = ApkAssets.loadOverlayFromPath(overlayPathToIdmapPath(key.path),
- 0 /*flags*/);
+ apkAssets = ApkAssets.loadOverlayFromPath(overlayPathToIdmapPath(key.path), flags);
} else {
- apkAssets = ApkAssets.loadFromPath(key.path,
- key.sharedLib ? ApkAssets.PROPERTY_DYNAMIC : 0);
+ apkAssets = ApkAssets.loadFromPath(key.path, flags);
}
synchronized (mLock) {
@@ -1437,6 +1474,10 @@ public class ResourcesManager {
String[] copiedResourceDirs = combinedOverlayPaths(appInfo.resourceDirs,
appInfo.overlayPaths);
+ if (appInfo.uid == myUid) {
+ addApplicationPathsLocked(baseCodePath, copiedSplitDirs);
+ }
+
final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>();
final int implCount = mResourceImpls.size();
for (int i = 0; i < implCount; i++) {
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index 224ff14c5df4..6fd2d05ad135 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -69,6 +69,12 @@ public final class ApkAssets {
*/
private static final int PROPERTY_OVERLAY = 1 << 3;
+ /**
+ * The apk assets is owned by the application running in this process and incremental crash
+ * protections for this APK must be disabled.
+ */
+ public static final int PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1 << 4;
+
/** Flags that change the behavior of loaded apk assets. */
@IntDef(prefix = { "PROPERTY_" }, value = {
PROPERTY_SYSTEM,
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 9c8daec7919a..1be84282f6db 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -212,10 +212,11 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma
std::unique_ptr<ApkAssets> apk_assets;
switch (format) {
case FORMAT_APK: {
- auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
- ZipAssetsProvider::Create(path.c_str()));
- apk_assets = ApkAssets::Load(std::move(assets), property_flags);
- break;
+ auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
+ ZipAssetsProvider::Create(path.c_str(),
+ property_flags));
+ apk_assets = ApkAssets::Load(std::move(assets), property_flags);
+ break;
}
case FORMAT_IDMAP:
apk_assets = ApkAssets::LoadOverlay(path.c_str(), property_flags);
@@ -271,11 +272,13 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t
std::unique_ptr<const ApkAssets> apk_assets;
switch (format) {
case FORMAT_APK: {
- auto assets = MultiAssetsProvider::Create(
- std::move(loader_assets),
- ZipAssetsProvider::Create(std::move(dup_fd), friendly_name_utf8.c_str()));
- apk_assets = ApkAssets::Load(std::move(assets), property_flags);
- break;
+ auto assets =
+ MultiAssetsProvider::Create(std::move(loader_assets),
+ ZipAssetsProvider::Create(std::move(dup_fd),
+ friendly_name_utf8.c_str(),
+ property_flags));
+ apk_assets = ApkAssets::Load(std::move(assets), property_flags);
+ break;
}
case FORMAT_ARSC:
apk_assets = ApkAssets::LoadTable(
@@ -336,12 +339,16 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_
std::unique_ptr<const ApkAssets> apk_assets;
switch (format) {
case FORMAT_APK: {
- auto assets = MultiAssetsProvider::Create(
- std::move(loader_assets),
- ZipAssetsProvider::Create(std::move(dup_fd), friendly_name_utf8.c_str(),
- static_cast<off64_t>(offset), static_cast<off64_t>(length)));
- apk_assets = ApkAssets::Load(std::move(assets), property_flags);
- break;
+ auto assets =
+ MultiAssetsProvider::Create(std::move(loader_assets),
+ ZipAssetsProvider::Create(std::move(dup_fd),
+ friendly_name_utf8.c_str(),
+ property_flags,
+ static_cast<off64_t>(offset),
+ static_cast<off64_t>(
+ length)));
+ apk_assets = ApkAssets::Load(std::move(assets), property_flags);
+ break;
}
case FORMAT_ARSC:
apk_assets = ApkAssets::LoadTable(
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 26d836328b54..2beb33abe782 100755
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -40,7 +40,7 @@ ApkAssets::ApkAssets(std::unique_ptr<Asset> resources_asset,
loaded_idmap_(std::move(loaded_idmap)) {}
std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path, package_property_t flags) {
- return Load(ZipAssetsProvider::Create(path), flags);
+ return Load(ZipAssetsProvider::Create(path, flags), flags);
}
std::unique_ptr<ApkAssets> ApkAssets::LoadFromFd(base::unique_fd fd,
@@ -91,7 +91,7 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
overlay_assets = EmptyAssetsProvider::Create(overlay_path);
} else {
// The overlay should be an APK.
- overlay_assets = ZipAssetsProvider::Create(overlay_path);
+ overlay_assets = ZipAssetsProvider::Create(overlay_path, flags);
}
if (overlay_assets == nullptr) {
return {};
diff --git a/libs/androidfw/AssetsProvider.cpp b/libs/androidfw/AssetsProvider.cpp
index 6c7a25307247..bce34d37c90b 100644
--- a/libs/androidfw/AssetsProvider.cpp
+++ b/libs/androidfw/AssetsProvider.cpp
@@ -85,12 +85,14 @@ const std::string& ZipAssetsProvider::PathOrDebugName::GetDebugName() const {
}
ZipAssetsProvider::ZipAssetsProvider(ZipArchiveHandle handle, PathOrDebugName&& path,
- time_t last_mod_time)
+ package_property_t flags, time_t last_mod_time)
: zip_handle_(handle, ::CloseArchive),
name_(std::forward<PathOrDebugName>(path)),
+ flags_(flags),
last_mod_time_(last_mod_time) {}
-std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path) {
+std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
+ package_property_t flags) {
ZipArchiveHandle handle;
if (int32_t result = OpenArchive(path.c_str(), &handle); result != 0) {
LOG(ERROR) << "Failed to open APK '" << path << "': " << ::ErrorCodeString(result);
@@ -109,11 +111,12 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path) {
return std::unique_ptr<ZipAssetsProvider>(
new ZipAssetsProvider(handle, PathOrDebugName{std::move(path),
- true /* is_path */}, sb.st_mtime));
+ true /* is_path */}, flags, sb.st_mtime));
}
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
std::string friendly_name,
+ package_property_t flags,
off64_t offset,
off64_t len) {
ZipArchiveHandle handle;
@@ -140,7 +143,7 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
return std::unique_ptr<ZipAssetsProvider>(
new ZipAssetsProvider(handle, PathOrDebugName{std::move(friendly_name),
- false /* is_path */}, sb.st_mtime));
+ false /* is_path */}, flags, sb.st_mtime));
}
std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
@@ -161,10 +164,11 @@ std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
const int fd = GetFileDescriptor(zip_handle_.get());
const off64_t fd_offset = GetFileDescriptorOffset(zip_handle_.get());
+ const bool incremental_hardening = (flags_ & PROPERTY_DISABLE_INCREMENTAL_HARDENING) == 0U;
incfs::IncFsFileMap asset_map;
if (entry.method == kCompressDeflated) {
if (!asset_map.Create(fd, entry.offset + fd_offset, entry.compressed_length,
- name_.GetDebugName().c_str())) {
+ name_.GetDebugName().c_str(), incremental_hardening)) {
LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName()
<< "'";
return {};
@@ -181,7 +185,7 @@ std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
}
if (!asset_map.Create(fd, entry.offset + fd_offset, entry.uncompressed_length,
- name_.GetDebugName().c_str())) {
+ name_.GetDebugName().c_str(), incremental_hardening)) {
LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName() << "'";
return {};
}
diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING
index 766714cd7694..8a5c06d1eef9 100644
--- a/libs/androidfw/TEST_MAPPING
+++ b/libs/androidfw/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "CtsResourcesLoaderTests"
+ },
+ {
+ "name": "ResourcesHardeningTest"
}
]
} \ No newline at end of file
diff --git a/libs/androidfw/include/androidfw/AssetsProvider.h b/libs/androidfw/include/androidfw/AssetsProvider.h
index ec51c65053bf..966ec74c1786 100644
--- a/libs/androidfw/include/androidfw/AssetsProvider.h
+++ b/libs/androidfw/include/androidfw/AssetsProvider.h
@@ -80,9 +80,12 @@ struct AssetsProvider {
// Supplies assets from a zip archive.
struct ZipAssetsProvider : public AssetsProvider {
- static std::unique_ptr<ZipAssetsProvider> Create(std::string path);
+ static std::unique_ptr<ZipAssetsProvider> Create(std::string path,
+ package_property_t flags);
+
static std::unique_ptr<ZipAssetsProvider> Create(base::unique_fd fd,
std::string friendly_name,
+ package_property_t flags,
off64_t offset = 0,
off64_t len = kUnknownLength);
@@ -101,7 +104,8 @@ struct ZipAssetsProvider : public AssetsProvider {
private:
struct PathOrDebugName;
- ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, time_t last_mod_time);
+ ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, package_property_t flags,
+ time_t last_mod_time);
struct PathOrDebugName {
PathOrDebugName(std::string&& value, bool is_path);
@@ -119,6 +123,7 @@ struct ZipAssetsProvider : public AssetsProvider {
std::unique_ptr<ZipArchive, void (*)(ZipArchive*)> zip_handle_;
PathOrDebugName name_;
+ package_property_t flags_;
time_t last_mod_time_;
};
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 9bbdede56293..b3d6a4dcb955 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -92,6 +92,10 @@ enum : package_property_t {
// The package is a RRO.
PROPERTY_OVERLAY = 1U << 3U,
+
+ // The apk assets is owned by the application running in this process and incremental crash
+ // protections for this APK must be disabled.
+ PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1U << 4U,
};
struct OverlayableInfo {