diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index d4fa5cbb4f55a..14b511df390b7 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -23,6 +23,7 @@ import static com.android.internal.os.ZygoteConnectionConstants.MAX_ZYGOTE_ARGC; import android.net.Credentials; import android.net.LocalServerSocket; import android.net.LocalSocket; +import android.os.Build; import android.os.FactoryTest; import android.os.IVold; import android.os.Process; @@ -215,7 +216,8 @@ public final class Zygote { */ public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, - int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { + int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, + int targetSdkVersion) { ZygoteHooks.preFork(); // Resets nice priority for zygote process. resetNicePriority(); @@ -224,6 +226,7 @@ public final class Zygote { fdsToIgnore, startChildZygote, instructionSet, appDataDir); // Enable tracing as soon as possible for the child process. if (pid == 0) { + Zygote.disableExecuteOnly(targetSdkVersion); Trace.setTracingEnabled(true, runtimeFlags); // Note that this event ends at the end of handleChildProc, @@ -568,6 +571,8 @@ public final class Zygote { args.mSeInfo, args.mNiceName, args.mStartChildZygote, args.mInstructionSet, args.mAppDataDir); + disableExecuteOnly(args.mTargetSdkVersion); + if (args.mNiceName != null) { Process.setArgV0(args.mNiceName); } @@ -613,6 +618,17 @@ public final class Zygote { } } + /** + * Mark execute-only segments of libraries read+execute for apps with targetSdkVersion #include #include +#include #include #include #include @@ -53,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -1546,6 +1549,26 @@ static jint com_android_internal_os_Zygote_nativeGetBlastulaPoolCount(JNIEnv* en return gBlastulaPoolCount; } +static int disable_execute_only(struct dl_phdr_info *info, size_t size, void *data) { + // Search for any execute-only segments and mark them read+execute. + for (int i = 0; i < info->dlpi_phnum; i++) { + if ((info->dlpi_phdr[i].p_type == PT_LOAD) && (info->dlpi_phdr[i].p_flags == PF_X)) { + mprotect(reinterpret_cast(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr), + info->dlpi_phdr[i].p_memsz, PROT_READ | PROT_EXEC); + } + } + // Return non-zero to exit dl_iterate_phdr. + return 0; +} + +/** + * @param env Managed runtime environment + * @return True if disable was successful. + */ +static jboolean com_android_internal_os_Zygote_nativeDisableExecuteOnly(JNIEnv* env, jclass) { + return dl_iterate_phdr(disable_execute_only, nullptr) == 0; +} + static const JNINativeMethod gMethods[] = { { "nativeSecurityInit", "()V", (void *) com_android_internal_os_Zygote_nativeSecurityInit }, @@ -1574,7 +1597,9 @@ static const JNINativeMethod gMethods[] = { { "nativeGetBlastulaPoolEventFD", "()I", (void *) com_android_internal_os_Zygote_nativeGetBlastulaPoolEventFD }, { "nativeGetBlastulaPoolCount", "()I", - (void *) com_android_internal_os_Zygote_nativeGetBlastulaPoolCount } + (void *) com_android_internal_os_Zygote_nativeGetBlastulaPoolCount }, + { "nativeDisableExecuteOnly", "()Z", + (void *) com_android_internal_os_Zygote_nativeDisableExecuteOnly } }; int register_com_android_internal_os_Zygote(JNIEnv* env) {