From b1afd554fc27bcdbb008b81d1bef630076bde47f Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 1 Mar 2019 17:08:08 -0500 Subject: [PATCH] Application Component Granularity MagiskHide Before switching to the new MagiskHide implementation (APK inotify), logcat parsing provides us lots of information to target a process. We were targeting components so that apps with multi-processes can still be hidden properly. After switching to the new implementation, our granularity is limited to the UID of the process. This is especially dangerous since Android allow apps signed with the same signature to share UIDs, and many system apps utilize this for elevated permissions for some services. This commit introduces process name matching. We could not blanketly target an UID, so the workaround is to verify its process name before unmounting. The tricky thing is that any app developer is allowed to name the process of its component to whatever they want; there is no 'one rule to catch them all' to target a specific package. As a result, Magisk Manager is updated to scan through all components of all apps, and show different processes of the same app, each as a separate hide target in the list. The hide target database also has to be updated accordingly. Each hide target is now a pair. The magiskhide CLI and Magisk Manager is updated to support this new target format. --- .../main/java/com/topjohnwu/magisk/Const.java | 6 - .../magisk/adapters/ApplicationAdapter.java | 214 ++++++++++++------ .../magisk/fragments/MagiskHideFragment.java | 4 +- app/src/full/res/layout/list_item_app.xml | 19 +- native/jni/core/db.cpp | 29 ++- native/jni/magiskhide/hide_utils.cpp | 134 ++++++----- native/jni/magiskhide/magiskhide.cpp | 20 +- native/jni/magiskhide/magiskhide.h | 7 +- native/jni/magiskhide/proc_monitor.cpp | 140 ++++++------ native/jni/utils/include/utils.h | 1 + native/jni/utils/xwrap.cpp | 8 + 11 files changed, 337 insertions(+), 245 deletions(-) diff --git a/app-core/src/main/java/com/topjohnwu/magisk/Const.java b/app-core/src/main/java/com/topjohnwu/magisk/Const.java index 4a72fb106..945010514 100644 --- a/app-core/src/main/java/com/topjohnwu/magisk/Const.java +++ b/app-core/src/main/java/com/topjohnwu/magisk/Const.java @@ -37,12 +37,6 @@ public class Const { public static final int MIN_MODULE_VER = 1500; public static final int SNET_EXT_VER = 12; - /* A list of apps that should not be shown as hide-able */ - public static final List HIDE_BLACKLIST = Arrays.asList( - App.self.getPackageName(), - "com.google.android.gms" - ); - public static final int USER_ID = Process.myUid() / 100000; public static final class MAGISK_VER { diff --git a/app/src/full/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java b/app/src/full/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java index f23c5561e..2de8c17e6 100644 --- a/app/src/full/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java +++ b/app/src/full/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java @@ -2,6 +2,7 @@ package com.topjohnwu.magisk.adapters; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.ComponentInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.AsyncTask; @@ -12,7 +13,8 @@ import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView; -import com.topjohnwu.magisk.Const; +import com.topjohnwu.magisk.App; +import com.topjohnwu.magisk.Config; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Utils; @@ -20,34 +22,40 @@ import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.internal.UiThreadHandler; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; -import java.util.Iterator; +import java.util.Comparator; import java.util.List; +import java.util.Set; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; +import androidx.collection.ArraySet; import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; public class ApplicationAdapter extends RecyclerView.Adapter { - private static PackageInfo PLATFORM; + /* A list of apps that should not be shown as hide-able */ + private static final List HIDE_BLACKLIST = Arrays.asList( + App.self.getPackageName(), + "android", + "com.android.chrome" + ); + private static final String SAFETYNET_PROCESS = "com.google.android.gms.unstable"; + private static final String GMS_PACKAGE = "com.google.android.gms"; - private List fullList, showList; - private List hideList; + private List fullList, showList; + private List hideList; private PackageManager pm; private boolean showSystem; public ApplicationAdapter(Context context) { - fullList = showList = Collections.emptyList(); - hideList = Collections.emptyList(); + showList = Collections.emptyList(); + fullList = new ArrayList<>(); + hideList = new ArrayList<>(); pm = context.getPackageManager(); - showSystem = false; - if (PLATFORM == null) { - try { - PLATFORM = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES); - } catch (PackageManager.NameNotFoundException ignored) {} - } + showSystem = Config.get(Config.Key.SHOW_SYSTEM_APP); AsyncTask.SERIAL_EXECUTOR.execute(this::loadApps); } @@ -58,32 +66,42 @@ public class ApplicationAdapter extends RecyclerView.Adapter set, ComponentInfo[] infos) { + if (infos != null) + for (ComponentInfo info : infos) + set.add(info.processName); + } + @WorkerThread private void loadApps() { - fullList = pm.getInstalledPackages(PackageManager.GET_SIGNATURES); - hideList = Shell.su("magiskhide --ls").exec().getOut(); - for (Iterator i = fullList.iterator(); i.hasNext(); ) { - PackageInfo info = i.next(); - if (Const.HIDE_BLACKLIST.contains(info.packageName) || + // Get package info with all components + List installed = pm.getInstalledPackages( + PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES | + PackageManager.GET_RECEIVERS | PackageManager.GET_PROVIDERS); + + fullList.clear(); + hideList.clear(); + + for (String line : Shell.su("magiskhide --ls").exec().getOut()) + hideList.add(new HideTarget(line)); + + for (PackageInfo pkg : installed) { + if (!HIDE_BLACKLIST.contains(pkg.packageName) && /* Do not show disabled apps */ - !info.applicationInfo.enabled || - /* Never show platform apps */ - PLATFORM.signatures[0].equals(info.signatures[0])) { - i.remove(); + pkg.applicationInfo.enabled) { + // Add all possible process names + Set procSet = new ArraySet<>(); + addProcesses(procSet, pkg.activities); + addProcesses(procSet, pkg.services); + addProcesses(procSet, pkg.receivers); + addProcesses(procSet, pkg.providers); + for (String proc : procSet) { + fullList.add(new HideAppInfo(pkg.applicationInfo, proc)); + } } } - Collections.sort(fullList, (a, b) -> { - boolean ah = hideList.contains(a.packageName); - boolean bh = hideList.contains(b.packageName); - if (ah == bh) { - return Utils.getAppLabel(a.applicationInfo, pm) - .compareToIgnoreCase(Utils.getAppLabel(b.applicationInfo, pm)); - } else if (ah) { - return -1; - } else { - return 1; - } - }); + + Collections.sort(fullList); Topic.publish(false, Topic.MAGISK_HIDE_DONE); } @@ -93,23 +111,35 @@ public class ApplicationAdapter extends RecyclerView.Adapter { - if (isChecked) { - Shell.su("magiskhide --add " + info.packageName).submit(); - hideList.add(info.packageName); - } else { - Shell.su("magiskhide --rm " + info.packageName).submit(); - hideList.remove(info.packageName); - } - }); + holder.checkBox.setChecked(target.hidden); + if (target.process.equals(SAFETYNET_PROCESS)) { + // Do not allow user to not hide SafetyNet + holder.checkBox.setOnCheckedChangeListener((v, c) -> holder.checkBox.setChecked(true)); + } else { + holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> { + String pair = Utils.fmt("%s %s", target.info.packageName, target.process); + if (isChecked) { + Shell.su("magiskhide --add " + pair).submit(); + target.hidden = true; + } else { + Shell.su("magiskhide --rm " + pair).submit(); + target.hidden = false; + } + }); + } } @Override @@ -117,36 +147,36 @@ public class ApplicationAdapter extends RecyclerView.Adapter