Skip to content

Commit fbc3785

Browse files
authored
On Android, set dynamic code files to readonly (#1430)
* To address an Android 14 security issue, set dex files to readonly. This follows the advice on dynamic code loading here: https://developer.android.com/about/versions/14/behavior-changes-14#safer-dynamic-code-loading * Format code. * Reorder exception check so that we cover all the spots. * Add release note.
1 parent f55c43c commit fbc3785

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

app/src/util_android.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,12 +1587,33 @@ const std::vector<internal::EmbeddedFile>& CacheEmbeddedFiles(
15871587
file::GetClass(), file::GetMethodId(file::kConstructorFilePath),
15881588
cache_dir, filename);
15891589
env->DeleteLocalRef(filename);
1590+
CheckAndClearJniExceptions(env);
1591+
// Below, we would have set the file read only on a previous run. Here, set
1592+
// it to writable and then delete it before creating it again.
1593+
//
1594+
// if output_file.exists() {
1595+
if (env->CallBooleanMethod(output_file, file::GetMethodId(file::kExists))) {
1596+
CheckAndClearJniExceptions(env);
1597+
// output_file.setWritable(true);
1598+
env->CallBooleanMethod(output_file, file::GetMethodId(file::kSetWritable),
1599+
JNI_TRUE);
1600+
CheckAndClearJniExceptions(env);
1601+
// output_file.delete();
1602+
env->CallBooleanMethod(output_file, file::GetMethodId(file::kDelete));
1603+
CheckAndClearJniExceptions(env);
1604+
}
15901605
jobject output_stream = env->NewObject(
15911606
file_output_stream::GetClass(),
15921607
file_output_stream::GetMethodId(file_output_stream::kConstructorFile),
15931608
output_file);
15941609
bool failed = CheckAndClearJniExceptions(env);
15951610
if (!failed) {
1611+
// Android 14 requires that we set the open dex file to readonly BEFORE
1612+
// writing code to it.
1613+
jboolean did_set_readonly = env->CallBooleanMethod(
1614+
output_file, file::GetMethodId(file::kSetReadOnly));
1615+
// If it failed, move on and try again later after closing the file.
1616+
if (CheckAndClearJniExceptions(env)) did_set_readonly = JNI_FALSE;
15961617
jobject output_array = env->NewByteArray(it->size);
15971618
env->SetByteArrayRegion(static_cast<jbyteArray>(output_array), 0,
15981619
it->size,
@@ -1605,6 +1626,11 @@ const std::vector<internal::EmbeddedFile>& CacheEmbeddedFiles(
16051626
env->CallVoidMethod(output_stream, file_output_stream::GetMethodId(
16061627
file_output_stream::kClose));
16071628
failed |= CheckAndClearJniExceptions(env);
1629+
if (!did_set_readonly) {
1630+
env->CallBooleanMethod(output_file,
1631+
file::GetMethodId(file::kSetReadOnly));
1632+
util::CheckAndClearJniExceptions(env);
1633+
}
16081634
env->DeleteLocalRef(output_array);
16091635
env->DeleteLocalRef(output_stream);
16101636
}

app/src/util_android.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,10 @@ METHOD_LOOKUP_DECLARATION(intent, INTENT_METHODS);
568568
X(ConstructorFilePath, "<init>", "(Ljava/io/File;Ljava/lang/String;)V"), \
569569
X(GetAbsolutePath, "getAbsolutePath", "()Ljava/lang/String;"), \
570570
X(GetPath, "getPath", "()Ljava/lang/String;"), \
571+
X(Exists, "exists", "()Z"), \
572+
X(Delete, "delete", "()Z"), \
573+
X(SetReadOnly, "setReadOnly", "()Z"), \
574+
X(SetWritable, "setWritable", "(Z)Z"), \
571575
X(ToUri, "toURI", "()Ljava/net/URI;")
572576
// clang-format on
573577
METHOD_LOOKUP_DECLARATION(file, FILE_METHODS)

release_build_files/readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,8 @@ code.
629629
## Release Notes
630630
### Next Release
631631
- Changes
632+
- General (Android): Made dynamic code files read only to comply with new
633+
Android 14 security requirements. This fixes a crash at API level 34+.
632634
- Analytics (iOS): Added InitiateOnDeviceConversionMeasurementWithPhoneNumber
633635
function to facilitate the [on-device conversion
634636
measurement](https://support.google.com/google-ads/answer/12119136) API.

0 commit comments

Comments
 (0)