mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-01 15:44:02 +00:00
Try to use broadcast for su logging and notify
In commit 8d4c407, native Magisk always launches an activity for
communicating with Magisk Manager. While this works extremely well,
since it also workaround stupid OEMs that blocks broadcasts, it has a
problem: launching an activity will claim the focus of the device,
which could be super annoying in some circumstances.
This commit adds a new feature to run a broadcast test on boot complete.
If Magisk Manager successfully receives the broadcast, it will toggle
a setting in magiskd so all future su loggings and notifies will always
use broadcasts instead of launching activities.
Fix #1412
This commit is contained in:
@@ -732,4 +732,7 @@ void boot_complete(int client) {
|
||||
install_apk("/data/magisk.apk");
|
||||
}
|
||||
}
|
||||
|
||||
// Test whether broadcast can be used or not
|
||||
broadcast_test();
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ static void *request_handler(void *args) {
|
||||
case LATE_START:
|
||||
case BOOT_COMPLETE:
|
||||
case SQLITE_CMD:
|
||||
case BROADCAST_ACK:
|
||||
if (credential.uid != 0) {
|
||||
write_int(client, ROOT_REQUIRED);
|
||||
close(client);
|
||||
@@ -90,6 +91,10 @@ static void *request_handler(void *args) {
|
||||
case SQLITE_CMD:
|
||||
exec_sql(client);
|
||||
break;
|
||||
case BROADCAST_ACK:
|
||||
LOGD("* Use broadcasts for su logging and notify\n");
|
||||
CONNECT_BROADCAST = true;
|
||||
close(client);
|
||||
default:
|
||||
close(client);
|
||||
break;
|
||||
|
||||
@@ -233,7 +233,7 @@ int get_db_strings(db_strings &str, int key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_uid_policy(int uid, su_access &su) {
|
||||
int get_uid_policy(su_access &su, int uid) {
|
||||
char query[256], *err;
|
||||
sprintf(query, "SELECT policy, logging, notification FROM policies "
|
||||
"WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr));
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <db.h>
|
||||
#include <flags.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -154,7 +154,7 @@ typedef std::function<bool(db_row&)> 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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user