mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Merge remote-tracking branch 'john/master' into development
This commit is contained in:
commit
a25dace7e0
@ -77,6 +77,7 @@ post_ota() {
|
||||
cat << EOF > post-fs-data.d/post_ota.sh
|
||||
${1}/bootctl mark-boot-successful
|
||||
rm -f ${1}/bootctl
|
||||
rm -f ${1}/post-fs-data.d/post_ota.sh
|
||||
EOF
|
||||
chmod 755 post-fs-data.d/post_ota.sh
|
||||
cd /
|
||||
|
@ -101,6 +101,8 @@ static void main_daemon() {
|
||||
android_logging();
|
||||
setsid();
|
||||
setcon("u:r:" SEPOL_PROC_DOMAIN ":s0");
|
||||
restore_rootcon();
|
||||
|
||||
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
|
||||
xdup2(fd, STDOUT_FILENO);
|
||||
xdup2(fd, STDERR_FILENO);
|
||||
|
@ -46,7 +46,8 @@ static int vprintk(const char *fmt, va_list ap) {
|
||||
|
||||
static void setup_klog() {
|
||||
mknod("/kmsg", S_IFCHR | 0666, makedev(1, 11));
|
||||
kmsg = xfopen("/kmsg", "ae");
|
||||
int fd = xopen("/kmsg", O_WRONLY | O_CLOEXEC);
|
||||
kmsg = fdopen(fd, "w");
|
||||
setbuf(kmsg, nullptr);
|
||||
unlink("/kmsg");
|
||||
log_cb.d = log_cb.i = log_cb.w = log_cb.e = vprintk;
|
||||
@ -156,11 +157,10 @@ private:
|
||||
bool read_dt_fstab(const char *name, char *partname, char *partfs);
|
||||
bool patch_sepolicy();
|
||||
void cleanup();
|
||||
void re_exec_init();
|
||||
|
||||
public:
|
||||
explicit MagiskInit(char *argv[]) : argv(argv) {}
|
||||
void setup_overlay();
|
||||
void re_exec_init();
|
||||
void start();
|
||||
void test();
|
||||
};
|
||||
@ -460,6 +460,27 @@ void MagiskInit::early_mount() {
|
||||
mount_root(odm);
|
||||
}
|
||||
|
||||
static void patch_socket_name(const char *path) {
|
||||
uint8_t *buf;
|
||||
char name[sizeof(MAIN_SOCKET)];
|
||||
size_t size;
|
||||
mmap_rw(path, buf, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (memcmp(buf + i, MAIN_SOCKET, sizeof(MAIN_SOCKET)) == 0) {
|
||||
gen_rand_str(name, sizeof(name));
|
||||
memcpy(buf + i, name, sizeof(name));
|
||||
i += sizeof(name);
|
||||
}
|
||||
}
|
||||
munmap(buf, size);
|
||||
}
|
||||
|
||||
constexpr const char wrapper[] =
|
||||
"#!/system/bin/sh\n"
|
||||
"export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:/apex/com.android.runtime/" LIBNAME "\"\n"
|
||||
"exec /sbin/magisk.bin \"$0\" \"$@\"\n"
|
||||
;
|
||||
|
||||
void MagiskInit::setup_rootfs() {
|
||||
bool patch_init = patch_sepolicy();
|
||||
|
||||
@ -531,6 +552,7 @@ void MagiskInit::setup_rootfs() {
|
||||
gen_rand_str(pfd_svc + 1, sizeof(pfd_svc) - 1);
|
||||
gen_rand_str(ls_svc + 1, sizeof(ls_svc) - 1);
|
||||
gen_rand_str(bc_svc + 1, sizeof(bc_svc) - 1);
|
||||
LOGD("Inject magisk services: [%s] [%s] [%s]\n", pfd_svc, ls_svc, bc_svc);
|
||||
fprintf(rc, magiskrc, pfd_svc, pfd_svc, ls_svc, bc_svc, bc_svc);
|
||||
fclose(rc);
|
||||
clone_attr("/init.rc", "/init.p.rc");
|
||||
@ -545,6 +567,56 @@ void MagiskInit::setup_rootfs() {
|
||||
int rootdir = xopen("/root", O_RDONLY | O_CLOEXEC);
|
||||
int sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
|
||||
link_dir(sbin, rootdir);
|
||||
close(sbin);
|
||||
|
||||
LOGD("Mount /sbin tmpfs overlay\n");
|
||||
xmount("tmpfs", "/sbin", "tmpfs", 0, "mode=755");
|
||||
sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
|
||||
|
||||
char path[64];
|
||||
|
||||
// Create symlinks pointing back to /root
|
||||
DIR *dir = xfdopendir(rootdir);
|
||||
struct dirent *entry;
|
||||
while((entry = xreaddir(dir))) {
|
||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||
continue;
|
||||
sprintf(path, "/root/%s", entry->d_name);
|
||||
xsymlinkat(path, sbin, entry->d_name);
|
||||
}
|
||||
|
||||
// Dump binaries
|
||||
mkdir(MAGISKTMP, 0755);
|
||||
fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000);
|
||||
write(fd, config.buf, config.sz);
|
||||
close(fd);
|
||||
fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755);
|
||||
write(fd, self.buf, self.sz);
|
||||
close(fd);
|
||||
if (access("/system/apex", F_OK) == 0) {
|
||||
LOGD("APEX detected, use wrapper\n");
|
||||
dump_magisk("/sbin/magisk.bin", 0755);
|
||||
patch_socket_name("/sbin/magisk.bin");
|
||||
fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
|
||||
write(fd, wrapper, sizeof(wrapper) - 1);
|
||||
close(fd);
|
||||
} else {
|
||||
dump_magisk("/sbin/magisk", 0755);
|
||||
patch_socket_name("/sbin/magisk");
|
||||
}
|
||||
|
||||
// Create applet symlinks
|
||||
for (int i = 0; applet_names[i]; ++i) {
|
||||
sprintf(path, "/sbin/%s", applet_names[i]);
|
||||
xsymlink("/sbin/magisk", path);
|
||||
}
|
||||
for (int i = 0; init_applet[i]; ++i) {
|
||||
sprintf(path, "/sbin/%s", init_applet[i]);
|
||||
xsymlink("/sbin/magiskinit", path);
|
||||
}
|
||||
|
||||
close(rootdir);
|
||||
close(sbin);
|
||||
}
|
||||
|
||||
bool MagiskInit::patch_sepolicy() {
|
||||
@ -603,99 +675,8 @@ void MagiskInit::cleanup() {
|
||||
umount_root(odm);
|
||||
}
|
||||
|
||||
static inline void patch_socket_name(const char *path) {
|
||||
uint8_t *buf;
|
||||
char name[sizeof(MAIN_SOCKET)];
|
||||
size_t size;
|
||||
mmap_rw(path, buf, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (memcmp(buf + i, MAIN_SOCKET, sizeof(MAIN_SOCKET)) == 0) {
|
||||
gen_rand_str(name, sizeof(name));
|
||||
memcpy(buf + i, name, sizeof(name));
|
||||
i += sizeof(name);
|
||||
}
|
||||
}
|
||||
munmap(buf, size);
|
||||
}
|
||||
|
||||
static const char wrapper[] =
|
||||
"#!/system/bin/sh\n"
|
||||
"export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:/apex/com.android.runtime/" LIBNAME "\"\n"
|
||||
"exec /sbin/magisk.bin \"$0\" \"$@\"\n";
|
||||
|
||||
void MagiskInit::setup_overlay() {
|
||||
char path[128];
|
||||
int fd;
|
||||
|
||||
// Wait for early-init start
|
||||
while (access(EARLYINIT, F_OK) != 0)
|
||||
usleep(10);
|
||||
setcon("u:r:" SEPOL_PROC_DOMAIN ":s0");
|
||||
unlink(EARLYINIT);
|
||||
|
||||
#ifdef MAGISK_DEBUG
|
||||
kmsg = xfopen("/dev/kmsg", "ae");
|
||||
setbuf(kmsg, nullptr);
|
||||
#endif
|
||||
|
||||
LOGD("Setting up overlay\n");
|
||||
|
||||
// Mount the /sbin tmpfs overlay
|
||||
xmount("tmpfs", "/sbin", "tmpfs", 0, nullptr);
|
||||
chmod("/sbin", 0755);
|
||||
setfilecon("/sbin", "u:object_r:rootfs:s0");
|
||||
|
||||
// Dump binaries
|
||||
mkdir(MAGISKTMP, 0755);
|
||||
fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000);
|
||||
write(fd, config.buf, config.sz);
|
||||
close(fd);
|
||||
fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755);
|
||||
write(fd, self.buf, self.sz);
|
||||
close(fd);
|
||||
if (access("/system/apex", F_OK) == 0) {
|
||||
LOGD("APEX detected, use wrapper\n");
|
||||
dump_magisk("/sbin/magisk.bin", 0755);
|
||||
patch_socket_name("/sbin/magisk.bin");
|
||||
setfilecon("/sbin/magisk.bin", "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
|
||||
fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
|
||||
write(fd, wrapper, sizeof(wrapper) - 1);
|
||||
close(fd);
|
||||
} else {
|
||||
dump_magisk("/sbin/magisk", 0755);
|
||||
patch_socket_name("/sbin/magisk");
|
||||
}
|
||||
setfilecon("/sbin/magisk", "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
|
||||
setfilecon("/sbin/magiskinit", "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
|
||||
|
||||
// Create applet symlinks
|
||||
for (int i = 0; applet_names[i]; ++i) {
|
||||
sprintf(path, "/sbin/%s", applet_names[i]);
|
||||
xsymlink("/sbin/magisk", path);
|
||||
}
|
||||
for (int i = 0; init_applet[i]; ++i) {
|
||||
sprintf(path, "/sbin/%s", init_applet[i]);
|
||||
xsymlink("/sbin/magiskinit", path);
|
||||
}
|
||||
|
||||
// Create symlinks pointing back to /root
|
||||
DIR *dir = xopendir("/root");
|
||||
struct dirent *entry;
|
||||
fd = xopen("/sbin", O_RDONLY);
|
||||
while((entry = xreaddir(dir))) {
|
||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||
continue;
|
||||
sprintf(path, "/root/%s", entry->d_name);
|
||||
xsymlinkat(path, fd, entry->d_name);
|
||||
}
|
||||
closedir(dir);
|
||||
close(fd);
|
||||
|
||||
close(xopen(EARLYINITDONE, O_RDONLY | O_CREAT, 0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void MagiskInit::re_exec_init() {
|
||||
LOGD("Re-exec /init\n");
|
||||
cleanup();
|
||||
execv("/init", argv);
|
||||
exit(1);
|
||||
@ -722,6 +703,7 @@ void MagiskInit::start() {
|
||||
preset();
|
||||
early_mount();
|
||||
setup_rootfs();
|
||||
re_exec_init();
|
||||
}
|
||||
|
||||
void MagiskInit::test() {
|
||||
@ -767,14 +749,4 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Run the main routine
|
||||
init.start();
|
||||
|
||||
// Close all file descriptors
|
||||
for (int i = 0; i < 30; ++i)
|
||||
close(i);
|
||||
|
||||
// Launch daemon to setup overlay
|
||||
if (fork_dont_care() == 0)
|
||||
init.setup_overlay();
|
||||
|
||||
init.re_exec_init();
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ int magisk_main(int argc, char *argv[]) {
|
||||
unlock_blocks();
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "--restorecon") == 0) {
|
||||
restore_rootcon();
|
||||
restorecon();
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "--clone-attr") == 0) {
|
||||
|
@ -1,15 +1,9 @@
|
||||
#include <magisk.h>
|
||||
#include <magiskpolicy.h>
|
||||
|
||||
static const char magiskrc[] =
|
||||
constexpr const char magiskrc[] =
|
||||
"\n\n"
|
||||
|
||||
"on early-init\n"
|
||||
" write " EARLYINIT " 1\n"
|
||||
" wait " EARLYINITDONE "\n"
|
||||
" rm " EARLYINITDONE "\n"
|
||||
"\n"
|
||||
|
||||
"on post-fs-data\n"
|
||||
" start logd\n"
|
||||
" load_persist_props\n"
|
||||
|
@ -6,8 +6,6 @@
|
||||
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
|
||||
#define LOGFILE "/cache/magisk.log"
|
||||
#define UNBLOCKFILE "/dev/.magisk_unblock"
|
||||
#define EARLYINIT "/dev/.magisk_early_init"
|
||||
#define EARLYINITDONE "/dev/.magisk_early_init_done"
|
||||
#define DISABLEFILE "/cache/.disable_magisk"
|
||||
#define MAGISKTMP "/sbin/.magisk"
|
||||
#define MIRRDIR MAGISKTMP "/mirror"
|
||||
|
@ -71,7 +71,7 @@ void crawl_procfs(DIR *dir, const function<bool (int)> &fn) {
|
||||
}
|
||||
}
|
||||
|
||||
bool proc_name_match(int pid, const char *name) {
|
||||
static bool proc_name_match(int pid, const char *name) {
|
||||
char buf[4019];
|
||||
FILE *f;
|
||||
#if 0
|
||||
|
@ -19,8 +19,6 @@
|
||||
#define SAFETYNET_PKG "com.google.android.gms"
|
||||
#define MICROG_SAFETYNET "org.microg.gms.droidguard"
|
||||
|
||||
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
|
||||
|
||||
// CLI entries
|
||||
void launch_magiskhide(int client);
|
||||
int stop_magiskhide();
|
||||
@ -29,15 +27,14 @@ int rm_list(int client);
|
||||
void ls_list(int client);
|
||||
|
||||
// Process monitoring
|
||||
void *update_uid_map(void * p = nullptr);
|
||||
void proc_monitor();
|
||||
void update_uid_map();
|
||||
|
||||
// Utility functions
|
||||
void manage_selinux();
|
||||
void clean_magisk_props();
|
||||
void crawl_procfs(const std::function<bool (int)> &fn);
|
||||
void crawl_procfs(DIR *dir, const std::function<bool (int)> &fn);
|
||||
bool proc_name_match(int pid, const char *name);
|
||||
|
||||
extern bool hide_enabled;
|
||||
extern pthread_mutex_t monitor_lock;
|
||||
|
@ -134,18 +134,21 @@ static bool parse_packages_xml(string_view s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void update_uid_map() {
|
||||
MutexGuard lock(monitor_lock);
|
||||
uid_proc_map.clear();
|
||||
file_readline("/data/system/packages.xml", parse_packages_xml, true);
|
||||
}
|
||||
|
||||
static void check_zygote() {
|
||||
int min_zyg = 1;
|
||||
if (access("/system/bin/app_process64", R_OK) == 0)
|
||||
min_zyg = 2;
|
||||
for (bool first = true; zygote_map.size() < min_zyg; first = false) {
|
||||
if (!first)
|
||||
usleep(10000);
|
||||
for (;;) {
|
||||
crawl_procfs([](int pid) -> bool {
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
|
||||
FILE *f = fopen(buf, "re");
|
||||
if (f) {
|
||||
if (FILE *f = fopen(buf, "re"); f) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (strncmp(buf, "zygote", 6) == 0 && parse_ppid(pid) == 1)
|
||||
new_zygote(pid);
|
||||
@ -153,14 +156,41 @@ static void check_zygote() {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (zygote_map.size() >= min_zyg)
|
||||
break;
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
void *update_uid_map(void*) {
|
||||
MutexGuard lock(monitor_lock);
|
||||
uid_proc_map.clear();
|
||||
file_readline("/data/system/packages.xml", parse_packages_xml, true);
|
||||
return nullptr;
|
||||
#define APP_PROC "/system/bin/app_process"
|
||||
|
||||
static void setup_inotify() {
|
||||
inotify_fd = xinotify_init1(IN_CLOEXEC);
|
||||
if (inotify_fd < 0)
|
||||
term_thread();
|
||||
|
||||
// Setup inotify asynchronous I/O
|
||||
fcntl(inotify_fd, F_SETFL, O_ASYNC);
|
||||
struct f_owner_ex ex = {
|
||||
.type = F_OWNER_TID,
|
||||
.pid = gettid()
|
||||
};
|
||||
fcntl(inotify_fd, F_SETOWN_EX, &ex);
|
||||
|
||||
// Monitor packages.xml
|
||||
inotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE);
|
||||
|
||||
// Monitor app_process
|
||||
if (access(APP_PROC "32", F_OK) == 0) {
|
||||
inotify_add_watch(inotify_fd, APP_PROC "32", IN_ACCESS);
|
||||
if (access(APP_PROC "64", F_OK) == 0)
|
||||
inotify_add_watch(inotify_fd, APP_PROC "64", IN_ACCESS);
|
||||
} else {
|
||||
inotify_add_watch(inotify_fd, APP_PROC, IN_ACCESS);
|
||||
}
|
||||
|
||||
// First find existing zygotes
|
||||
check_zygote();
|
||||
}
|
||||
|
||||
/*************************
|
||||
@ -233,7 +263,10 @@ static void inotify_event(int) {
|
||||
read(inotify_fd, buf, sizeof(buf));
|
||||
if ((event->mask & IN_CLOSE_WRITE) && strcmp(event->name, "packages.xml") == 0) {
|
||||
LOGD("proc_monitor: /data/system/packages.xml updated\n");
|
||||
new_daemon_thread(update_uid_map);
|
||||
uid_proc_map.clear();
|
||||
file_readline("/data/system/packages.xml", parse_packages_xml, true);
|
||||
} else if (event->mask & IN_ACCESS) {
|
||||
check_zygote();
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,12 +395,10 @@ static void new_zygote(int pid) {
|
||||
xptrace(PTRACE_CONT, pid);
|
||||
}
|
||||
|
||||
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
|
||||
#define DETACH_AND_CONT { detach = true; continue; }
|
||||
void proc_monitor() {
|
||||
inotify_fd = xinotify_init1(IN_CLOEXEC);
|
||||
if (inotify_fd < 0)
|
||||
term_thread();
|
||||
|
||||
void proc_monitor() {
|
||||
// Unblock some signals
|
||||
sigset_t block_set;
|
||||
sigemptyset(&block_set);
|
||||
@ -381,19 +412,7 @@ void proc_monitor() {
|
||||
act.sa_handler = inotify_event;
|
||||
sigaction(SIGIO, &act, nullptr);
|
||||
|
||||
// Setup inotify asynchronous I/O
|
||||
fcntl(inotify_fd, F_SETFL, O_ASYNC);
|
||||
struct f_owner_ex ex = {
|
||||
.type = F_OWNER_TID,
|
||||
.pid = gettid()
|
||||
};
|
||||
fcntl(inotify_fd, F_SETOWN_EX, &ex);
|
||||
|
||||
// Start monitoring packages.xml
|
||||
inotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE);
|
||||
|
||||
// First find existing zygotes
|
||||
check_zygote();
|
||||
setup_inotify();
|
||||
|
||||
int status;
|
||||
|
||||
|
@ -54,6 +54,8 @@ void sepol_magisk_rules() {
|
||||
// Let init run stuffs
|
||||
sepol_allow("kernel", SEPOL_PROC_DOMAIN, "fd", "use");
|
||||
sepol_allow("init", SEPOL_PROC_DOMAIN, "process", ALL);
|
||||
sepol_allow("init", "tmpfs", "file", "getattr");
|
||||
sepol_allow("init", "tmpfs", "file", "execute");
|
||||
|
||||
// Shell, properties, logs
|
||||
if (sepol_exists("default_prop"))
|
||||
|
@ -36,6 +36,7 @@ void setfilecon_at(int dirfd, const char *name, const char *con);
|
||||
void selinux_builtin_impl();
|
||||
void dload_selinux();
|
||||
void restorecon();
|
||||
void restore_rootcon();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,17 +1,21 @@
|
||||
#include <sys/xattr.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <string_view>
|
||||
|
||||
#include <magisk.h>
|
||||
#include <utils.h>
|
||||
#include <selinux.h>
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
#define UNLABEL_CON "u:object_r:unlabeled:s0"
|
||||
#define SYSTEM_CON "u:object_r:system_file:s0"
|
||||
#define ADB_CON "u:object_r:adb_data_file:s0"
|
||||
#define ROOT_CON "u:object_r:rootfs:s0"
|
||||
#define MAGISK_CON "u:object_r:" SEPOL_FILE_DOMAIN ":s0"
|
||||
|
||||
// Stub implementation
|
||||
@ -164,7 +168,7 @@ static void restore_syscon(int dirfd) {
|
||||
|
||||
dir = xfdopendir(dirfd);
|
||||
while ((entry = xreaddir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||
continue;
|
||||
int fd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
if (entry->d_type == DT_DIR) {
|
||||
@ -193,7 +197,7 @@ static void restore_magiskcon(int dirfd) {
|
||||
|
||||
dir = xfdopendir(dirfd);
|
||||
while ((entry = xreaddir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||
continue;
|
||||
int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||
if (entry->d_type == DT_DIR) {
|
||||
@ -220,3 +224,22 @@ void restorecon() {
|
||||
restore_magiskcon(fd);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void restore_rootcon() {
|
||||
setfilecon("/sbin", ROOT_CON);
|
||||
struct dirent *entry;
|
||||
DIR *dir = xopendir("/sbin");
|
||||
int dfd = dirfd(dir);
|
||||
|
||||
while ((entry = xreaddir(dir))) {
|
||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||
continue;
|
||||
setfilecon_at(dfd, entry->d_name, ROOT_CON);
|
||||
}
|
||||
|
||||
setfilecon("/sbin/magisk.bin", MAGISK_CON);
|
||||
setfilecon("/sbin/magisk", MAGISK_CON);
|
||||
setfilecon("/sbin/magiskinit", MAGISK_CON);
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user