Esecuzione di una libreria nativa su errore Android L. : eseguibili indipendenti solo di posizione ( PIE ) sono supportati

? Maksim Dmitriev @ | Original: StackOverFlow
---

Quando eseguo codice nativo su Android L ( Nexus 5 ), ottengo l'errore .

errore : unica posizione eseguibili indipendenti ( PIE ) sono supportati .

Lo stesso codice viene eseguito correttamente sul mio Samsung Galaxy S3 ( Android 4.3 ) .

Ecco il mio 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

Tuttavia quando sostituisco APP_PLATFORM := android-9 con APP_PLATFORM := android-16 ( Mentre leggevo https://www.duosecurity.com/blog/exploit-mitigations-in-android-jelly-bean-4-1, supporto PIE apparso in Jelly Been ( livello di API 16 ) ), lo stesso file eseguibile funziona bene su Android L.

C'è un modo per compilare codice nativo utilizzando APP_PLATFORM := android-9 ed eseguirlo su L Android ?

---

Top 5 Risposta

1Maksim Dmitriev @

Ho costruito due file eseguibili : uno con APP_PLATFORM := android-9 e l'altro con APP_PLATFORM := android-16 . Per eseguire il codice nativo in Java Ho bisogno di questo :

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 @

Se si può vivere con il solo supporto 4.1+ Android, basta impostare APP_PLATFORM := android-16 e sarete pronti per partire . Dietro le quinte imposta APP_PIE := true . Il tuo binario sarà segfault su SDK anziani .

Se inoltre avete bisogno di supportare i livelli più bassi SDK, è necessario creare due binari . Alcune altre risposte che ho visto hanno raccomandato il mantenimento di due alberi di origine separati con diversi APP_PLATFORMs, ma non c'è bisogno di farlo . E ' possibile fare una sola uscita Android.mk sia PIE e un binario non- PIE .

NDK 10c:

Assicurarsi che Torta è disabilitata per default in quanto consente ai è manualmente più facile di disabilitarlo . PIE non viene abilitato di default a meno che il APP_PLATFORM è > = 16 . Assicurati che il tuo APP_PLATFORM non è impostata ( inadempiente a android - 3 ) ​​, inferiore a android -16, o impostare APP_PIE := false .

Il seguente Android.mk quindi crea un PIE e un binario non -PIE, ma ha un avvertimento ( vedi sotto ) :

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)

Avrai quindi aggiungere una sorta di logica per invocare il corretto binario nel codice .

Sfortunatamente, questo significa che dovrete compilare il modulo eseguibile due volte, che può essere lenta . È inoltre necessario specificare LOCAL_SRC_FILES e le librerie per due volte, che può essere frustrante e difficile tenere traccia di . Che cosa si può fare è compilare l'eseguibile principale, come una libreria statica, e costruire eseguibili dal nulla, ma quella libreria statica . Le librerie statiche non richiedono PIE .

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)

Questo sembra funzionare abbastanza bene, anche se è ancora necessaria una certa quantità di boilerplate .

NDK 10b:

NDK 10b consente PIE per impostazione predefinita e non consente di disattivare, se non con hack terribili . In realtà, solo l'aggiornamento a 10c . Sto lasciando la mia vecchia risposta qui per riferimento, ma io non lo consiglio a chiunque .

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 @

Il progetto Chromium pubblicato un https://chromium.googlesource.com/chromium/src.git/+/master/tools/android/run_pie/run_pie.c che consente di eseguire file binari PIE pre- JB Android rilascia . Si noti che l'eseguibile PIE richiede alcune bandiere in più per fare questo lavoro :

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

Nel mio caso, mi è stato shipping ~ binari 2MB per 3 architetture e non volevo aggiungere 6MB di dati non compressi al APK solo di continuare a sostenere ICS . run_pie È estremamente piccolo ( 6-7kB ) in modo che forma il conto .

run_pie Non deve essere costruito con le bandiere Torta, e non dovrebbe essere eseguito su Android 5.0+ ( perché, naturalmente, i binari non- PIE sono vietati ) . Purtroppo non può essere costruita in modo statico perché deve essere collegato con -ldl e NDK fornisce solo una versione condivisa di tale libreria .

Il lato Java potrebbe somigliare :

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;
}

dove busybox è un eseguibile PIE e vive in directory file privato della app .

Vedi anche : discussioni precedenti di questo argomento https://code.google.com/p/android-developer-preview/issues/detail?id=888 e http://forum.xda-developers.com/google-nexus- 5 / sviluppo / fix - scavalcando - pie - sicurezza -check- t2797731 .