diff --git a/core/src/main/java/io/github/lsposed/lspd/config/LSPApplicationServiceClient.java b/core/src/main/java/io/github/lsposed/lspd/config/LSPApplicationServiceClient.java index d0d72020..c8e0af0e 100644 --- a/core/src/main/java/io/github/lsposed/lspd/config/LSPApplicationServiceClient.java +++ b/core/src/main/java/io/github/lsposed/lspd/config/LSPApplicationServiceClient.java @@ -15,7 +15,6 @@ public class LSPApplicationServiceClient implements ILSPApplicationService { static IBinder serviceBinder = null; static String baseCachePath = null; - static String basePrefsPath = null; static String processName = null; public static LSPApplicationServiceClient serviceClient = null; @@ -99,16 +98,14 @@ public class LSPApplicationServiceClient implements ILSPApplicationService { return new String[0]; } - public String[] getModulesList(){ + public String[] getModulesList() { return getModulesList(processName); } @Override public String getPrefsPath(String packageName) { try { - if (basePrefsPath == null) - basePrefsPath = service.getPrefsPath(""); - return basePrefsPath + File.separator + packageName; + return service.getPrefsPath(packageName); } catch (RemoteException | NullPointerException ignored) { } return null; diff --git a/core/src/main/java/io/github/lsposed/lspd/hooker/HandleBindAppHooker.java b/core/src/main/java/io/github/lsposed/lspd/hooker/HandleBindAppHooker.java index 18935dea..59bafe75 100644 --- a/core/src/main/java/io/github/lsposed/lspd/hooker/HandleBindAppHooker.java +++ b/core/src/main/java/io/github/lsposed/lspd/hooker/HandleBindAppHooker.java @@ -29,6 +29,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; import android.content.res.XResources; +import android.os.IBinder; import io.github.lsposed.lspd.util.Hookers; import io.github.lsposed.lspd.util.MetaDataReader; @@ -68,12 +69,6 @@ public class HandleBindAppHooker extends XC_MethodHook { Utils.logD("processName=" + appProcessName + ", packageName=" + reportedPackageName + ", appDataDir=" + appDataDir); - ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName"); - if (instrumentationName != null) { - Hookers.logD("Instrumentation detected, disabling framework for"); - XposedBridge.disableHooks = true; - return; - } CompatibilityInfo compatInfo = (CompatibilityInfo) XposedHelpers.getObjectField(bindData, "compatInfo"); if (appInfo.sourceDir == null) { return; @@ -87,14 +82,14 @@ public class HandleBindAppHooker extends XC_MethodHook { String processName = (String) XposedHelpers.getObjectField(bindData, "processName"); - boolean isModule = false; + IBinder moduleBinder = serviceClient.requestModuleBinder(); + boolean isModule = moduleBinder != null; int xposedminversion = -1; boolean xposedsharedprefs = false; boolean xposedmigrateprefs = false; try { - Map metaData = MetaDataReader.getMetaData(new File(appInfo.sourceDir)); - isModule = metaData.containsKey("xposedmodule"); if (isModule) { + Map metaData = MetaDataReader.getMetaData(new File(appInfo.sourceDir)); Object minVersionRaw = metaData.get("xposedminversion"); if (minVersionRaw instanceof Integer) { xposedminversion = (Integer) minVersionRaw; diff --git a/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java b/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java index b0354138..ba5c6591 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java @@ -33,7 +33,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -83,6 +82,7 @@ public class ConfigManager { public void onEvent(int event, @Nullable String path) { updateConfig(); cacheScopes(); + cacheModules(); } }; @@ -126,6 +126,8 @@ public class ConfigManager { private final ConcurrentHashMap> cachedScope = new ConcurrentHashMap<>(); + private final ConcurrentHashMap cachedModule = new ConcurrentHashMap<>(); + // for system server, cache is not yet ready, we need to query database for it public boolean shouldSkipSystemServer() { try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"modules.mid"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) { @@ -214,6 +216,7 @@ public class ConfigManager { Log.d(TAG, "pm is ready, updating cache"); instance.packageStarted = true; instance.cacheScopes(); + instance.cacheModules(); instance.updateManager(); } } @@ -226,6 +229,7 @@ public class ConfigManager { isPermissive = readInt(selinuxPath, 1) == 0; configObserver.startWatching(); cacheScopes(); + cacheModules(); } private void createTables() { @@ -242,6 +246,41 @@ public class ConfigManager { return processes; } + private synchronized void cacheModules() { + // skip caching when pm is not yet available + if (!packageStarted) return; + cachedModule.clear(); + try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"}, + "enabled = 1", null, null, null, null)) { + if (cursor == null) { + Log.e(TAG, "db cache failed"); + return; + } + int pkgNameIdx = cursor.getColumnIndex("module_pkg_name"); + HashSet obsoleteModules = new HashSet<>(); + while (cursor.moveToNext()) { + String packageName = cursor.getString(pkgNameIdx); + try { + PackageInfo pkgInfo = PackageService.getPackageInfo(packageName, 0, 0); + if (pkgInfo != null && pkgInfo.applicationInfo != null) { + cachedModule.put(pkgInfo.applicationInfo.uid, pkgInfo.packageName); + } else { + obsoleteModules.add(packageName); + } + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(e)); + } + } + for (String obsoleteModule : obsoleteModules) { + removeModule(obsoleteModule); + } + } + Log.d(TAG, "cached modules"); + for (int uid : cachedModule.keySet()) { + Log.d(TAG, cachedModule.get(uid) + "/" + uid); + } + } + private synchronized void cacheScopes() { // skip caching when pm is not yet available if (!packageStarted) return; @@ -524,6 +563,34 @@ public class ConfigManager { } } + public boolean isModule(int uid) { + return cachedModule.containsKey(uid); + } + + private void recursivelyChown(File file, int uid, int gid) throws ErrnoException { + Os.chown(file.toString(), uid, gid); + if (file.isDirectory()) { + for (File subFile : file.listFiles()) { + recursivelyChown(subFile, uid, gid); + } + } + } + + public boolean ensureModulePrefsPermission(int uid) { + String packageName = cachedModule.get(uid); + if (packageName == null) return false; + File path = new File(getPrefsPath(packageName)); + try { + if (path.exists() && !path.isDirectory()) path.delete(); + if (!path.exists()) Files.createDirectories(path.toPath()); + recursivelyChown(path, uid, 1000); + return true; + } catch (IOException | ErrnoException e) { + Log.e(TAG, Log.getStackTraceString(e)); + return false; + } + } + // migrate setting @Keep public static void main(String[] args) { @@ -541,9 +608,9 @@ public class ConfigManager { int userId = Integer.parseInt(dir.getName()); System.out.println("Processing user: " + userId); File conf = new File(dir, "conf"); - if (!conf.exists()) System.exit(0); + if (!conf.exists()) continue; File enabledModules = new File(conf, "enabled_modules.list"); - if (!enabledModules.exists()) System.exit(0); + if (!enabledModules.exists()) continue; System.out.println("updating modules..."); @@ -577,6 +644,7 @@ public class ConfigManager { } } + System.out.println("Applying scope"); for (HashMap.Entry> entry : modulesScope.entrySet()) { getInstance().setModuleScope(entry.getKey(), entry.getValue()); } diff --git a/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java b/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java index 95daf6f6..b3ac2df2 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java @@ -75,11 +75,13 @@ public class LSPApplicationService extends ILSPApplicationService.Stub { return ConfigManager.getInstance().getModulesLog(ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND); } - // TODO: check if module @Override public IBinder requestModuleBinder() throws RemoteException { ensureRegistered(); - return ServiceManager.getModuleService(); + if (ConfigManager.getInstance().isModule(Binder.getCallingUid())) { + ConfigManager.getInstance().ensureModulePrefsPermission(Binder.getCallingUid()); + return ServiceManager.getModuleService(); + } else return null; } @Override