Ausführen eines nativen Bibliothek auf Android L. Fehler: nur Position unabhängig ausführbaren Dateien (PIE ) werden unterstützt

? Maksim Dmitriev @ | Original: StackOverFlow
---

Wenn ich nativen Code auf Android- L ( Nexus 5), erhalte ich die Fehler .

Fehler : nur Position unabhängige ausführbare (PIE ) werden unterstützt.

Der gleiche Code auf meinem Samsung Galaxy S3 ( Android 4.3) korrekt ausgeführt wird .

Hier ist meine Application.mk

APP_PROJECT_PATH := $(call my-dir)/..
APP_ABI := armeabi
NDK_TOOLCHAIN_VERSION := 4.7
APP_PLATFORM := android-9
APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti

Allerdings, wenn ich ersetzen APP_PLATFORM := android-9 mit APP_PLATFORM := android-16 ( Wie ich gelesen https://www.duosecurity.com/blog/exploit-mitigations-in-android-jelly-bean-4-1 erschien PIE Unterstützung bei Jelly worden ( API-Ebene 16) ), die gleiche ausführbare Datei funktioniert auf Android L.

Gibt es eine Möglichkeit, um native Code kompiliert mit APP_PLATFORM := android-9 und führen Sie es auf Android- L ?

---

Top 5 Antwort

1Maksim Dmitriev @

Ich baute zwei ausführbare Dateien : eine mit APP_PLATFORM := android-9 und das andere mit APP_PLATFORM := android-16 . Um den nativen Code in Java Ich brauche dies auszuführen:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
    // Run the file which was created using APP_PLATFORM := android-16
} else {
    // Run the file which was created using APP_PLATFORM := android-9
}
2Simo Kinnunen @

Wenn Sie nur mit Unterstützung von Android 4.1 und höher zu leben, nur auf APP_PLATFORM := android-16, und Sie werden gut zu gehen . Hinter den Kulissen es setzt APP_PIE := true . Ihre Binärdatei wird auf älteren SDKs segfault .

Wenn Sie auch zu niedrigeren SDK Ebenen zu unterstützen, müssen Sie zwei Binaries erstellen. Einige andere Antworten, die ich gesehen habe, haben empfohlen Beibehaltung von zwei separaten Quelle Bäume mit verschiedenen APP_PLATFORMs, aber Sie nicht zu tun brauchen. Es ist möglich, eine einzelne Android.mk Ausgang sowohl ein PIE und eine nicht- PIE binär zu machen.

NDK 10c:

Stellen Sie sicher, dass PIE ist standardmäßig seit ermöglicht es manuell ist einfacher, als es zu deaktivieren deaktiviert . PIE nicht standardmäßig aktiviert lassen, es sei denn Ihr APP_PLATFORM ist > = 16 . Stellen Sie sicher, dass Ihre APP_PLATFORM entweder nicht festgelegt ( standardmäßig auf android -3), niedriger als android -16, oder auf APP_PIE := false .

Die folgende Android.mk erstellt dann ein PIE und eine nicht- PIE binäre, hat aber einen Vorbehalt (siehe unten) :

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Enable PIE manually. Will get reset on $(CLEAR_VARS). This
# is what enabling PIE translates to behind the scenes.
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie

LOCAL_MODULE := mymod

LOCAL_SRC_FILES := 
    mymod.c

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_MODULE := mymod-nopie

LOCAL_SRC_FILES := 
    mymod.c

include $(BUILD_EXECUTABLE)

Sie haben dann eine Art von Logik hinzufügen, um die korrekten binären im Code aufrufen .

Leider bedeutet dies, müssen Sie die ausführbare Modul zweimal zusammenstellen, die langsam sein kann . Sie müssen auch LOCAL_SRC_FILES und alle Bibliotheken zweimal angeben, was frustrierend und schwierig zu verfolgen sein. Was Sie tun können, ist das Hauptprogramm als eine statische Bibliothek zu kompilieren, und bauen ausführbare Dateien aus dem Nichts, sondern dass statische Bibliothek . Statische Bibliotheken nicht PIE erfordern .

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := mymod-common

LOCAL_SRC_FILES := 
  mymod.c

include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)

# Enable PIE manually. Will get reset on $(CLEAR_VARS). This
# is what enabling PIE translates to behind the scenes.
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie

LOCAL_MODULE := mymod

LOCAL_STATIC_LIBRARIES := mymod-common

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_MODULE := mymod-nopie

LOCAL_STATIC_LIBRARIES := mymod-common

include $(BUILD_EXECUTABLE)

Das scheint ganz gut zu funktionieren, auch wenn eine gewisse Menge an Textvorschlag noch benötigt wird .

NDK 10b:

NDK 10b ermöglicht es PIE standardmäßig und nicht lassen Sie sie deaktivieren, außer mit schreckliche Hacks . Wirklich, einfach zu aktualisieren, um 10c . Ich verlasse mein alter Antwort hier als Referenz, aber ich würde nicht empfehlen es jedem.

LOCAL_PATH := $(call my-dir)

# Forcefully disable PIE globally. This makes it possible to
# build some binaries without PIE by adding the necessary flags
# manually. These will not get reset by $(CLEAR_VARS). PIE is
# force-enabled on NDK 10b so we'll need this even if APP_PIE
# is set to false.
TARGET_PIE := false
NDK_APP_PIE := false

include $(CLEAR_VARS)

# Enable PIE manually. Will get reset on $(CLEAR_VARS). This
# is what enabling PIE translates to behind the scenes.
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie

LOCAL_MODULE := mymod

LOCAL_SRC_FILES := 
    mymod.c

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_MODULE := mymod-nopie

LOCAL_SRC_FILES := 
    mymod.c

include $(BUILD_EXECUTABLE)
3Kevin Cernekee @

Die Chromium -Projekt veröffentlicht eine https://chromium.googlesource.com/chromium/src.git/+/master/tools/android/run_pie/run_pie.c die PIE -Binärdateien auf Pre- JB Android Mitteilungen laufen zu lassen. Beachten Sie, dass Ihre PIE ausführbare erfordert ein paar zusätzliche Flags, um diese Arbeit zu machen :

CFLAGS += -fvisibility=default -fPIE
LDFLAGS += -rdynamic -fPIE -pie

In meinem Fall wurde ich können Verschiffen ~ 2MB Binaries für 3 -Architekturen und wollte nicht zu 6 MB unkomprimierter Daten in die APK fügen Sie einfach weiter zu unterstützen ICS . run_pie Ist extrem klein ( 6-7kB ) so ist es genau das Richtige.

run_pie Sollten nicht mit den PIE Fahnen aufgebaut werden, und es sollte nicht auf Android 5.0 und höher (da natürlich nicht PIE Binärdateien verboten sind ) durchgeführt werden. Leider kann sie nicht statisch aufgebaut werden, weil es muss mit -ldl verknüpft werden und NDK bietet nur eine gemeinsame Version der Bibliothek.

Die Java-Seite könnte ungefähr so ​​aussehen :

String dir = mContext.getFilesDir().getPath();
String command = dir + "/busybox netstat";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
    command = dir + "/run_pie " + command;
}

wo busybox ist ein PIE ausführbare und lebt in Verzeichnis privaten Dateien der App.

Siehe auch: früheren Diskussionen zu diesem Thema https://code.google.com/p/android-developer-preview/issues/detail?id=888 und http://forum.xda-developers.com/google-nexus- 5 / Entwicklung / fix - Umgehung -pie -security- Check- t2797731 .