diff --git a/app/src/full/java/com/topjohnwu/magisk/container/SuLogEntry.java b/app/src/full/java/com/topjohnwu/magisk/container/SuLogEntry.java index b9410fc51..2638105f4 100644 --- a/app/src/full/java/com/topjohnwu/magisk/container/SuLogEntry.java +++ b/app/src/full/java/com/topjohnwu/magisk/container/SuLogEntry.java @@ -19,6 +19,7 @@ public class SuLogEntry { fromUid = policy.uid; packageName = policy.packageName; appName = policy.appName; + action = policy.policy == Policy.ALLOW; } public SuLogEntry(ContentValues values) { diff --git a/app/src/full/java/com/topjohnwu/magisk/receivers/BootReceiver.java b/app/src/full/java/com/topjohnwu/magisk/receivers/BootReceiver.java index 75bf33616..c5cc42ad8 100644 --- a/app/src/full/java/com/topjohnwu/magisk/receivers/BootReceiver.java +++ b/app/src/full/java/com/topjohnwu/magisk/receivers/BootReceiver.java @@ -14,8 +14,13 @@ public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + if (intent == null) + return; if (TextUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED)) { - switch (intent.getExtras().getString("action", "boot")) { + String action = intent.getStringExtra("action"); + if (action == null) + action = "boot"; + switch (action) { case "request": Intent i = new Intent(context, Data.classMap.get(SuRequestActivity.class)) .putExtra("socket", intent.getStringExtra("socket")) @@ -26,6 +31,9 @@ public class BootReceiver extends BroadcastReceiver { case "log": SuConnector.handleLogs(intent, 2); break; + case "notify": + SuConnector.handleNotify(intent); + break; case "boot": OnBootService.enqueueWork(context); break; diff --git a/app/src/full/java/com/topjohnwu/magisk/superuser/SuReceiver.java b/app/src/full/java/com/topjohnwu/magisk/superuser/SuReceiver.java index fe7198e68..e247c42ec 100644 --- a/app/src/full/java/com/topjohnwu/magisk/superuser/SuReceiver.java +++ b/app/src/full/java/com/topjohnwu/magisk/superuser/SuReceiver.java @@ -10,6 +10,7 @@ public class SuReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - SuConnector.handleLogs(intent, 1); + if (intent != null) + SuConnector.handleLogs(intent, 1); } } diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/SuConnector.java b/app/src/full/java/com/topjohnwu/magisk/utils/SuConnector.java index 408aa35cf..1d6d1129f 100644 --- a/app/src/full/java/com/topjohnwu/magisk/utils/SuConnector.java +++ b/app/src/full/java/com/topjohnwu/magisk/utils/SuConnector.java @@ -50,69 +50,87 @@ public abstract class SuConnector { public abstract void response(); public static void handleLogs(Intent intent, int version) { - MagiskManager mm = Data.MM(); - - if (intent == null) return; int fromUid = intent.getIntExtra("from.uid", -1); if (fromUid < 0) return; if (fromUid == Process.myUid()) return; - Policy policy = mm.mDB.getPolicy(fromUid); - if (policy == null) { + MagiskManager mm = Data.MM(); + PackageManager pm = mm.getPackageManager(); + Policy policy; + + boolean notify; + Bundle data = intent.getExtras(); + if (data.containsKey("notify")) { + notify = data.getBoolean("notify"); try { - policy = new Policy(fromUid, mm.getPackageManager()); + policy = new Policy(fromUid, pm); } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); return; } + } else { + // Doesn't report whether notify or not, check database ourselves + policy = mm.mDB.getPolicy(fromUid); + if (policy == null) + return; + notify = policy.notification; } - SuLogEntry log = new SuLogEntry(policy); if (version == 1) { String action = intent.getStringExtra("action"); if (action == null) return; switch (action) { case "allow": - log.action = true; + policy.policy = Policy.ALLOW; break; case "deny": - log.action = false; + policy.policy = Policy.DENY; break; default: return; } } else { - switch (intent.getIntExtra("policy", -1)) { - case Policy.ALLOW: - log.action = true; - break; - case Policy.DENY: - log.action = false; - break; - default: - return; - } + policy.policy = data.getInt("policy", -1); + if (policy.policy < 0) + return; } - String message = mm.getString(log.action ? - R.string.su_allow_toast : R.string.su_deny_toast, policy.appName); + if (notify) + handleNotify(policy); + SuLogEntry log = new SuLogEntry(policy); + + int toUid = intent.getIntExtra("to.uid", -1); + if (toUid < 0) return; + int pid = intent.getIntExtra("pid", -1); + if (pid < 0) return; + String command = intent.getStringExtra("command"); + if (command == null) return; + log.toUid = toUid; + log.fromPid = pid; + log.command = command; + log.date = new Date(); + mm.mDB.addLog(log); + } + + private static void handleNotify(Policy policy) { + MagiskManager mm = Data.MM(); + String message = mm.getString(policy.policy == Policy.ALLOW ? + R.string.su_allow_toast : R.string.su_deny_toast, policy.appName); if (policy.notification && Data.suNotificationType == Const.Value.NOTIFICATION_TOAST) Utils.toast(message, Toast.LENGTH_SHORT); + } - if (policy.logging) { - int toUid = intent.getIntExtra("to.uid", -1); - if (toUid < 0) return; - int pid = intent.getIntExtra("pid", -1); - if (pid < 0) return; - String command = intent.getStringExtra("command"); - if (command == null) return; - log.toUid = toUid; - log.fromPid = pid; - log.command = command; - log.date = new Date(); - mm.mDB.addLog(log); - } + public static void handleNotify(Intent intent) { + MagiskManager mm = Data.MM(); + int fromUid = intent.getIntExtra("from.uid", -1); + if (fromUid < 0) return; + if (fromUid == Process.myUid()) return; + try { + Policy policy = new Policy(fromUid, mm.getPackageManager()); + policy.policy = intent.getIntExtra("policy", -1); + if (policy.policy >= 0) + handleNotify(policy); + } catch (PackageManager.NameNotFoundException ignored) {} } } diff --git a/native/jni/daemon/db.c b/native/jni/daemon/db.c index 28be6cb6f..5d6309c7f 100644 --- a/native/jni/daemon/db.c +++ b/native/jni/daemon/db.c @@ -15,32 +15,31 @@ static int ver_cb(void *v, int col_num, char **data, char **col_name) { sqlite3 *get_magiskdb() { sqlite3 *db; - char *err; int ret = sqlite3_open(MAGISKDB, &db); if (ret) { LOGE("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); return NULL; } int ver, upgrade = 0; - sqlite3_exec(db, "PRAGMA user_version", ver_cb, &ver, &err); + sqlite3_exec(db, "PRAGMA user_version", ver_cb, &ver, NULL); if (ver < 3) { // Policies sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS policies " "(uid INT, package_name TEXT, policy INT, until INT, " "logging INT, notification INT, PRIMARY KEY(uid))", - NULL, NULL, &err); + NULL, NULL, NULL); // Logs sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS logs " "(from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " "to_uid INT, action INT, time INT, command TEXT)", - NULL, NULL, &err); + NULL, NULL, NULL); // Settings sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS settings " "(key TEXT, value INT, PRIMARY KEY(key))", - NULL, NULL, &err); + NULL, NULL, NULL); ver = 3; upgrade = 1; } @@ -49,12 +48,12 @@ sqlite3 *get_magiskdb() { sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS strings " "(key TEXT, value TEXT, PRIMARY KEY(key))", - NULL, NULL, &err); + NULL, NULL, NULL); ver = 4; upgrade = 1; } if (ver == 4) { - sqlite3_exec(db, "UPDATE policies SET uid=uid%100000", NULL, NULL, &err); + sqlite3_exec(db, "UPDATE policies SET uid=uid%100000", NULL, NULL, NULL); /* Skip version 5 */ ver = 6; upgrade = 1; @@ -64,7 +63,7 @@ sqlite3 *get_magiskdb() { // Set version char query[32]; sprintf(query, "PRAGMA user_version=%d", ver); - sqlite3_exec(db, query, NULL, NULL, &err); + sqlite3_exec(db, query, NULL, NULL, NULL); } return db; } @@ -102,6 +101,7 @@ int get_db_settings(sqlite3 *db, int key, struct db_settings *dbs) { } if (err) { LOGE("sqlite3_exec: %s\n", err); + sqlite3_free(err); return 1; } return 0; @@ -141,6 +141,7 @@ int get_db_strings(sqlite3 *db, int key, struct db_strings *str) { } if (err) { LOGE("sqlite3_exec: %s\n", err); + sqlite3_free(err); return 1; } return 0; @@ -169,6 +170,7 @@ int get_uid_policy(sqlite3 *db, int uid, struct su_access *su) { sqlite3_exec(db, query, policy_cb, su, &err); if (err) { LOGE("sqlite3_exec: %s\n", err); + sqlite3_free(err); return 1; } return 0; diff --git a/native/jni/su/connect.c b/native/jni/su/connect.c index 098b34700..fb89c7db4 100644 --- a/native/jni/su/connect.c +++ b/native/jni/su/connect.c @@ -82,11 +82,37 @@ void app_log(struct su_context *ctx) { "--ei", "pid", pid, "--ei", "policy", policy, "--es", "command", get_command(&ctx->req), + "--ez", "notify", ctx->info->access.notify ? "true" : "false", NULL }; silent_run(cmd); } +void app_notify(struct su_context *ctx) { + char user[8]; + setup_user(user, ctx->info); + + char fromUid[8]; + sprintf(fromUid, "%d", + DB_SET(ctx->info, SU_MULTIUSER_MODE) == MULTIUSER_MODE_OWNER_MANAGED ? + ctx->info->uid % 100000 : ctx->info->uid); + + char policy[2]; + sprintf(policy, "%d", ctx->info->access.policy); + + char *cmd[] = { + AM_PATH, "broadcast", + "-a", "android.intent.action.BOOT_COMPLETED", + "-p", DB_STR(ctx->info, SU_MANAGER), + "--user", user, + "--es", "action", "notify", + "--ei", "from.uid", fromUid, + "--ei", "policy", policy, + NULL + }; + silent_run(cmd); +} + void app_connect(const char *socket, struct su_info *info) { char user[8]; setup_user(user, info); diff --git a/native/jni/su/su.h b/native/jni/su/su.h index e3a925193..6244803ac 100644 --- a/native/jni/su/su.h +++ b/native/jni/su/su.h @@ -54,6 +54,7 @@ struct su_context { // connect.c void app_log(struct su_context *ctx); +void app_notify(struct su_context *ctx); void app_connect(const char *socket, struct su_info *info); void socket_send_request(int fd, struct su_info *info); diff --git a/native/jni/su/su_daemon.c b/native/jni/su/su_daemon.c index 5093f7763..b37bba858 100644 --- a/native/jni/su/su_daemon.c +++ b/native/jni/su/su_daemon.c @@ -361,8 +361,10 @@ void su_daemon_handler(int client, struct ucred *credential) { break; } - if (info->access.notify || info->access.log) + if (info->access.log) app_log(&ctx); + else if (info->access.notify) + app_notify(&ctx); if (info->access.policy == ALLOW) { char* argv[] = { NULL, NULL, NULL, NULL };