Remove all backwards compatibility nonsense

This also allows full obfuscation
This commit is contained in:
topjohnwu 2018-12-08 03:54:00 -05:00
parent a54eaf5371
commit c91f809eba
20 changed files with 188 additions and 717 deletions

View File

@ -24,6 +24,7 @@
# Snet extention
-keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; }
-keepclassmembers class com.topjohnwu.magisk.utils.BootSigner { *; }
# Fast Android Networking Library
-dontwarn okhttp3.**

View File

@ -53,15 +53,6 @@
android:taskAffinity="internal.superuser"
android:theme="@style/SuRequest" />
<activity
android:name=".superuser.RequestActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity="internal.superuser"
android:theme="@style/AppTheme.Translucent" />
<receiver android:name=".superuser.SuReceiver" />
<!-- Receiver -->
<receiver android:name="a.h">

View File

@ -10,7 +10,6 @@ import java.util.List;
public class Const {
public static final String DEBUG_TAG = "MagiskManager";
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
// APK content
public static final String ANDROID_MANIFEST = "AndroidManifest.xml";
@ -47,11 +46,7 @@ public class Const {
public static final int USER_ID = Process.myUid() / 100000;
public static final class MAGISK_VER {
public static final int SEPOL_REFACTOR = 1640;
public static final int FIX_ENV = 1650;
public static final int DBVER_SIX = 17000;
public static final int CMDLINE_DB = 17305;
public static final int HIDE_STATUS = 17315;
/* Currently no backwards compatibility needed */
}
public static class ID {

View File

@ -83,12 +83,7 @@ public class Data {
try {
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
if (magiskVersionCode >= Const.MAGISK_VER.HIDE_STATUS) {
magiskHide = Shell.su("magiskhide --status").exec().isSuccess();
} else {
String s = ShellUtils.fastCmd(("resetprop -p ") + Const.MAGISKHIDE_PROP);
magiskHide = s.isEmpty() || Integer.parseInt(s) != 0;
}
} catch (NumberFormatException ignored) {}
}

View File

@ -15,7 +15,6 @@ import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.FlashZip;
import com.topjohnwu.magisk.asyncs.InstallMagisk;
import com.topjohnwu.magisk.components.BaseActivity;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.CallbackList;
import com.topjohnwu.superuser.Shell;
@ -160,7 +159,7 @@ public class FlashActivity extends BaseActivity {
protected void onPostExecute(Integer result) {
if (result == 1) {
Data.mainHandler.postDelayed(() ->
RootUtils.uninstallPkg(getActivity().getPackageName()), 3000);
Shell.su("pm uninstall " + getActivity().getPackageName()).exec(), 3000);
} else {
super.onPostExecute(result);
}

View File

@ -20,8 +20,8 @@ public class MagiskManager extends ContainerApp {
// Global resources
public SharedPreferences prefs;
public MagiskDB mDB;
public RepoDatabaseHelper repoDB;
public MagiskDB mDB;
public MagiskManager() {
Data.weakApp = new WeakReference<>(this);
@ -37,8 +37,8 @@ public class MagiskManager extends ContainerApp {
Shell.Config.setTimeout(2);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
mDB = MagiskDB.getInstance();
repoDB = new RepoDatabaseHelper(this);
mDB = new MagiskDB(this);
LocaleManager.setLocale(this);
Data.loadConfig();

View File

@ -12,7 +12,6 @@ import com.topjohnwu.magisk.components.Notifications;
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
import com.topjohnwu.magisk.utils.Download;
import com.topjohnwu.magisk.utils.LocaleManager;
import com.topjohnwu.magisk.utils.RootUtils;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
@ -31,7 +30,7 @@ public class SplashActivity extends BaseActivity {
try {
// We are the manager, remove com.topjohnwu.magisk as it could be malware
getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
RootUtils.uninstallPkg(BuildConfig.APPLICATION_ID);
Shell.su("pm uninstall " + BuildConfig.APPLICATION_ID).submit();
} catch (PackageManager.NameNotFoundException ignored) {}
}

View File

@ -3,10 +3,8 @@ package com.topjohnwu.magisk;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.net.LocalSocketAddress;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.FileObserver;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;
@ -43,48 +41,6 @@ public class SuRequestActivity extends BaseActivity {
private CountDownTimer timer;
private FingerprintHelper fingerprintHelper;
class SuConnectorV1 extends SuConnector {
SuConnectorV1(String name) throws IOException {
super(name);
}
@Override
public void connect(String name) throws IOException {
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.FILESYSTEM));
new FileObserver(name) {
@Override
public void onEvent(int fileEvent, String path) {
if (fileEvent == FileObserver.DELETE_SELF) {
finish();
}
}
}.startWatching();
}
@Override
public void onResponse() throws IOException {
out.write((policy.policy == Policy.ALLOW ? "socket:ALLOW" : "socket:DENY").getBytes());
}
}
class SuConnectorV2 extends SuConnector {
SuConnectorV2(String name) throws IOException {
super(name);
}
@Override
public void connect(String name) throws IOException {
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));
}
@Override
public void onResponse() throws IOException {
out.writeInt(policy.policy);
}
}
@Override
public int getDarkTheme() {
return R.style.SuRequest_Dark;
@ -120,8 +76,12 @@ public class SuRequestActivity extends BaseActivity {
Intent intent = getIntent();
try {
String socketName = intent.getStringExtra("socket");
connector = intent.getIntExtra("version", 1) == 1 ?
new SuConnectorV1(socketName) : new SuConnectorV2(socketName);
connector = new SuConnector(socketName) {
@Override
protected void onResponse() throws IOException {
out.writeInt(policy.policy);
}
};
Bundle bundle = connector.readSocketInput();
int uid = Integer.parseInt(bundle.getString("uid"));
policy = mm.mDB.getPolicy(uid);

View File

@ -342,18 +342,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
console.add("- Target image: " + mBoot);
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
String arch;
if (Data.remoteMagiskVersionCode >= Const.MAGISK_VER.SEPOL_REFACTOR) {
// 32-bit only
if (abis.contains("x86")) arch = "x86";
else arch = "arm";
} else {
if (abis.contains("x86_64")) arch = "x64";
else if (abis.contains("arm64-v8a")) arch = "arm64";
else if (abis.contains("x86")) arch = "x86";
else arch = "arm";
}
String arch = abis.contains("x86") ? "x86" : "arm";
console.add("- Device platform: " + Build.SUPPORTED_ABIS[0]);

View File

@ -1,66 +1,197 @@
package com.topjohnwu.magisk.database;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.utils.LocaleManager;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import androidx.annotation.NonNull;
import java.util.Map;
public class MagiskDB {
static final String POLICY_TABLE = "policies";
static final String LOG_TABLE = "logs";
static final String SETTINGS_TABLE = "settings";
static final String STRINGS_TABLE = "strings";
static final File LEGACY_MANAGER_DB =
new File(Utils.fmt("/sbin/.magisk/db-%d/magisk.db", Const.USER_ID));
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";
@NonNull
public static MagiskDB getInstance() {
if (LEGACY_MANAGER_DB.canWrite()) {
return MagiskDBLegacy.newInstance();
} else if (Shell.rootAccess()) {
return Data.magiskVersionCode >= Const.MAGISK_VER.CMDLINE_DB ?
new MagiskDBCmdline() : MagiskDBLegacy.newInstance();
} else {
return new MagiskDB();
}
}
private PackageManager pm;
public void clearOutdated() {}
public MagiskDB(Context context) {
pm = context.getPackageManager();
}
public void deletePolicy(Policy policy) {
deletePolicy(policy.uid);
}
public void deletePolicy(String pkg) {}
public void deletePolicy(int uid) {}
public Policy getPolicy(int uid) { return null; }
public void updatePolicy(Policy policy) {}
public List<Policy> getPolicyList() { return Collections.emptyList(); }
public List<List<SuLogEntry>> getLogs() { return Collections.emptyList(); }
public void addLog(SuLogEntry log) {}
public void clearLogs() {}
public void setSettings(String key, int value) {}
public int getSettings(String key, int defaultValue) { return defaultValue; }
public void setStrings(String key, String value) {}
public String getStrings(String key, String defaultValue) { return defaultValue; }
private List<String> rawSQL(String fmt, Object... args) {
return Shell.su("magisk --sqlite '" + Utils.fmt(fmt, args) + "'").exec().getOut();
}
private List<ContentValues> SQL(String fmt, Object... args) {
List<ContentValues> list = new ArrayList<>();
for (String raw : rawSQL(fmt, args)) {
ContentValues values = new ContentValues();
String[] cols = raw.split("\\|");
for (String col : cols) {
String[] pair = col.split("=", 2);
if (pair.length != 2)
continue;
values.put(pair[0], pair[1]);
}
list.add(values);
}
return list;
}
private String toSQL(ContentValues values) {
StringBuilder keys = new StringBuilder(), vals = new StringBuilder();
keys.append('(');
vals.append("VALUES(");
boolean first = true;
for (Map.Entry<String, Object> entry : values.valueSet()) {
if (!first) {
keys.append(',');
vals.append(',');
} else {
first = false;
}
keys.append(entry.getKey());
vals.append('"');
vals.append(entry.getValue());
vals.append('"');
}
keys.append(')');
vals.append(')');
keys.append(vals);
return keys.toString();
}
public void clearOutdated() {
rawSQL(
"DELETE FROM %s WHERE until > 0 AND until < %d;" +
"DELETE FROM %s WHERE time < %d",
POLICY_TABLE, System.currentTimeMillis() / 1000,
LOG_TABLE, System.currentTimeMillis() - Data.suLogTimeout * 86400000
);
}
public void deletePolicy(String pkg) {
rawSQL("DELETE FROM %s WHERE package_name=\"%s\"", POLICY_TABLE, pkg);
}
public void deletePolicy(int uid) {
rawSQL("DELETE FROM %s WHERE uid=%d", POLICY_TABLE, uid);
}
public Policy getPolicy(int uid) {
List<ContentValues> res =
SQL("SELECT * FROM %s WHERE uid=%d", POLICY_TABLE, uid);
if (!res.isEmpty()) {
try {
return new Policy(res.get(0), pm);
} catch (PackageManager.NameNotFoundException e) {
deletePolicy(uid);
}
}
return null;
}
public void updatePolicy(Policy policy) {
rawSQL("REPLACE INTO %s %s", POLICY_TABLE, toSQL(policy.getContentValues()));
}
public List<Policy> getPolicyList() {
List<Policy> list = new ArrayList<>();
for (ContentValues values : SQL("SELECT * FROM %s WHERE uid/100000=%d", POLICY_TABLE, Const.USER_ID)) {
try {
list.add(new Policy(values, pm));
} catch (PackageManager.NameNotFoundException e) {
deletePolicy(values.getAsInteger("uid"));
}
}
Collections.sort(list);
return list;
}
public List<List<SuLogEntry>> getLogs() {
List<List<SuLogEntry>> ret = new ArrayList<>();
List<SuLogEntry> list = null;
String dateString = null, newString;
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
Date date = new Date(values.getAsLong("time"));
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
if (!TextUtils.equals(dateString, newString)) {
dateString = newString;
list = new ArrayList<>();
ret.add(list);
}
list.add(new SuLogEntry(values));
}
return ret;
}
public void addLog(SuLogEntry log) {
rawSQL("INSERT INTO %s %s", LOG_TABLE, toSQL(log.getContentValues()));
}
public void clearLogs() {
rawSQL("DELETE FROM %s", LOG_TABLE);
}
public void setSettings(String key, int value) {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
rawSQL("REPLACE INTO %s %s", SETTINGS_TABLE, toSQL(data));
}
public int getSettings(String key, int defaultValue) {
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", SETTINGS_TABLE, key);
if (res.isEmpty())
return defaultValue;
return res.get(0).getAsInteger("value");
}
public void setStrings(String key, String value) {
if (value == null) {
rawSQL("DELETE FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
return;
}
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
rawSQL("REPLACE INTO %s %s", STRINGS_TABLE, toSQL(data));
}
public String getStrings(String key, String defaultValue) {
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
if (res.isEmpty())
return defaultValue;
return res.get(0).getAsString("value");
}
}

View File

@ -1,189 +0,0 @@
package com.topjohnwu.magisk.database;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.utils.LocaleManager;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class MagiskDBCmdline extends MagiskDB {
private PackageManager pm;
public MagiskDBCmdline() {
pm = Data.MM().getPackageManager();
}
private List<String> rawSQL(String fmt, Object... args) {
return Shell.su("magisk --sqlite '" + Utils.fmt(fmt, args) + "'").exec().getOut();
}
private List<ContentValues> SQL(String fmt, Object... args) {
List<ContentValues> list = new ArrayList<>();
for (String raw : rawSQL(fmt, args)) {
ContentValues values = new ContentValues();
String[] cols = raw.split("\\|");
for (String col : cols) {
String[] pair = col.split("=", 2);
if (pair.length != 2)
continue;
values.put(pair[0], pair[1]);
}
list.add(values);
}
return list;
}
private String toSQL(ContentValues values) {
StringBuilder keys = new StringBuilder(), vals = new StringBuilder();
keys.append('(');
vals.append("VALUES(");
boolean first = true;
for (Map.Entry<String, Object> entry : values.valueSet()) {
if (!first) {
keys.append(',');
vals.append(',');
} else {
first = false;
}
keys.append(entry.getKey());
vals.append('"');
vals.append(entry.getValue());
vals.append('"');
}
keys.append(')');
vals.append(')');
keys.append(vals);
return keys.toString();
}
@Override
public void clearOutdated() {
rawSQL(
"DELETE FROM %s WHERE until > 0 AND until < %d;" +
"DELETE FROM %s WHERE time < %d",
POLICY_TABLE, System.currentTimeMillis() / 1000,
LOG_TABLE, System.currentTimeMillis() - Data.suLogTimeout * 86400000
);
}
@Override
public void deletePolicy(String pkg) {
rawSQL("DELETE FROM %s WHERE package_name=\"%s\"", POLICY_TABLE, pkg);
}
@Override
public void deletePolicy(int uid) {
rawSQL("DELETE FROM %s WHERE uid=%d", POLICY_TABLE, uid);
}
@Override
public Policy getPolicy(int uid) {
List<ContentValues> res =
SQL("SELECT * FROM %s WHERE uid=%d", POLICY_TABLE, uid);
if (!res.isEmpty()) {
try {
return new Policy(res.get(0), pm);
} catch (PackageManager.NameNotFoundException e) {
deletePolicy(uid);
}
}
return null;
}
@Override
public void updatePolicy(Policy policy) {
rawSQL("REPLACE INTO %s %s", POLICY_TABLE, toSQL(policy.getContentValues()));
}
@Override
public List<Policy> getPolicyList() {
List<Policy> list = new ArrayList<>();
for (ContentValues values : SQL("SELECT * FROM %s WHERE uid/100000=%d", POLICY_TABLE, Const.USER_ID)) {
try {
list.add(new Policy(values, pm));
} catch (PackageManager.NameNotFoundException e) {
deletePolicy(values.getAsInteger("uid"));
}
}
Collections.sort(list);
return list;
}
@Override
public List<List<SuLogEntry>> getLogs() {
List<List<SuLogEntry>> ret = new ArrayList<>();
List<SuLogEntry> list = null;
String dateString = null, newString;
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
Date date = new Date(values.getAsLong("time"));
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
if (!TextUtils.equals(dateString, newString)) {
dateString = newString;
list = new ArrayList<>();
ret.add(list);
}
list.add(new SuLogEntry(values));
}
return ret;
}
@Override
public void addLog(SuLogEntry log) {
rawSQL("INSERT INTO %s %s", LOG_TABLE, toSQL(log.getContentValues()));
}
@Override
public void clearLogs() {
rawSQL("DELETE FROM %s", LOG_TABLE);
}
@Override
public void setSettings(String key, int value) {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
rawSQL("REPLACE INTO %s %s", SETTINGS_TABLE, toSQL(data));
}
@Override
public int getSettings(String key, int defaultValue) {
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", SETTINGS_TABLE, key);
if (res.isEmpty())
return defaultValue;
return res.get(0).getAsInteger("value");
}
@Override
public void setStrings(String key, String value) {
if (value == null) {
rawSQL("DELETE FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
return;
}
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
rawSQL("REPLACE INTO %s %s", STRINGS_TABLE, toSQL(data));
}
@Override
public String getStrings(String key, String defaultValue) {
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
if (res.isEmpty())
return defaultValue;
return res.get(0).getAsString("value");
}
}

View File

@ -1,299 +0,0 @@
package com.topjohnwu.magisk.database;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Process;
import android.text.TextUtils;
import android.widget.Toast;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.utils.LocaleManager;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.io.SuFile;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class MagiskDBLegacy extends MagiskDB {
private static final int DATABASE_VER = 6;
private static final int OLD_DATABASE_VER = 5;
private PackageManager pm;
private SQLiteDatabase db;
static MagiskDBLegacy newInstance() {
try {
return new MagiskDBLegacy();
} catch (Exception e) {
// Let's cleanup everything and try again
Shell.su("db_clean '*'").exec();
return new MagiskDBLegacy();
}
}
private MagiskDBLegacy() {
pm = Data.MM().getPackageManager();
db = openDatabase();
db.disableWriteAheadLogging();
int version = Data.magiskVersionCode >= Const.MAGISK_VER.DBVER_SIX ? DATABASE_VER : OLD_DATABASE_VER;
int curVersion = db.getVersion();
if (curVersion < version) {
onUpgrade(db, curVersion);
} else if (curVersion > DATABASE_VER) {
/* Higher than we can possibly support */
onDowngrade(db);
}
db.setVersion(version);
clearOutdated();
}
private SQLiteDatabase openDatabase() {
MagiskManager mm = Data.MM();
Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
? mm.createDeviceProtectedStorageContext() : mm;
if (!LEGACY_MANAGER_DB.canWrite()) {
if (!Shell.rootAccess() || Data.magiskVersionCode < 0) {
// We don't want the app to crash, create a db and return
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
}
// Cleanup
Shell.su("db_clean " + Const.USER_ID).exec();
// Global database
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db");
mm.deleteDatabase("su.db");
de.deleteDatabase("su.db");
if (Data.magiskVersionCode < Const.MAGISK_VER.SEPOL_REFACTOR) {
// We need some additional policies on old versions
Shell.su("db_sepatch").exec();
}
if (!GLOBAL_DB.exists()) {
Shell.su("db_init").exec();
SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close();
Shell.su("db_restore").exec();
}
Shell.su("db_setup " + Process.myUid()).exec();
}
// Not using legacy mode, open the mounted global DB
return SQLiteDatabase.openOrCreateDatabase(LEGACY_MANAGER_DB, null);
}
private void onUpgrade(SQLiteDatabase db, int oldVersion) {
if (oldVersion == 0) {
createTables(db);
oldVersion = 3;
}
if (oldVersion == 1) {
// We're dropping column app_name, rename and re-construct table
db.execSQL(Utils.fmt("ALTER TABLE %s RENAME TO %s_old", POLICY_TABLE));
// Create the new tables
createTables(db);
// Migrate old data to new tables
db.execSQL(Utils.fmt("INSERT INTO %s SELECT " +
"uid, package_name, policy, until, logging, notification FROM %s_old",
POLICY_TABLE, POLICY_TABLE));
db.execSQL(Utils.fmt("DROP TABLE %s_old", POLICY_TABLE));
Data.MM().deleteDatabase("sulog.db");
++oldVersion;
}
if (oldVersion == 2) {
db.execSQL(Utils.fmt("UPDATE %s SET time=time*1000", LOG_TABLE));
++oldVersion;
}
if (oldVersion == 3) {
db.execSQL(Utils.fmt("CREATE TABLE IF NOT EXISTS %s (key TEXT, value TEXT, PRIMARY KEY(key))", STRINGS_TABLE));
++oldVersion;
}
if (oldVersion == 4) {
db.execSQL(Utils.fmt("UPDATE %s SET uid=uid%%100000", POLICY_TABLE));
++oldVersion;
}
if (oldVersion == 5) {
setSettings(Const.Key.SU_FINGERPRINT,
Data.MM().prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) ? 1 : 0);
++oldVersion;
}
}
// Remove everything, we do not support downgrade
private void onDowngrade(SQLiteDatabase db) {
Utils.toast(R.string.su_db_corrupt, Toast.LENGTH_LONG);
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);
}
private void createTables(SQLiteDatabase db) {
// Policies
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + POLICY_TABLE + " " +
"(uid INT, package_name TEXT, policy INT, " +
"until INT, logging INT, notification INT, " +
"PRIMARY KEY(uid))");
// Logs
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + LOG_TABLE + " " +
"(from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
"to_uid INT, action INT, time INT, command TEXT)");
// Settings
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + SETTINGS_TABLE + " " +
"(key TEXT, value INT, PRIMARY KEY(key))");
}
@Override
public void clearOutdated() {
// Clear outdated policies
db.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null);
// Clear outdated logs
db.delete(LOG_TABLE, Utils.fmt("time < %d", System.currentTimeMillis() - Data.suLogTimeout * 86400000), null);
}
@Override
public void deletePolicy(String pkg) {
db.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
}
@Override
public void deletePolicy(int uid) {
db.delete(POLICY_TABLE, Utils.fmt("uid=%d", uid), null);
}
@Override
public Policy getPolicy(int uid) {
Policy policy = null;
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid=%d", uid), null, null, null, null)) {
if (c.moveToNext()) {
ContentValues values = new ContentValues();
DatabaseUtils.cursorRowToContentValues(c, values);
policy = new Policy(values, pm);
}
} catch (PackageManager.NameNotFoundException e) {
deletePolicy(uid);
return null;
}
return policy;
}
@Override
public void updatePolicy(Policy policy) {
db.replace(POLICY_TABLE, null, policy.getContentValues());
}
@Override
public List<Policy> getPolicyList() {
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid/100000=%d", Const.USER_ID),
null, null, null, null)) {
List<Policy> ret = new ArrayList<>(c.getCount());
while (c.moveToNext()) {
try {
ContentValues values = new ContentValues();
DatabaseUtils.cursorRowToContentValues(c, values);
Policy policy = new Policy(values, pm);
ret.add(policy);
} catch (PackageManager.NameNotFoundException e) {
// The app no longer exist, remove from DB
deletePolicy(c.getInt(c.getColumnIndex("uid")));
}
}
Collections.sort(ret);
return ret;
}
}
@Override
public List<List<SuLogEntry>> getLogs() {
try (Cursor c = db.query(LOG_TABLE, null, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
null, null, null, "time DESC")) {
List<List<SuLogEntry>> ret = new ArrayList<>();
List<SuLogEntry> list = null;
String dateString = null, newString;
while (c.moveToNext()) {
Date date = new Date(c.getLong(c.getColumnIndex("time")));
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
if (!TextUtils.equals(dateString, newString)) {
dateString = newString;
list = new ArrayList<>();
ret.add(list);
}
ContentValues values = new ContentValues();
DatabaseUtils.cursorRowToContentValues(c, values);
list.add(new SuLogEntry(values));
}
return ret;
}
}
@Override
public void addLog(SuLogEntry log) {
db.insert(LOG_TABLE, null, log.getContentValues());
}
@Override
public void clearLogs() {
db.delete(LOG_TABLE, null, null);
}
@Override
public void setSettings(String key, int value) {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
db.replace(SETTINGS_TABLE, null, data);
}
@Override
public int getSettings(String key, int defaultValue) {
int value = defaultValue;
try (Cursor c = db.query(SETTINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
if (c.moveToNext()) {
value = c.getInt(c.getColumnIndex("value"));
}
}
return value;
}
@Override
public void setStrings(String key, String value) {
if (value == null) {
db.delete(STRINGS_TABLE, "key=?", new String[] { key });
} else {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
db.replace(STRINGS_TABLE, null, data);
}
}
@Override
public String getStrings(String key, String defaultValue) {
String value = defaultValue;
try (Cursor c = db.query(STRINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
if (c.moveToNext()) {
value = c.getString(c.getColumnIndex("value"));
}
}
return value;
}
}

View File

@ -271,8 +271,7 @@ public class MagiskFragment extends BaseFragment
if (Data.remoteMagiskVersionCode > Data.magiskVersionCode
|| Data.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
install();
} else if (Data.remoteMagiskVersionCode >= Const.MAGISK_VER.FIX_ENV &&
!ShellUtils.fastCmdResult("env_check")) {
} else if (!ShellUtils.fastCmdResult("env_check")) {
new EnvFixDialog(requireActivity()).show();
}
}

