From 3f55be96765fc38ace0dc419ccb0c9e3c35359b5 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 31 Jan 2018 04:00:11 +0800 Subject: [PATCH] Update the method to handle global su db --- .../com/topjohnwu/magisk/MagiskManager.java | 7 +- .../topjohnwu/magisk/asyncs/HideManager.java | 2 +- .../magisk/asyncs/InstallMagisk.java | 2 +- .../magisk/database/SuDatabaseHelper.java | 208 +++++++----------- .../magisk/superuser/RequestActivity.java | 2 +- .../com/topjohnwu/magisk/utils/Utils.java | 4 +- 6 files changed, 87 insertions(+), 138 deletions(-) diff --git a/src/main/java/com/topjohnwu/magisk/MagiskManager.java b/src/main/java/com/topjohnwu/magisk/MagiskManager.java index ba19c70aa..366fb07f1 100644 --- a/src/main/java/com/topjohnwu/magisk/MagiskManager.java +++ b/src/main/java/com/topjohnwu/magisk/MagiskManager.java @@ -119,7 +119,7 @@ public class MagiskManager extends Shell.ContainerApp { } catch (PackageManager.NameNotFoundException ignored) { /* Expected */ } } - suDB = SuDatabaseHelper.getSuDB(false); + suDB = SuDatabaseHelper.getInstance(this); repoDB = new RepoDatabaseHelper(this); defaultLocale = Locale.getDefault(); setLocale(); @@ -219,11 +219,6 @@ public class MagiskManager extends Shell.ContainerApp { ret = Shell.Sync.su("echo \"$BOOTIMAGE\""); if (Utils.isValidShellResponse(ret)) bootBlock = ret.get(0); - - if (suDB != null && !SuDatabaseHelper.verified) { - suDB.close(); - suDB = SuDatabaseHelper.getSuDB(true); - } } public void getDefaultInstallFlags() { diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java b/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java index cae13457c..262a4ae93 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java @@ -4,13 +4,13 @@ import android.app.Activity; import android.app.ProgressDialog; import android.widget.Toast; -import com.topjohnwu.utils.JarMap; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.ZipUtils; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.utils.JarMap; import java.io.File; import java.io.FileInputStream; diff --git a/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java b/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java index 9418e3660..0dd9694ff 100644 --- a/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java +++ b/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java @@ -7,7 +7,6 @@ import android.os.Build; import android.text.TextUtils; import android.view.View; -import com.topjohnwu.utils.SignBoot; import com.topjohnwu.magisk.FlashActivity; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.container.TarEntry; @@ -15,6 +14,7 @@ import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.ZipUtils; import com.topjohnwu.superuser.Shell; +import com.topjohnwu.utils.SignBoot; import org.kamranzafar.jtar.TarInputStream; import org.kamranzafar.jtar.TarOutputStream; diff --git a/src/main/java/com/topjohnwu/magisk/database/SuDatabaseHelper.java b/src/main/java/com/topjohnwu/magisk/database/SuDatabaseHelper.java index e8f0319e7..cd52d5998 100644 --- a/src/main/java/com/topjohnwu/magisk/database/SuDatabaseHelper.java +++ b/src/main/java/com/topjohnwu/magisk/database/SuDatabaseHelper.java @@ -5,8 +5,8 @@ import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; import android.os.Build; +import android.os.Process; import android.text.TextUtils; import android.widget.Toast; @@ -25,142 +25,99 @@ import java.util.Collections; import java.util.Date; import java.util.List; -public class SuDatabaseHelper extends SQLiteOpenHelper { - - public static final String DB_NAME = "su.db"; - public static boolean verified = false; +public class SuDatabaseHelper { private static final int DATABASE_VER = 5; private static final String POLICY_TABLE = "policies"; private static final String LOG_TABLE = "logs"; private static final String SETTINGS_TABLE = "settings"; private static final String STRINGS_TABLE = "strings"; - private static final File GLOBAL_DB = new File("/data/adb/magisk.db"); - private Context mContext; private PackageManager pm; private SQLiteDatabase mDb; - private static void unmntDB() { - Shell.Sync.su(Utils.fmt("umount -l /data/user*/*/%s/*/*.db", MagiskManager.get().getPackageName())); - } - - private static Context initDB(boolean verify) { - Context context, de = null; - MagiskManager ce = MagiskManager.get(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - de = ce.createDeviceProtectedStorageContext(); - File ceDB = Utils.getDB(ce, DB_NAME); - if (ceDB.exists()) { - context = ce; - } else { - context = de; - } - } else { - context = ce; - } - - File db = Utils.getDB(context, DB_NAME); - if (!verify) { - if (db.exists() && db.length() == 0) { - ce.loadMagiskInfo(); - // Continue verification - } else { - return context; - } - } - - // Encryption storage - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - if (ce.magiskVersionCode < 1410) { - if (context == de) { - unmntDB(); - ce.moveDatabaseFrom(de, DB_NAME); - context = ce; - } - } else { - if (context == ce) { - unmntDB(); - de.moveDatabaseFrom(ce, DB_NAME); - context = de; - } - } - } - // Context might be updated - db = Utils.getDB(context, DB_NAME); - - if (!Shell.rootAccess()) - return context; - - // Verify the global db matches the local with the same inode - if (ce.magiskVersionCode >= 1450 && ce.magiskVersionCode < 1460) { - // v14.5 global su db - File OLD_GLOBAL_DB = new File(context.getFilesDir().getParentFile().getParentFile(), "magisk.db"); - verified = TextUtils.equals(Utils.checkInode(OLD_GLOBAL_DB), Utils.checkInode(db)); - if (!verified) { - context.deleteDatabase(DB_NAME); - db.getParentFile().mkdirs(); - Shell.Sync.su(Utils.fmt("magisk --clone-attr %s %s; chmod 600 %s; ln %s %s", - context.getFilesDir(), OLD_GLOBAL_DB, OLD_GLOBAL_DB, OLD_GLOBAL_DB, db)); - verified = TextUtils.equals(Utils.checkInode(OLD_GLOBAL_DB), Utils.checkInode(db)); - } - } else if (ce.magiskVersionCode >= 1464) { - // New global su db - Shell.Sync.su(Utils.fmt("mkdir %s 2>/dev/null; chmod 700 %s", GLOBAL_DB.getParent(), GLOBAL_DB.getParent())); - if (!Utils.itemExist(GLOBAL_DB)) { - context.openOrCreateDatabase(DB_NAME, 0, null).close(); - Shell.Sync.su(Utils.fmt("cp -af %s %s; rm -f %s*", db, GLOBAL_DB, db)); - } - verified = TextUtils.equals(Utils.checkInode(GLOBAL_DB), Utils.checkInode(db)); - if (!verified) { - context.deleteDatabase(DB_NAME); - Utils.javaCreateFile(db); - Shell.Sync.su(Utils.fmt( - "chown 0.0 %s; chmod 666 %s; chcon u:object_r:su_file:s0 %s;" + - "mount -o bind %s %s", - GLOBAL_DB, GLOBAL_DB, GLOBAL_DB, GLOBAL_DB, db)); - verified = TextUtils.equals(Utils.checkInode(GLOBAL_DB), Utils.checkInode(db)); - } - } - return context; - } - - public static SuDatabaseHelper getSuDB(boolean verify) { + public static SuDatabaseHelper getInstance(MagiskManager mm) { try { - return new SuDatabaseHelper(initDB(verify)); - } catch(Exception e) { - // Try to catch runtime exceptions and remove all db for retry - unmntDB(); - Shell.Sync.su(Utils.fmt("rm -rf /data/user*/*/magisk.db /data/adb/magisk.db /data/user*/*/%s/databases", - MagiskManager.get().getPackageName())); - e.printStackTrace(); - return new SuDatabaseHelper(initDB(false)); + return new SuDatabaseHelper(mm); + } catch (Exception e) { + // Let's cleanup and try again + cleanup(); + return new SuDatabaseHelper(mm); } } - private SuDatabaseHelper(Context context) { - super(context, DB_NAME, null, DATABASE_VER); - mContext = context; - pm = context.getPackageManager(); - mDb = getWritableDatabase(); - cleanup(); + public static void cleanup() { + Shell.Sync.su( + "umount -l /data/user*/*/*/databases/su.db /sbin/.core/db-*/magisk.db", + "rm -rf /sbin/.core/db-*"); + } - if (context.getPackageName().equals(Const.ORIG_PKG_NAME)) { - String pkg = getStrings(Const.Key.SU_REQUESTER, null); - if (pkg != null) { - Utils.uninstallPkg(pkg); - setStrings(Const.Key.SU_REQUESTER, null); + private SuDatabaseHelper(MagiskManager mm) { + pm = mm.getPackageManager(); + mDb = openDatabase(mm); + clearOutdated(); + } + + private SQLiteDatabase openDatabase(MagiskManager mm) { + SQLiteDatabase db = null; + String GLOBAL_DB = "/data/adb/magisk.db"; + File dbFile = new File(Utils.fmt("/sbin/.core/db-%s/magisk.db", mm.getPackageName())); + Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N + ? mm.createDeviceProtectedStorageContext() : mm; + if (!dbFile.exists()) { + if (!Shell.rootAccess()) { + // We don't want the app to crash, create a db and return + return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null); + } + mm.loadMagiskInfo(); + // Cleanup + cleanup(); + if (mm.magiskVersionCode < 1410) { + // Super old legacy mode + db = mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null); + } else if (mm.magiskVersionCode < 1450) { + // Legacy mode with FBE aware + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + de.moveDatabaseFrom(mm, "su.db"); + } + db = de.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null); + } else { + mm.deleteDatabase("su.db"); + de.deleteDatabase("su.db"); + if (mm.magiskVersionCode < 1460) { + // v14.5 global DB location + GLOBAL_DB = new File(de.getFilesDir().getParentFile().getParentFile(), + "magisk.db").getPath(); + // We need some additional policies on old versions + Shell.Sync.su("magiskpolicy --live 'create su_file' 'allow * su_file file *'"); + } + // Touch global DB and setup db in tmpfs + Shell.Sync.su(Utils.fmt("touch %s; mkdir -p %s; touch %s; touch %s-journal;" + + "mount -o bind %s %s;" + + "chcon u:object_r:su_file:s0 %s/*; chown %d.%d %s;" + + "chmod 666 %s/*; chmod 700 %s;", + GLOBAL_DB, dbFile.getParent(), dbFile, dbFile, + GLOBAL_DB, dbFile, + dbFile.getParent(), Process.myUid(), Process.myUid(), dbFile.getParent(), + dbFile.getParent(), dbFile.getParent() + )); } } + if (db == null) { + // Not using legacy mode, open the mounted global DB + db = SQLiteDatabase.openOrCreateDatabase(dbFile, null); + } + int version = db.getVersion(); + if (version < DATABASE_VER) { + onUpgrade(db, version); + } else if (version > DATABASE_VER) { + onDowngrade(db); + } + db.setVersion(DATABASE_VER); + return db; } - @Override - public void onCreate(SQLiteDatabase db) { - onUpgrade(db, 0, DATABASE_VER); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + public void onUpgrade(SQLiteDatabase db, int oldVersion) { try { if (oldVersion == 0) { createTables(db); @@ -196,23 +153,18 @@ public class SuDatabaseHelper extends SQLiteOpenHelper { } } catch (Exception e) { e.printStackTrace(); - onDowngrade(db, DATABASE_VER, 0); + onDowngrade(db); } } - @Override - public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { + // Remove everything, we do not support downgrade + public void onDowngrade(SQLiteDatabase db) { MagiskManager.toast(R.string.su_db_corrupt, Toast.LENGTH_LONG); - // Remove everything, we do not support downgrade db.execSQL("DROP TABLE IF EXISTS " + POLICY_TABLE); db.execSQL("DROP TABLE IF EXISTS " + LOG_TABLE); db.execSQL("DROP TABLE IF EXISTS " + SETTINGS_TABLE); db.execSQL("DROP TABLE IF EXISTS " + STRINGS_TABLE); - onUpgrade(db, 0, DATABASE_VER); - } - - public File getDbFile() { - return mContext.getDatabasePath(DB_NAME); + onUpgrade(db, 0); } private void createTables(SQLiteDatabase db) { @@ -235,7 +187,7 @@ public class SuDatabaseHelper extends SQLiteOpenHelper { "(key TEXT, value INT, PRIMARY KEY(key))"); } - public void cleanup() { + public void clearOutdated() { // Clear outdated policies mDb.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null); // Clear outdated logs diff --git a/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java b/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java index 31e2990c6..bede50060 100644 --- a/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java +++ b/src/main/java/com/topjohnwu/magisk/superuser/RequestActivity.java @@ -68,7 +68,7 @@ public class RequestActivity extends Activity { pm = getPackageManager(); mm = Utils.getMagiskManager(this); - mm.suDB.cleanup(); + mm.suDB.clearOutdated(); Intent intent = getIntent(); socketPath = intent.getStringExtra("socket"); diff --git a/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 93c3c65df..0afa1acb0 100644 --- a/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -28,6 +28,7 @@ import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.SplashActivity; import com.topjohnwu.magisk.components.SnackbarMaker; +import com.topjohnwu.magisk.database.SuDatabaseHelper; import com.topjohnwu.magisk.receivers.DownloadReceiver; import com.topjohnwu.superuser.Shell; @@ -80,7 +81,8 @@ public class Utils { } public static void uninstallPkg(String pkg) { - Shell.Sync.su(fmt("umount -l /data/user*/*/%s/*/*.db 2>/dev/null; pm uninstall %s", pkg, pkg)); + SuDatabaseHelper.cleanup(); + Shell.Sync.su("pm uninstall " + pkg); } public static void dlAndReceive(Context context, DownloadReceiver receiver, String link, String filename) {