[core] Cache & check module

This commit is contained in:
LoveSy 2021-02-20 19:41:38 +08:00 committed by tehcneko
parent f56cf01e9f
commit a12336f69b
4 changed files with 81 additions and 19 deletions

View File

@ -15,7 +15,6 @@ public class LSPApplicationServiceClient implements ILSPApplicationService {
static IBinder serviceBinder = null; static IBinder serviceBinder = null;
static String baseCachePath = null; static String baseCachePath = null;
static String basePrefsPath = null;
static String processName = null; static String processName = null;
public static LSPApplicationServiceClient serviceClient = null; public static LSPApplicationServiceClient serviceClient = null;
@ -106,9 +105,7 @@ public class LSPApplicationServiceClient implements ILSPApplicationService {
@Override @Override
public String getPrefsPath(String packageName) { public String getPrefsPath(String packageName) {
try { try {
if (basePrefsPath == null) return service.getPrefsPath(packageName);
basePrefsPath = service.getPrefsPath("");
return basePrefsPath + File.separator + packageName;
} catch (RemoteException | NullPointerException ignored) { } catch (RemoteException | NullPointerException ignored) {
} }
return null; return null;

View File

@ -29,6 +29,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo; import android.content.res.CompatibilityInfo;
import android.content.res.XResources; import android.content.res.XResources;
import android.os.IBinder;
import io.github.lsposed.lspd.util.Hookers; import io.github.lsposed.lspd.util.Hookers;
import io.github.lsposed.lspd.util.MetaDataReader; import io.github.lsposed.lspd.util.MetaDataReader;
@ -68,12 +69,6 @@ public class HandleBindAppHooker extends XC_MethodHook {
Utils.logD("processName=" + appProcessName + Utils.logD("processName=" + appProcessName +
", packageName=" + reportedPackageName + ", appDataDir=" + appDataDir); ", 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"); CompatibilityInfo compatInfo = (CompatibilityInfo) XposedHelpers.getObjectField(bindData, "compatInfo");
if (appInfo.sourceDir == null) { if (appInfo.sourceDir == null) {
return; return;
@ -87,14 +82,14 @@ public class HandleBindAppHooker extends XC_MethodHook {
String processName = (String) XposedHelpers.getObjectField(bindData, "processName"); String processName = (String) XposedHelpers.getObjectField(bindData, "processName");
boolean isModule = false; IBinder moduleBinder = serviceClient.requestModuleBinder();
boolean isModule = moduleBinder != null;
int xposedminversion = -1; int xposedminversion = -1;
boolean xposedsharedprefs = false; boolean xposedsharedprefs = false;
boolean xposedmigrateprefs = false; boolean xposedmigrateprefs = false;
try { try {
Map<String, Object> metaData = MetaDataReader.getMetaData(new File(appInfo.sourceDir));
isModule = metaData.containsKey("xposedmodule");
if (isModule) { if (isModule) {
Map<String, Object> metaData = MetaDataReader.getMetaData(new File(appInfo.sourceDir));
Object minVersionRaw = metaData.get("xposedminversion"); Object minVersionRaw = metaData.get("xposedminversion");
if (minVersionRaw instanceof Integer) { if (minVersionRaw instanceof Integer) {
xposedminversion = (Integer) minVersionRaw; xposedminversion = (Integer) minVersionRaw;

View File

@ -33,7 +33,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -83,6 +82,7 @@ public class ConfigManager {
public void onEvent(int event, @Nullable String path) { public void onEvent(int event, @Nullable String path) {
updateConfig(); updateConfig();
cacheScopes(); cacheScopes();
cacheModules();
} }
}; };
@ -126,6 +126,8 @@ public class ConfigManager {
private final ConcurrentHashMap<ProcessScope, Set<String>> cachedScope = new ConcurrentHashMap<>(); private final ConcurrentHashMap<ProcessScope, Set<String>> cachedScope = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, String> cachedModule = new ConcurrentHashMap<>();
// for system server, cache is not yet ready, we need to query database for it // for system server, cache is not yet ready, we need to query database for it
public boolean shouldSkipSystemServer() { 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)) { 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"); Log.d(TAG, "pm is ready, updating cache");
instance.packageStarted = true; instance.packageStarted = true;
instance.cacheScopes(); instance.cacheScopes();
instance.cacheModules();
instance.updateManager(); instance.updateManager();
} }
} }
@ -226,6 +229,7 @@ public class ConfigManager {
isPermissive = readInt(selinuxPath, 1) == 0; isPermissive = readInt(selinuxPath, 1) == 0;
configObserver.startWatching(); configObserver.startWatching();
cacheScopes(); cacheScopes();
cacheModules();
} }
private void createTables() { private void createTables() {
@ -242,6 +246,41 @@ public class ConfigManager {
return processes; 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<String> 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() { private synchronized void cacheScopes() {
// skip caching when pm is not yet available // skip caching when pm is not yet available
if (!packageStarted) return; 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 // migrate setting
@Keep @Keep
public static void main(String[] args) { public static void main(String[] args) {
@ -541,9 +608,9 @@ public class ConfigManager {
int userId = Integer.parseInt(dir.getName()); int userId = Integer.parseInt(dir.getName());
System.out.println("Processing user: " + userId); System.out.println("Processing user: " + userId);
File conf = new File(dir, "conf"); File conf = new File(dir, "conf");
if (!conf.exists()) System.exit(0); if (!conf.exists()) continue;
File enabledModules = new File(conf, "enabled_modules.list"); File enabledModules = new File(conf, "enabled_modules.list");
if (!enabledModules.exists()) System.exit(0); if (!enabledModules.exists()) continue;
System.out.println("updating modules..."); System.out.println("updating modules...");
@ -577,6 +644,7 @@ public class ConfigManager {
} }
} }
System.out.println("Applying scope");
for (HashMap.Entry<String, List<Application>> entry : modulesScope.entrySet()) { for (HashMap.Entry<String, List<Application>> entry : modulesScope.entrySet()) {
getInstance().setModuleScope(entry.getKey(), entry.getValue()); getInstance().setModuleScope(entry.getKey(), entry.getValue());
} }

View File

@ -75,11 +75,13 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
return ConfigManager.getInstance().getModulesLog(ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND); return ConfigManager.getInstance().getModulesLog(ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_APPEND);
} }
// TODO: check if module
@Override @Override
public IBinder requestModuleBinder() throws RemoteException { public IBinder requestModuleBinder() throws RemoteException {
ensureRegistered(); ensureRegistered();
if (ConfigManager.getInstance().isModule(Binder.getCallingUid())) {
ConfigManager.getInstance().ensureModulePrefsPermission(Binder.getCallingUid());
return ServiceManager.getModuleService(); return ServiceManager.getModuleService();
} else return null;
} }
@Override @Override