OpenVPN-hulpbinêre misluk op Android 10: toestemming geweier
Android 10 weier om ’n hulpprogram uit te voer wat die app in sy eie berging geskryf het. Lees logcat, lewer die hulp as ’n inheemse biblioteek en maak bondelboue reg.
Die app het op Android 9 gewerk en sterf op dieselfde foon ná die opdatering na Android 10. Jou profiel is onaangeraak, die sertifikate is dieselfde, en die ineenstorting kom voor enige verifikasieverkeer. Logcat wys eers ’n nulwyser, en ’n paar reëls hierbo staan Cannot run program ...: error=13, Permission denied. Daardie boodskap handel oor die uitvoer van ’n lêer, nie oor die lees van jou konfigurasie nie.
Wat fout 13 werklik weier
Android 10, API-vlak 29, het apps verhinder om lêers uit te voer wat hulle in hul eie datagids geskryf het. Die reël mik op berging wat eers beskryfbaar en dan uitvoerbaar is, presies wat ’n laerder wat uit bates kopieer, skep. Ouer boue van die ics-openvpn-kern pak op die eerste lopie ’n openvpn uitvoerbare lêer uit die APK uit en begin dit met ProcessBuilder. Die uitpak slaag steeds; die uitvoering is wat geweier word. ’n App wat op API 29 mik, erf die reël selfs wanneer dit op ’n toestel loop wat met ’n ouer weergawe verskeep is, en daarom kan ’n opdatering ’n bou breek wat niemand aangeraak het nie.
Niks aan die weiering is spesifiek aan een gidsnaam nie. ’n Lêer wat die app onder sy datagids geskep het, word as nie-uitvoerbaar beskou ongeag die pad, so getFilesDir(), getCacheDir() en ’n pasgemaakte subgids misluk almal op dieselfde manier.
Skei die hulp-ineenstorting van ’n profielprobleem
Lees die log rondom die prosesbegin in plaas daarvan om van bo af te rol. Die kenmerk om na te soek is die error=13-reël, en die stapelspoor hierbo noem gewoonlik die laerdermetode wat ProcessBuilder genoem het:
adb logcat -d | grep -n -i -E "cannot run program|permission denied|startOpenVPN"As die hulp nooit begin het nie, sal jy glad geen OpenVPN-loguitset sien nie: geen syferonderhandeling, geen gestuurde roetes, geen DNS-konfigurasie nie. As daardie reëls wel verskyn en die faling kom later, het die binêre geloop en die probleem lê in die profiel, die bediener of die roetelaag. Daardie enkele onderskeid spaar baie tyd wat anders bestee word aan die wysig van .ovpn-lêers wat nooit skuldig was nie. Dit sê ook vir jou watter van die twee regstellings hieronder jy werklik nodig het.
Kontroleer ook die API-vlak op die toestel wat jy toets, nie dié in jou boukonfigurasie nie. ’n Emulatorbeeld op API 28 reproduseer niks, want die beperking byt eers vanaf 29 opwaarts. Kontroleer terselfdertyd die teiken-SDK in jou bouleêr: dit is die verhoging daarvan wat die reël inbring.
adb shell getprop ro.build.version.sdkWaarom om die binêre elders te kopieer nie help nie
Die ooglopende omweg, om die hulp na ’n ander beskryfbare gids te skryf, misluk om dieselfde rede as die oorspronklike. Android laat steeds die uitvoering van gedeelde biblioteke toe wat in die app se inheemse biblioteekgids geïnstalleer is, want dit word deur die installeerder verpak eerder as tydens looptyd geskryf. Daardie gids is die een plek waarheen die laerder moet wys. Enigiets wat jy self tydens looptyd uitpak, hoe jy dit ook al noem, bly in die geweierde kategorie.
Eksterne berging is erger: dit is as noexec gekoppel, en ’n hulp wat daar geplaas word, kan deur geen app begin word nie. Om appdata skoon te maak herstel ook nie die ou gedrag nie, want die volgende lopie skep eenvoudig dieselfde nie-uitvoerbare kopie.
Wys die laerder na ’n verpakte biblioteek
Hernoem die hulp na ’n gedeelde-biblioteeknaam en lewer dit onder jniLibs vir elke ABI wat jy ondersteun, en laat die laerder dan die geïnstalleerde biblioteekpad vanaf API 28 teruggee:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return new File(context.getApplicationInfo().nativeLibraryDir,
"libovpnexec.so").getPath();
}Die biblioteek moet tydens installasie uitgepak word sodat daardie pad ’n werklike lêer bevat, so stel android:extractNativeLibs="true" op die <application>-element. As ’n manifes-samevoeger ’n ander waarde inbring, voeg tools:replace="android:extractNativeLibs" daarby. Die naslaanblad vir die application-element dokumenteer wat die kenmerk beheer.
Let op ’n gedupliseerde plaaslike veranderlike wanneer jy die laerder met die hand wysig. Ouer bronne verklaar nativeAPI later in dieselfde metode, en ’n tweede verklaring is ’n samestellingsfout eerder as ’n looptydfout, so die bou misluk vinnig en die fout is maklik om raak te sien. Hou die ABI-lys in die Gradle-blok in pas met die gidse wat jy byvoeg.
Laat die vrystellingsartefak by die toetsbou pas
’n Ontfout-APK kan die tonnel begin terwyl ’n vrystellingsbondel steeds ineenstort, want ’n bondel verpak inheemse biblioteke in ’n ander vorm en kan dit saamgepers uit die argief lewer. As slegs bondelafgeleide boue misluk, voeg dit by gradle.properties en bou weer:
android.bundle.enableUncompressedNativeLibs=falseBevestig dan dat die geïnstalleerde pakket die ABI rapporteer wat jy verwag, en herhaal die kontrole op ’n 32-bis- en ’n 64-bis-toestel as jy albei lewer. Die pakketbestuurder noem die ABI wat dit gekies het, so ’n toestel wat na 32-bis teruggeval het, wys hier eerder as in ’n ineenstortingsverslag:
adb shell dumpsys package com.example.openvpn | grep -i primaryCpuAbi’n Ontbrekende biblioteek vir een ABI reproduseer die oorspronklike toestemmingsfout net op daardie toestel, en daarom is een suksesvolle toetstelefoon nie bewys nie. Lewer die manifesvlag, die biblioteeknaam en die bondelinstelling saam; om een te verander en die ander te vergeet, sit jou terug by dieselfde ineenstorting. Die blywende oplossing is om na ’n onderhoude kernvrystelling oor te skuif eerder as om die pleister vir ewig te dra.