diff --git a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.java b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.java deleted file mode 100644 index 0a7432c4d..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.topjohnwu.magisk.model.receiver; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import com.topjohnwu.magisk.App; -import com.topjohnwu.magisk.ClassMap; -import com.topjohnwu.magisk.Config; -import com.topjohnwu.magisk.Const; -import com.topjohnwu.magisk.ui.surequest.SuRequestActivity; -import com.topjohnwu.magisk.utils.DownloadApp; -import com.topjohnwu.magisk.utils.SuLogger; -import com.topjohnwu.magisk.view.Notifications; -import com.topjohnwu.magisk.view.Shortcuts; -import com.topjohnwu.superuser.Shell; - -public class GeneralReceiver extends BroadcastReceiver { - - private String getPkg(Intent i) { - return i.getData() == null ? "" : i.getData().getEncodedSchemeSpecificPart(); - } - - @Override - public void onReceive(Context context, Intent intent) { - App app = App.self; - if (intent == null) - return; - String action = intent.getAction(); - if (action == null) - return; - switch (action) { - case Intent.ACTION_REBOOT: - case Intent.ACTION_BOOT_COMPLETED: - action = intent.getStringExtra("action"); - if (action == null) { - // Actual boot completed event - Shell.su("mm_patch_dtbo").submit(result -> { - if (result.isSuccess()) - Notifications.dtboPatched(); - }); - break; - } - switch (action) { - case SuRequestActivity.REQUEST: - Intent i = new Intent(app, ClassMap.get(SuRequestActivity.class)) - .setAction(action) - .putExtra("socket", intent.getStringExtra("socket")) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - app.startActivity(i); - break; - case SuRequestActivity.LOG: - SuLogger.handleLogs(intent); - break; - case SuRequestActivity.NOTIFY: - SuLogger.handleNotify(intent); - break; - } - break; - case Intent.ACTION_PACKAGE_REPLACED: - // This will only work pre-O - if (Config.get(Config.Key.SU_REAUTH)) { - app.getDB().deletePolicy(getPkg(intent)); - } - break; - case Intent.ACTION_PACKAGE_FULLY_REMOVED: - String pkg = getPkg(intent); - app.getDB().deletePolicy(pkg); - Shell.su("magiskhide --rm " + pkg).submit(); - break; - case Intent.ACTION_LOCALE_CHANGED: - Shortcuts.setup(context); - break; - case Const.Key.BROADCAST_MANAGER_UPDATE: - Config.managerLink = intent.getStringExtra(Const.Key.INTENT_SET_LINK); - DownloadApp.upgrade(intent.getStringExtra(Const.Key.INTENT_SET_NAME)); - break; - case Const.Key.BROADCAST_REBOOT: - Shell.su("/system/bin/reboot").submit(); - break; - } - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt new file mode 100644 index 000000000..8024d39e0 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt @@ -0,0 +1,80 @@ +package com.topjohnwu.magisk.model.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.topjohnwu.magisk.ClassMap +import com.topjohnwu.magisk.Config +import com.topjohnwu.magisk.Const +import com.topjohnwu.magisk.data.database.MagiskDB +import com.topjohnwu.magisk.ui.surequest.SuRequestActivity +import com.topjohnwu.magisk.utils.DownloadApp +import com.topjohnwu.magisk.utils.RootUtils +import com.topjohnwu.magisk.utils.SuLogger +import com.topjohnwu.magisk.utils.get +import com.topjohnwu.magisk.view.Notifications +import com.topjohnwu.magisk.view.Shortcuts +import com.topjohnwu.superuser.Shell + +open class GeneralReceiver : BroadcastReceiver() { + + companion object { + const val REQUEST = "request" + const val LOG = "log" + const val NOTIFY = "notify" + const val TEST = "test" + } + + private fun getPkg(intent: Intent): String { + return intent.data?.encodedSchemeSpecificPart ?: "" + } + + override fun onReceive(context: Context, intent: Intent?) { + if (intent == null) + return + val mDB: MagiskDB = get() + var action: String? = intent.action ?: return + when (action) { + Intent.ACTION_REBOOT, Intent.ACTION_BOOT_COMPLETED -> { + action = intent.getStringExtra("action") + if (action == null) { + // Actual boot completed event + Shell.su("mm_patch_dtbo").submit { result -> + if (result.isSuccess) + Notifications.dtboPatched() + } + return + } + when (action) { + REQUEST -> { + val i = Intent(context, ClassMap.get(SuRequestActivity::class.java)) + .setAction(action) + .putExtra("socket", intent.getStringExtra("socket")) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) + context.startActivity(i) + } + LOG -> SuLogger.handleLogs(intent) + NOTIFY -> SuLogger.handleNotify(intent) + TEST -> Shell.su("magisk --use-broadcast").submit() + } + } + Intent.ACTION_PACKAGE_REPLACED -> + // This will only work pre-O + if (Config.get(Config.Key.SU_REAUTH)!!) { + mDB.deletePolicy(getPkg(intent)) + } + Intent.ACTION_PACKAGE_FULLY_REMOVED -> { + val pkg = getPkg(intent) + mDB.deletePolicy(pkg) + Shell.su("magiskhide --rm $pkg").submit() + } + Intent.ACTION_LOCALE_CHANGED -> Shortcuts.setup(context) + Const.Key.BROADCAST_MANAGER_UPDATE -> { + Config.managerLink = intent.getStringExtra(Const.Key.INTENT_SET_LINK) + DownloadApp.upgrade(intent.getStringExtra(Const.Key.INTENT_SET_NAME)) + } + Const.Key.BROADCAST_REBOOT -> RootUtils.reboot() + } + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt index 9ad1b2f62..dddf4d75a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt @@ -10,6 +10,7 @@ import com.topjohnwu.magisk.R import com.topjohnwu.magisk.databinding.ActivityRequestBinding import com.topjohnwu.magisk.model.entity.Policy import com.topjohnwu.magisk.model.events.DieEvent +import com.topjohnwu.magisk.model.receiver.GeneralReceiver import com.topjohnwu.magisk.ui.base.MagiskActivity import com.topjohnwu.magisk.utils.SuLogger import org.koin.androidx.viewmodel.ext.android.viewModel @@ -31,15 +32,15 @@ open class SuRequestActivity : MagiskActivity%li)", uid, time(nullptr)); diff --git a/native/jni/core/magisk.cpp b/native/jni/core/magisk.cpp index 3468728cd..b14300f9f 100644 --- a/native/jni/core/magisk.cpp +++ b/native/jni/core/magisk.cpp @@ -12,6 +12,8 @@ #include #include +using namespace std::literals; + [[noreturn]] static void usage() { fprintf(stderr, FULL_VER(Magisk) " multi-call binary\n" @@ -33,6 +35,7 @@ " --clone-attr SRC DEST clone permission, owner, and selinux context\n" " --clone SRC DEST clone SRC to DEST\n" " --sqlite SQL exec SQL to Magisk database\n" + " --use-broadcast use broadcast for su logging and notify\n" "\n" "Supported init triggers:\n" " post-fs-data, service, boot-complete\n" @@ -48,66 +51,70 @@ int magisk_main(int argc, char *argv[]) { if (argc < 2) usage(); - if (strcmp(argv[1], "-c") == 0) { + if (argv[1] == "-c"sv) { printf(MAGISK_VERSION ":MAGISK (" str(MAGISK_VER_CODE) ")\n"); return 0; - } else if (strcmp(argv[1], "-v") == 0) { + } else if (argv[1] == "-v"sv) { int fd = connect_daemon(); write_int(fd, CHECK_VERSION); char *v = read_string(fd); printf("%s\n", v); free(v); return 0; - } else if (strcmp(argv[1], "-V") == 0) { + } else if (argv[1] == "-V"sv) { int fd = connect_daemon(); write_int(fd, CHECK_VERSION_CODE); printf("%d\n", read_int(fd)); return 0; - } else if (strcmp(argv[1], "--list") == 0) { + } else if (argv[1] == "--list"sv) { for (int i = 0; applet_names[i]; ++i) printf("%s\n", applet_names[i]); return 0; - } else if (strcmp(argv[1], "--unlock-blocks") == 0) { + } else if (argv[1] == "--unlock-blocks"sv) { unlock_blocks(); return 0; - } else if (strcmp(argv[1], "--restorecon") == 0) { + } else if (argv[1] == "--restorecon"sv) { restore_rootcon(); restorecon(); return 0; - } else if (strcmp(argv[1], "--clone-attr") == 0) { + } else if (argv[1] == "--clone-attr"sv) { if (argc < 4) usage(); clone_attr(argv[2], argv[3]); return 0; - } else if (strcmp(argv[1], "--clone") == 0) { + } else if (argv[1] == "--clone"sv) { if (argc < 4) usage(); cp_afc(argv[2], argv[3]); return 0; - } else if (strcmp(argv[1], "--daemon") == 0) { + } else if (argv[1] == "--daemon"sv) { int fd = connect_daemon(true); write_int(fd, DO_NOTHING); return 0; - } else if (strcmp(argv[1], "--post-fs-data") == 0) { + } else if (argv[1] == "--post-fs-data"sv) { int fd = connect_daemon(true); write_int(fd, POST_FS_DATA); return read_int(fd); - } else if (strcmp(argv[1], "--service") == 0) { + } else if (argv[1] == "--service"sv) { int fd = connect_daemon(true); write_int(fd, LATE_START); return read_int(fd); - } else if (strcmp(argv[1], "--boot-complete") == 0) { + } else if (argv[1] == "--boot-complete"sv) { int fd = connect_daemon(true); write_int(fd, BOOT_COMPLETE); return read_int(fd); - } else if (strcmp(argv[1], "--sqlite") == 0) { + } else if (argv[1] == "--sqlite"sv) { int fd = connect_daemon(); write_int(fd, SQLITE_CMD); write_string(fd, argv[2]); send_fd(fd, STDOUT_FILENO); return read_int(fd); + } else if (argv[1] == "--use-broadcast"sv) { + int fd = connect_daemon(); + write_int(fd, BROADCAST_ACK); + return 0; } #if 0 /* Entry point for testing stuffs */ - else if (strcmp(argv[1], "--test") == 0) { + else if (argv[1] == "--test"sv) { return 0; } #endif diff --git a/native/jni/include/daemon.h b/native/jni/include/daemon.h index 41baeb9c8..bfc45041c 100644 --- a/native/jni/include/daemon.h +++ b/native/jni/include/daemon.h @@ -17,7 +17,7 @@ enum { BOOT_COMPLETE, MAGISKHIDE, SQLITE_CMD, - ZYGOTE_NOTIFY, + BROADCAST_ACK, }; // Return codes for daemon @@ -82,6 +82,8 @@ void magiskhide_handler(int client); *************/ void su_daemon_handler(int client, struct ucred *credential); +void broadcast_test(); extern int SDK_INT; extern bool RECOVERY_MODE; +extern bool CONNECT_BROADCAST; diff --git a/native/jni/include/db.h b/native/jni/include/db.h index 50f8605ca..7b5726e0a 100644 --- a/native/jni/include/db.h +++ b/native/jni/include/db.h @@ -154,7 +154,7 @@ typedef std::function db_row_cb; int get_db_settings(db_settings &cfg, int key = -1); int get_db_strings(db_strings &str, int key = -1); -int get_uid_policy(int uid, su_access &su); +int get_uid_policy(su_access &su, int uid); int validate_manager(std::string &alt_pkg, int userid, struct stat *st); void exec_sql(int client); char *db_exec(const char *sql); diff --git a/native/jni/su/connect.cpp b/native/jni/su/connect.cpp index f68997f18..4cf8720f1 100644 --- a/native/jni/su/connect.cpp +++ b/native/jni/su/connect.cpp @@ -11,12 +11,21 @@ #include "su.h" +bool CONNECT_BROADCAST; + #define START_ACTIVITY \ "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am", \ "start", "-n", nullptr, "--user", nullptr, "-f", "0x18000020", "-a" // 0x18000020 = FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_MULTIPLE_TASK|FLAG_INCLUDE_STOPPED_PACKAGES +#define START_BROADCAST \ +"/system/bin/app_process", "/system/bin", "com.android.commands.am.Am", \ +"broadcast", "-n", nullptr, "--user", nullptr, "-f", "0x00000020", \ +"-a", "android.intent.action.REBOOT", "--es", "action" + +// 0x00000020 = FLAG_INCLUDE_STOPPED_PACKAGES + static inline const char *get_command(const su_request *to) { if (to->command[0]) return to->command; @@ -39,9 +48,9 @@ static inline void get_uid(char *uid, su_info *info) { : info->uid); } -static void silent_run(const char **args, su_info *info) { +static void exec_am_cmd(const char **args, su_info *info) { char component[128]; - sprintf(component, "%s/a.m", info->str[SU_MANAGER].data()); + sprintf(component, "%s/%s", info->str[SU_MANAGER].data(), args[3][0] == 'b' ? "a.h" : "a.m"); char user[8]; get_user(user, info); @@ -62,6 +71,16 @@ static void silent_run(const char **args, su_info *info) { exec_command(exec); } +#define LOG_BODY \ +"log", \ +"--ei", "from.uid", fromUid, \ +"--ei", "to.uid", toUid, \ +"--ei", "pid", pid, \ +"--ei", "policy", policy, \ +"--es", "command", get_command(&ctx->req), \ +"--ez", "notify", ctx->info->access.notify ? "true" : "false", \ +nullptr + void app_log(su_context *ctx) { char fromUid[8]; get_uid(fromUid, ctx->info); @@ -75,19 +94,21 @@ void app_log(su_context *ctx) { char policy[2]; sprintf(policy, "%d", ctx->info->access.policy); - const char *cmd[] = { - START_ACTIVITY, "log", - "--ei", "from.uid", fromUid, - "--ei", "to.uid", toUid, - "--ei", "pid", pid, - "--ei", "policy", policy, - "--es", "command", get_command(&ctx->req), - "--ez", "notify", ctx->info->access.notify ? "true" : "false", - nullptr - }; - silent_run(cmd, ctx->info); + if (CONNECT_BROADCAST) { + const char *cmd[] = { START_BROADCAST, LOG_BODY }; + exec_am_cmd(cmd, ctx->info); + } else { + const char *cmd[] = { START_ACTIVITY, LOG_BODY }; + exec_am_cmd(cmd, ctx->info); + } } +#define NOTIFY_BODY \ +"notify", \ +"--ei", "from.uid", fromUid, \ +"--ei", "policy", policy, \ +nullptr + void app_notify(su_context *ctx) { char fromUid[8]; get_uid(fromUid, ctx->info); @@ -95,13 +116,14 @@ void app_notify(su_context *ctx) { char policy[2]; sprintf(policy, "%d", ctx->info->access.policy); - const char *cmd[] = { - START_ACTIVITY, "notify", - "--ei", "from.uid", fromUid, - "--ei", "policy", policy, - nullptr - }; - silent_run(cmd, ctx->info); + if (CONNECT_BROADCAST) { + const char *cmd[] = { START_BROADCAST, NOTIFY_BODY }; + exec_am_cmd(cmd, ctx->info); + } else { + const char *cmd[] = { START_ACTIVITY, NOTIFY_BODY }; + exec_am_cmd(cmd, ctx->info); + } + } void app_connect(const char *socket, su_info *info) { @@ -110,7 +132,17 @@ void app_connect(const char *socket, su_info *info) { "--es", "socket", socket, nullptr }; - silent_run(cmd, info); + exec_am_cmd(cmd, info); +} + +void broadcast_test() { + su_info info; + get_db_settings(info.cfg); + get_db_strings(info.str); + validate_manager(info.str[SU_MANAGER], 0, &info.mgr_st); + + const char *cmd[] = { START_BROADCAST, "test", nullptr }; + exec_am_cmd(cmd, &info); } void socket_send_request(int fd, su_info *info) { diff --git a/native/jni/su/su.h b/native/jni/su/su.h index 4d7822c02..33672da7e 100644 --- a/native/jni/su/su.h +++ b/native/jni/su/su.h @@ -32,7 +32,7 @@ public: int ref; time_t timestamp; - su_info(unsigned uid); + su_info(unsigned uid = 0); ~su_info(); void lock(); void unlock(); diff --git a/native/jni/su/su_daemon.cpp b/native/jni/su/su_daemon.cpp index 3d69bddda..d9f022e4d 100644 --- a/native/jni/su/su_daemon.cpp +++ b/native/jni/su/su_daemon.cpp @@ -83,7 +83,7 @@ static void database_check(su_info *info) { } if (uid > 0) - get_uid_policy(uid, info->access); + get_uid_policy(info->access, uid); // We need to check our manager if (info->access.log || info->access.notify)