Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f4986b6 authored by Peter Collingbourne's avatar Peter Collingbourne
Browse files

Preserve x18 while preloading SP-HALs in the zygote.

Shadow call stack (SCS) is a security mitigation that uses a separate
stack (the SCS) for return addresses. In versions of Android newer
than P, the compiler cooperates with the system to ensure that the
SCS address is always stored in register x18, as long as the app was
compiled with a new enough compiler and does not use features that
rely on SP-HALs (this restriction is because the SP-HALs might not
preserve x18 due to potentially having been compiled with an old
compiler as a consequence of Treble; it generally means that the
app must be a system app without a UI). This change makes it so that
we temporarily store the address on the stack while preloading the
SP-HALs, so that such apps can use the same zygote as everything else.

Bug: 112907825
Change-Id: I5300fe89a0bba514894bdfb58237091d80fd0db8
parent e42fbe46
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -173,12 +173,13 @@ public class ZygoteInit {
    }

    native private static void nativePreloadAppProcessHALs();
    native private static void nativePreloadOpenGL();

    private static void preloadOpenGL() {
        String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
        if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
                (driverPackageName == null || driverPackageName.isEmpty())) {
            EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
            nativePreloadOpenGL();
        }
    }

+37 −0
Original line number Diff line number Diff line
@@ -16,21 +16,58 @@

#define LOG_TAG "Zygote"

#include <EGL/egl.h>
#include <ui/GraphicBufferMapper.h>

#include "core_jni_helpers.h"

namespace {

// Shadow call stack (SCS) is a security mitigation that uses a separate stack
// (the SCS) for return addresses. In versions of Android newer than P, the
// compiler cooperates with the system to ensure that the SCS address is always
// stored in register x18, as long as the app was compiled with a new enough
// compiler and does not use features that rely on SP-HALs (this restriction is
// because the SP-HALs might not preserve x18 due to potentially having been
// compiled with an old compiler as a consequence of Treble; it generally means
// that the app must be a system app without a UI). This struct is used to
// temporarily store the address on the stack while preloading the SP-HALs, so
// that such apps can use the same zygote as everything else.
struct ScopedSCSExit {
#ifdef __aarch64__
    void* scs;

    ScopedSCSExit() {
        __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
    }

    ~ScopedSCSExit() {
        __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
    }
#else
    // Silence unused variable warnings in non-SCS builds.
    ScopedSCSExit() {}
    ~ScopedSCSExit() {}
#endif
};

void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) {
    ScopedSCSExit x;
    android::GraphicBufferMapper::preloadHal();
    // Add preloading here for other HALs that are (a) always passthrough, and
    // (b) loaded by most app processes.
}

void android_internal_os_ZygoteInit_nativePreloadOpenGL(JNIEnv* env, jclass) {
    ScopedSCSExit x;
    eglGetDisplay(EGL_DEFAULT_DISPLAY);
}

const JNINativeMethod gMethods[] = {
    { "nativePreloadAppProcessHALs", "()V",
      (void*)android_internal_os_ZygoteInit_nativePreloadAppProcessHALs },
    { "nativePreloadOpenGL", "()V",
      (void*)android_internal_os_ZygoteInit_nativePreloadOpenGL },
};

}  // anonymous namespace