Skip to content

Commit

Permalink
C++/Rust 2 way binding for MagiskD
Browse files Browse the repository at this point in the history
  • Loading branch information
topjohnwu committed Nov 17, 2023
1 parent 6c0966b commit 8d5b9e5
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 176 deletions.
6 changes: 6 additions & 0 deletions native/src/base/misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,9 @@ void exec_command_async(Args &&...args) {
};
exec_command(exec);
}

template <typename T>
constexpr auto operator+(T e) noexcept ->
std::enable_if_t<std::is_enum<T>::value, std::underlying_type_t<T>> {
return static_cast<std::underlying_type_t<T>>(e);
}
78 changes: 4 additions & 74 deletions native/src/core/bootstages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,6 @@

using namespace std;

// Boot stage state
enum : int {
FLAG_NONE = 0,
FLAG_POST_FS_DATA_DONE = (1 << 0),
FLAG_LATE_START_DONE = (1 << 1),
FLAG_BOOT_COMPLETE = (1 << 2),
FLAG_SAFE_MODE = (1 << 3),
};

static int boot_state = FLAG_NONE;

bool zygisk_enabled = false;

/*********
Expand Down Expand Up @@ -243,31 +232,6 @@ static bool magisk_env() {
return true;
}

static bool check_data() {
bool mnt = false;
file_readline("/proc/mounts", [&](string_view s) {
if (str_contains(s, " /data ") && !str_contains(s, "tmpfs")) {
mnt = true;
return false;
}
return true;
});
if (!mnt)
return false;
auto crypto = get_prop("ro.crypto.state");
if (!crypto.empty()) {
if (crypto != "encrypted") {
// Unencrypted, we can directly access data
return true;
} else {
// Encrypted, check whether vold is started
return !get_prop("init.svc.vold").empty();
}
}
// ro.crypto.state is not set, assume it's unencrypted
return true;
}

void unlock_blocks() {
int fd, dev, OFF = 0;

Expand Down Expand Up @@ -341,10 +305,7 @@ static bool check_key_combo() {
extern int disable_deny();

void MagiskD::post_fs_data() const {
if (!check_data())
return;

setup_logfile();
as_rust().setup_logfile();

LOGI("** post-fs-data mode running\n");

Expand All @@ -364,7 +325,7 @@ void MagiskD::post_fs_data() const {

if (get_prop("persist.sys.safemode", true) == "1" ||
get_prop("ro.sys.safemode") == "1" || check_key_combo()) {
boot_state |= FLAG_SAFE_MODE;
as_rust().enable_safe_mode();
// Disable all modules and denylist so next boot will be clean
disable_modules();
disable_deny();
Expand All @@ -380,23 +341,19 @@ void MagiskD::post_fs_data() const {
early_abort:
// We still do magic mount because root itself might need it
load_modules();
boot_state |= FLAG_POST_FS_DATA_DONE;
}

void MagiskD::late_start() const {
setup_logfile();
as_rust().setup_logfile();

LOGI("** late_start service mode running\n");

exec_common_scripts("service");
exec_module_scripts("service");

boot_state |= FLAG_LATE_START_DONE;
}

void MagiskD::boot_complete() const {
boot_state |= FLAG_BOOT_COMPLETE;
setup_logfile();
as_rust().setup_logfile();

LOGI("** boot-complete triggered\n");

Expand All @@ -410,30 +367,3 @@ void MagiskD::boot_complete() const {

reset_zygisk(true);
}

void boot_stage_handler(int client, int code) {
// Make sure boot stage execution is always serialized
static pthread_mutex_t stage_lock = PTHREAD_MUTEX_INITIALIZER;
mutex_guard lock(stage_lock);
MagiskD daemon;

switch (code) {
case MainRequest::POST_FS_DATA:
if ((boot_state & FLAG_POST_FS_DATA_DONE) == 0)
daemon.post_fs_data();
close(client);
break;
case MainRequest::LATE_START:
close(client);
if ((boot_state & FLAG_POST_FS_DATA_DONE) && (boot_state & FLAG_SAFE_MODE) == 0)
daemon.late_start();
break;
case MainRequest::BOOT_COMPLETE:
close(client);
if ((boot_state & FLAG_SAFE_MODE) == 0)
daemon.boot_complete();
break;
default:
__builtin_unreachable();
}
}
91 changes: 52 additions & 39 deletions native/src/core/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,43 +128,54 @@ static void poll_ctrl_handler(pollfd *pfd) {
}
}

const MagiskD &MagiskD::get() {
return *reinterpret_cast<const MagiskD*>(&rust::get_magiskd());
}

const rust::MagiskD &MagiskD::as_rust() const {
return *reinterpret_cast<const rust::MagiskD*>(this);
}

void MagiskD::boot_stage_handler(int client, int code) const {
as_rust().boot_stage_handler(client, code);
}

void MagiskD::reboot() const {
if (is_recovery())
if (as_rust().is_recovery())
exec_command_sync("/system/bin/reboot", "recovery");
else
exec_command_sync("/system/bin/reboot");
}

static void handle_request_async(int client, int code, const sock_cred &cred) {
switch (code) {
case MainRequest::DENYLIST:
case +RequestCode::DENYLIST:
denylist_handler(client, &cred);
break;
case MainRequest::SUPERUSER:
case +RequestCode::SUPERUSER:
su_daemon_handler(client, &cred);
break;
case MainRequest::ZYGOTE_RESTART:
case +RequestCode::ZYGOTE_RESTART:
LOGI("** zygote restarted\n");
pkg_xml_ino = 0;
prune_su_access();
reset_zygisk(false);
close(client);
break;
case MainRequest::SQLITE_CMD:
case +RequestCode::SQLITE_CMD:
exec_sql(client);
break;
case MainRequest::REMOVE_MODULES: {
case +RequestCode::REMOVE_MODULES: {
int do_reboot = read_int(client);
remove_modules();
write_int(client, 0);
close(client);
if (do_reboot) {
MagiskD daemon;
daemon.reboot();
MagiskD::get().reboot();
}
break;
}
case MainRequest::ZYGISK:
case +RequestCode::ZYGISK:
zygisk_handler(client, &cred);
break;
default:
Expand All @@ -174,20 +185,20 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {

static void handle_request_sync(int client, int code) {
switch (code) {
case MainRequest::CHECK_VERSION:
case +RequestCode::CHECK_VERSION:
#if MAGISK_DEBUG
write_string(client, MAGISK_VERSION ":MAGISK:D");
#else
write_string(client, MAGISK_VERSION ":MAGISK:R");
#endif
break;
case MainRequest::CHECK_VERSION_CODE:
case +RequestCode::CHECK_VERSION_CODE:
write_int(client, MAGISK_VER_CODE);
break;
case MainRequest::START_DAEMON:
case +RequestCode::START_DAEMON:
rust::get_magiskd().setup_logfile();
break;
case MainRequest::STOP_DAEMON: {
case +RequestCode::STOP_DAEMON: {
// Unmount all overlays
denylist_handler(-1, nullptr);

Expand Down Expand Up @@ -236,57 +247,59 @@ static void handle_request(pollfd *pfd) {

if (!is_root && !is_zygote && !is_client(cred.pid)) {
// Unsupported client state
write_int(client, MainResponse::ACCESS_DENIED);
write_int(client, +RespondCode::ACCESS_DENIED);
return;
}

code = read_int(client);
if (code < 0 || code >= MainRequest::END ||
code == MainRequest::_SYNC_BARRIER_ ||
code == MainRequest::_STAGE_BARRIER_) {
if (code < 0 || code >= +RequestCode::END ||
code == +RequestCode::_SYNC_BARRIER_ ||
code == +RequestCode::_STAGE_BARRIER_) {
// Unknown request code
return;
}

// Check client permissions
switch (code) {
case MainRequest::POST_FS_DATA:
case MainRequest::LATE_START:
case MainRequest::BOOT_COMPLETE:
case MainRequest::ZYGOTE_RESTART:
case MainRequest::SQLITE_CMD:
case MainRequest::DENYLIST:
case MainRequest::STOP_DAEMON:
case +RequestCode::POST_FS_DATA:
case +RequestCode::LATE_START:
case +RequestCode::BOOT_COMPLETE:
case +RequestCode::ZYGOTE_RESTART:
case +RequestCode::SQLITE_CMD:
case +RequestCode::DENYLIST:
case +RequestCode::STOP_DAEMON:
if (!is_root) {
write_int(client, MainResponse::ROOT_REQUIRED);
write_int(client, +RespondCode::ROOT_REQUIRED);
return;
}
break;
case MainRequest::REMOVE_MODULES:
case +RequestCode::REMOVE_MODULES:
if (!is_root && cred.uid != AID_SHELL) {
write_int(client, MainResponse::ACCESS_DENIED);
write_int(client, +RespondCode::ACCESS_DENIED);
return;
}
break;
case MainRequest::ZYGISK:
case +RequestCode::ZYGISK:
if (!is_zygote) {
// Invalid client context
write_int(client, MainResponse::ACCESS_DENIED);
write_int(client, +RespondCode::ACCESS_DENIED);
return;
}
break;
default:
break;
}

write_int(client, MainResponse::OK);
write_int(client, +RespondCode::OK);

if (code < MainRequest::_SYNC_BARRIER_) {
if (code < +RequestCode::_SYNC_BARRIER_) {
handle_request_sync(client, code);
} else if (code < MainRequest::_STAGE_BARRIER_) {
} else if (code < +RequestCode::_STAGE_BARRIER_) {
exec_task([=, fd = client.release()] { handle_request_async(fd, code, cred); });
} else {
exec_task([=, fd = client.release()] { boot_stage_handler(fd, code); });
exec_task([=, fd = client.release()] {
MagiskD::get().boot_stage_handler(fd, code);
});
}
}

Expand Down Expand Up @@ -460,20 +473,20 @@ int connect_daemon(int req, bool create) {
}
write_int(fd, req);
int res = read_int(fd);
if (res < MainResponse::ERROR || res >= MainResponse::END)
res = MainResponse::ERROR;
if (res < +RespondCode::ERROR || res >= +RespondCode::END)
res = +RespondCode::ERROR;
switch (res) {
case MainResponse::OK:
case +RespondCode::OK:
break;
case MainResponse::ERROR:
case +RespondCode::ERROR:
LOGE("Daemon error\n");
close(fd);
return -1;
case MainResponse::ROOT_REQUIRED:
case +RespondCode::ROOT_REQUIRED:
LOGE("Root is required for this operation\n");
close(fd);
return -1;
case MainResponse::ACCESS_DENIED:
case +RespondCode::ACCESS_DENIED:
LOGE("Access denied\n");
close(fd);
return -1;
Expand Down
Loading

0 comments on commit 8d5b9e5

Please sign in to comment.