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

Commit 60150da0 authored by Jonathan Klee's avatar Jonathan Klee
Browse files

ship libinject

parent 95c937d7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -302,6 +302,7 @@ cc_defaults {
    shared_libs: [
        "libbinder",
        "libutils",
        "libinject",
    ],
    aidl: {
        include_dirs: [
+71 −0
Original line number Diff line number Diff line
@@ -251,6 +251,8 @@ public final class Zygote {
    public static final String CHILD_ZYGOTE_UID_RANGE_END = "--uid-range-end=";

    private static final String TAG = "Zygote";
    private static final String GMS_CORE_PACKAGE = "com.google.android.gms";
    private static final String PLAY_STORE_PACKAGE = "com.android.vending";

    /** Prefix prepended to socket names created by init */
    private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
@@ -367,6 +369,8 @@ public final class Zygote {
            if (gids != null && gids.length > 0) {
                NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
            }

            maybeInitInject(niceName, appDataDir);
        }

        // Set the Java Language thread priority to the default value for new apps.
@@ -376,6 +380,70 @@ public final class Zygote {
        return pid;
    }

    private static void maybeInitInject(@Nullable String niceName, @Nullable String appDataDir) {
        final String packageName = resolvePackageName(niceName, appDataDir);
        if (packageName == null) {
            return;
        }

        final boolean isGmsCore = GMS_CORE_PACKAGE.equals(packageName);
        final boolean isVending = PLAY_STORE_PACKAGE.equals(packageName);
        if (!isGmsCore && !isVending) {
            return;
        }

        final String gmsDir = resolveAppDataDir(packageName, appDataDir);
        if (gmsDir == null) {
            Log.w(TAG, "Unable to resolve app data dir for target package " + packageName);
            return;
        }

        final boolean isGmsUnstable = isGmsCore && isUnstableProcess(niceName);
        try {
            nativeInitInject(gmsDir, isGmsUnstable, isVending);
        } catch (Throwable t) {
            Log.w(TAG, "Failed to initialize inject for " + packageName, t);
        }
    }

    @Nullable
    private static String resolvePackageName(@Nullable String niceName, @Nullable String appDataDir) {
        if (appDataDir != null) {
            int lastSlash = appDataDir.lastIndexOf('/');
            if (lastSlash >= 0 && lastSlash + 1 < appDataDir.length()) {
                return appDataDir.substring(lastSlash + 1);
            }
        }

        if (niceName == null || niceName.isEmpty()) {
            return null;
        }

        int colonIndex = niceName.indexOf(':');
        if (colonIndex > 0) {
            return niceName.substring(0, colonIndex);
        }
        return niceName;
    }

    @Nullable
    private static String resolveAppDataDir(@NonNull String packageName,
            @Nullable String appDataDir) {
        if (appDataDir != null && !appDataDir.isEmpty()) {
            return appDataDir;
        }

        // Fallback to the primary user data directory if the framework does not provide one.
        return "/data/data/" + packageName;
    }

    private static boolean isUnstableProcess(@Nullable String niceName) {
        if (niceName == null) {
            return false;
        }
        return niceName.endsWith(":unstable") || niceName.endsWith(".unstable");
    }

    private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
            int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
            int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
@@ -562,6 +630,9 @@ public final class Zygote {

    protected static native void nativeInitNativeState(boolean isPrimary);

    private static native void nativeInitInject(String gmsDir, boolean isGmsUnstable,
            boolean isVending);

    /**
     * Returns the raw string value of a system property.
     *
+76 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/fs.h>
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>

#include <algorithm>
#include <array>
@@ -33,6 +34,7 @@
#include <functional>
#include <iterator>
#include <list>
#include <mutex>
#include <optional>
#include <sstream>
#include <string>
@@ -117,6 +119,60 @@ typedef const std::function<void(std::string)>& fail_fn_t;

static pid_t gSystemServerPid = 0;

using InjectInitFn = void (*)(JavaVM*, const std::string&, bool, bool);
static std::mutex gInjectMutex;
static void* gInjectHandle = nullptr;
static InjectInitFn gInjectInitFn = nullptr;
static bool gTriedLoadInject = false;

static InjectInitFn LoadInjectIfNeededLocked() {
    if (gTriedLoadInject) {
        return gInjectInitFn;
    }

    gTriedLoadInject = true;
    gInjectHandle = dlopen("libinject.so", RTLD_NOW | RTLD_LOCAL);
    if (gInjectHandle == nullptr) {
        const char* error = dlerror();
        ALOGW("Failed to dlopen libinject.so: %s", error == nullptr ? "unknown" : error);
        return nullptr;
    }

    gInjectInitFn = reinterpret_cast<InjectInitFn>(dlsym(gInjectHandle, "init"));
    if (gInjectInitFn == nullptr) {
        const char* error = dlerror();
        ALOGW("Failed to locate init() in libinject.so: %s", error == nullptr ? "unknown" : error);
    }

    return gInjectInitFn;
}

static void MaybeInitInject(JNIEnv* env, const char* gms_dir,
                            bool is_gms_unstable, bool is_vending) {
    if (gms_dir == nullptr) {
        return;
    }

    InjectInitFn init_fn;
    {
        std::lock_guard<std::mutex> lock(gInjectMutex);
        init_fn = LoadInjectIfNeededLocked();
    }

    if (init_fn == nullptr) {
        ALOGW("nativeInitInject requested but libinject could not be loaded");
        return;
    }

    JavaVM* vm = nullptr;
    if (env->GetJavaVM(&vm) != JNI_OK || vm == nullptr) {
        ALOGW("Unable to obtain JavaVM for libinject initialization");
        return;
    }

    init_fn(vm, std::string(gms_dir), is_gms_unstable, is_vending);
}

static constexpr const char* kVoldAppDataIsolation = "persist.sys.vold_app_data_isolation_enabled";
static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
static jclass gZygoteClass;
@@ -2606,6 +2662,24 @@ static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jc
  }
}

static void com_android_internal_os_Zygote_nativeInitInject(JNIEnv* env, jclass,
                                                            jstring gms_dir,
                                                            jboolean is_gms_unstable,
                                                            jboolean is_vending) {
  if (gms_dir == nullptr) {
    ALOGW("nativeInitInject called with null gmsDir");
    return;
  }

  ScopedUtfChars scoped_dir(env, gms_dir);
  if (scoped_dir.c_str() == nullptr) {
    return;
  }

  MaybeInitInject(env, scoped_dir.c_str(), is_gms_unstable == JNI_TRUE,
                  is_vending == JNI_TRUE);
}

/**
 * @param env  Managed runtime environment
 * @return  A managed array of raw file descriptors for the read ends of the USAP reporting
@@ -2844,6 +2918,8 @@ static const JNINativeMethod gMethods[] = {
         (void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess},
        {"nativeInitNativeState", "(Z)V",
         (void*)com_android_internal_os_Zygote_nativeInitNativeState},
        {"nativeInitInject", "(Ljava/lang/String;ZZ)V",
         (void*)com_android_internal_os_Zygote_nativeInitInject},
        {"nativeGetUsapPipeFDs", "()[I",
         (void*)com_android_internal_os_Zygote_nativeGetUsapPipeFDs},
        // @CriticalNative
+11 −0
Original line number Diff line number Diff line
cc_prebuilt_library_shared {
    name: "libinject",
    srcs: ["libinject.so"],
    compile_multilib: "both",
    stl: "none",
    strip: {
        none: true,
    },
    check_elf_files: true,
    prefer: true,
}
+648 KiB

File added.

No diff preview for this file type.