From b02d72b01fd0c7239b494818c05ab7252880d3b0 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Mon, 1 Jul 2019 11:11:13 +0200 Subject: [PATCH] Add support for cross architecture loading in ProviderInstaller --- .../security/ProviderInstallerImpl.java | 90 ++++++++++++++++++- .../gms/maps/mapbox/utils/MultiArchLoader.kt | 4 - .../microg/gms/maps/vtm/BackendMapView.java | 4 - 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java b/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java index 62647365..fa72252d 100644 --- a/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java +++ b/play-services-core/src/main/java/com/google/android/gms/common/security/ProviderInstallerImpl.java @@ -17,15 +17,28 @@ package com.google.android.gms.common.security; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.os.Process; import android.util.Log; +import org.conscrypt.NativeCrypto; import org.conscrypt.OpenSSLProvider; import org.microg.gms.common.PackageUtils; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.security.Security; import java.util.Collections; +import java.util.Enumeration; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; @@ -35,12 +48,69 @@ public class ProviderInstallerImpl { private static final List DISABLED = Collections.singletonList("com.discord"); public static void insertProvider(Context context) { + String packageName = PackageUtils.packageFromProcessId(context, Process.myPid()); + Log.d(TAG, "Provider installer invoked for " + packageName); try { - String packageName = PackageUtils.packageFromProcessId(context, Process.myPid()); - Log.d(TAG, "Provider installer invoked for " + packageName); if (DISABLED.contains(packageName)) { Log.d(TAG, "Package is excluded from usage of provider installer"); - } else if (Security.insertProviderAt(new OpenSSLProvider("GmsCore_OpenSSL"), 1) == 1) { + return; + } + + OpenSSLProvider provider = null; + + try { + provider = new OpenSSLProvider("GmsCore_OpenSSL"); + } catch (UnsatisfiedLinkError e) { + Log.w(TAG, "Could not link conscrypt via default loader, trying manual loading"); + + // TODO: Move manual loading into helper function (as it is also used in both maps implementations) + try { + ApplicationInfo otherAppInfo = context.getPackageManager().getApplicationInfo(packageName, 0); + + String primaryCpuAbi = (String) ApplicationInfo.class.getField("primaryCpuAbi").get(otherAppInfo); + if (primaryCpuAbi != null) { + String path = "lib/" + primaryCpuAbi + "/libconscrypt_jni.so"; + File cacheFile = new File(context.createPackageContext(packageName, 0).getCacheDir().getAbsolutePath() + "/.gmscore/" + path); + cacheFile.getParentFile().mkdirs(); + File apkFile = new File(context.getPackageCodePath()); + if (!cacheFile.exists() || cacheFile.lastModified() < apkFile.lastModified()) { + ZipFile zipFile = new ZipFile(apkFile); + ZipEntry entry = zipFile.getEntry(path); + if (entry != null) { + copyInputStream(zipFile.getInputStream(entry), new FileOutputStream(cacheFile)); + } else { + Log.d(TAG, "Can't load native library: " + path + " does not exist in " + apkFile); + } + } + Log.d(TAG, "Loading conscrypt_jni from " + cacheFile.getPath()); + System.load(cacheFile.getAbsolutePath()); + + Class clazz = NativeCrypto.class; + Field loadError = clazz.getDeclaredField("loadError"); + loadError.setAccessible(true); + loadError.set(null, null); + Method clinit =clazz.getDeclaredMethod("clinit"); + clinit.setAccessible(true); + try { + clinit.invoke(null); + provider = new OpenSSLProvider("GmsCore_OpenSSL"); + } catch (InvocationTargetException inner) { + if (inner.getTargetException() instanceof UnsatisfiedLinkError) { + loadError.set(null, inner.getTargetException()); + } + } + } + } catch (Exception e2) { + Log.w(TAG, e2); + } + } + + if (provider == null) { + Log.w(TAG, "Failed to initialize conscrypt provider"); + return; + } + + if (Security.insertProviderAt(provider, 1) == 1) { Security.setProperty("ssl.SocketFactory.provider", "org.conscrypt.OpenSSLSocketFactoryImpl"); Security.setProperty("ssl.ServerSocketFactory.provider", "org.conscrypt.OpenSSLServerSocketFactoryImpl"); @@ -50,8 +120,20 @@ public class ProviderInstallerImpl { } else { Log.w(TAG, "Did not insert the new SSL provider"); } - } catch (Exception e) { + } catch (Throwable e) { Log.w(TAG, e); } } + + + private static final void copyInputStream(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + int len; + + while ((len = in.read(buffer)) >= 0) + out.write(buffer, 0, len); + + in.close(); + out.close(); + } } diff --git a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt index a4882883..bfcda14e 100644 --- a/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt +++ b/play-services-maps-core-mapbox/src/main/kotlin/org/microg/gms/maps/mapbox/utils/MultiArchLoader.kt @@ -42,10 +42,6 @@ class MultiArchLoader(private val mapContext: Context, private val appContext: C copyInputStream(zipFile.getInputStream(entry), FileOutputStream(cacheFile)) } else { Log.d(TAG, "Can't load native library: $path does not exist in $apkFile") - val entries = zipFile.entries() - while (entries.hasMoreElements()) { - Log.d(TAG, "but: ${entries.nextElement()}") - } } } Log.d(TAG, "Loading $name from ${cacheFile.getPath()}") diff --git a/play-services-maps-core-vtm/src/main/java/org/microg/gms/maps/vtm/BackendMapView.java b/play-services-maps-core-vtm/src/main/java/org/microg/gms/maps/vtm/BackendMapView.java index 05cf4157..6af341e6 100644 --- a/play-services-maps-core-vtm/src/main/java/org/microg/gms/maps/vtm/BackendMapView.java +++ b/play-services-maps-core-vtm/src/main/java/org/microg/gms/maps/vtm/BackendMapView.java @@ -76,10 +76,6 @@ public class BackendMapView extends MapView { copyInputStream(zipFile.getInputStream(entry), new FileOutputStream(cacheFile)); } else { Log.d(TAG, "Can't load native library: " + path + " does not exist in " + apkFile); - Enumeration entries = zipFile.entries(); - while (entries.hasMoreElements()) { - Log.d(TAG, "but: " + entries.nextElement()); - } } } Log.d(TAG, "Loading vtm-jni from " + cacheFile.getPath());