View File

@ -36,12 +36,11 @@ public class GeneralReceiver extends BroadcastReceiver {
case "request":
Intent i = new Intent(mm, Data.classMap.get(SuRequestActivity.class))
.putExtra("socket", intent.getStringExtra("socket"))
.putExtra("version", 2)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mm.startActivity(i);
break;
case "log":
SuConnector.handleLogs(intent, 2);
SuConnector.handleLogs(intent);
break;
case "notify":
SuConnector.handleNotify(intent);

View File

@ -1,21 +0,0 @@
package com.topjohnwu.magisk.superuser;
import android.content.Intent;
import android.os.Bundle;
import com.topjohnwu.magisk.Data;
import com.topjohnwu.magisk.SuRequestActivity;
import com.topjohnwu.magisk.components.BaseActivity;
public class RequestActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, Data.classMap.get(SuRequestActivity.class))
.putExtra("socket", getIntent().getStringExtra("socket"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
}

View File

@ -1,16 +0,0 @@
package com.topjohnwu.magisk.superuser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.topjohnwu.magisk.utils.SuConnector;
public class SuReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null)
SuConnector.handleLogs(intent, 1);
}
}

View File

@ -9,7 +9,6 @@ import androidx.annotation.Keep;
public class BootSigner {
@Keep
public static void main(String[] args) throws Exception {
if (args.length > 0 && "-verify".equals(args[0])) {
String certPath = "";

View File

@ -21,10 +21,6 @@ public class RootUtils extends Shell.Initializer {
BusyBox.BB_PATH = new File(Const.BUSYBOX_PATH);
}
public static void uninstallPkg(String pkg) {
Shell.su("db_clean " + Const.USER_ID, "pm uninstall " + pkg).exec();
}
public static void rmAndLaunch(String rm, String launch) {
Shell.su(Utils.fmt("(rm_launch %d %s %s)&", Const.USER_ID, rm, launch)).exec();
}
@ -33,9 +29,6 @@ public class RootUtils extends Shell.Initializer {
public boolean onInit(Context context, @NonNull Shell shell) {
Shell.Job job = shell.newJob();
if (shell.isRoot()) {
if (!new SuFile("/sbin/.magisk").exists())
job.add("ln -s /sbin/.core /sbin/.magisk");
job.add(context.getResources().openRawResource(R.raw.util_functions))
.add(context.getResources().openRawResource(R.raw.utils));
Const.MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk");

View File

@ -3,6 +3,7 @@ package com.topjohnwu.magisk.utils;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
@ -24,12 +25,13 @@ import java.util.Date;
public abstract class SuConnector {
protected LocalSocket socket = new LocalSocket();
private LocalSocket socket;
protected DataOutputStream out;
protected DataInputStream in;
public SuConnector(String name) throws IOException {
connect(name);
socket = new LocalSocket();
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
}
@ -66,11 +68,9 @@ public abstract class SuConnector {
} catch (IOException ignored) { }
}
public abstract void connect(String name) throws IOException;
protected abstract void onResponse() throws IOException;
public static void handleLogs(Intent intent, int version) {
public static void handleLogs(Intent intent) {
int fromUid = intent.getIntExtra("from.uid", -1);
if (fromUid < 0) return;
@ -97,24 +97,9 @@ public abstract class SuConnector {
notify = policy.notification;
}
if (version == 1) {
String action = intent.getStringExtra("action");
if (action == null) return;
switch (action) {
case "allow":
policy.policy = Policy.ALLOW;
break;
case "deny":
policy.policy = Policy.DENY;
break;
default:
return;
}
} else {
policy.policy = data.getInt("policy", -1);
if (policy.policy < 0)
return;
}
if (notify)
handleNotify(policy);

View File

@ -1,42 +1,3 @@
db_sepatch() {
magiskpolicy --live 'create magisk_file' 'attradd magisk_file mlstrustedobject' \
'allow * magisk_file file *' 'allow * magisk_file dir *' \
'allow magisk_file * filesystem associate'
}
db_clean() {
local USERID=$1
local DIR="/sbin/.magisk/db-${USERID}"
umount -l /data/user*/*/*/databases/su.db $DIR $DIR/*
rm -rf $DIR
[ "$USERID" = "*" ] && rm -fv /data/adb/magisk.db*
}
db_init() {
# Temporary let the folder rw by anyone
chcon u:object_r:magisk_file:s0 /data/adb
chmod 777 /data/adb
}
db_restore() {
chmod 700 /data/adb
magisk --restorecon
}
db_setup() {
local USER=$1
local USERID=$(($USER / 100000))
local DIR=/sbin/.magisk/db-${USERID}
mkdir -p $DIR
touch $DIR/magisk.db
mount -o bind /data/adb/magisk.db $DIR/magisk.db
rm -f /data/adb/magisk.db-*
chcon u:object_r:magisk_file:s0 $DIR $DIR/*
chmod 700 $DIR
chown $USER.$USER $DIR
chmod 666 $DIR/*
}
env_check() {
for file in busybox magisk magiskboot magiskinit util_functions.sh boot_patch.sh; do
[ -f /data/adb/magisk/$file ] || return 1