Compare commits

..

23 Commits
v15.0 ... v15.3

Author SHA1 Message Date
topjohnwu
e8302dfbe2 Update Magisk Manager 2018-01-13 06:28:22 +08:00
topjohnwu
558f95cf7e Improve APK installation and add logging 2018-01-13 06:28:07 +08:00
topjohnwu
18f6ead891 Fix alignment when boot image has head offset 2018-01-13 06:28:07 +08:00
topjohnwu
10bd25be52 Suppress harmless error logs 2018-01-12 00:23:38 +08:00
topjohnwu
65511845d2 Fix APK installation on some devices
Close #367. Android 6.0 and before doesn't like the new path
2018-01-11 20:57:05 +08:00
topjohnwu
1c743839ea Add MS_SILENT to xmount and cleanup function wraps 2018-01-11 03:06:20 +08:00
topjohnwu
bcae9dec41 Fix a bug when only one script will run 2018-01-11 02:48:15 +08:00
Shaka Huang
482c9af41f Fix segmentation fault
When both keepverity and keepforceencrypt are false, ‘e’ will be freed after removing ‘verity_key’ and segmentation fault might happened in strstr(e->filename, “fstab”)

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2018-01-11 02:08:52 +08:00
topjohnwu
2bf2e7461f Update diagram URL 2018-01-09 06:50:03 +08:00
topjohnwu
7d1082b1cb Fix magiskhide in graph 2018-01-09 06:48:58 +08:00
topjohnwu
0dbae83aec Update diagram URL 2018-01-09 06:08:54 +08:00
topjohnwu
f927c1b997 Update procedure diagram 2018-01-09 06:07:12 +08:00
topjohnwu
89ec7dad2b Update documentation to v15.2 2018-01-08 22:33:55 +08:00
topjohnwu
4fd61345af Happy New Year 2018-01-02 01:27:20 +08:00
topjohnwu
66cca24453 Samsung need more rules :) 2018-01-02 00:11:26 +08:00
topjohnwu
e733484fab Some devices don't like all log buffers 2018-01-01 23:58:13 +08:00
topjohnwu
e5c3183025 Update scripts 2018-01-01 16:46:28 +08:00
topjohnwu
930c82316a Slightly change logging style 2017-12-31 21:54:39 +08:00
Shaka Huang
3dc22db265 Support loading split sepolicy on non skip_initramfs devices
For certain device (e.g ZenFone 4 ZE554KL) there’s no sepolicy under rootfs and no a/b partition (implies no vendor partition) Magisk will failed to patch SELinux policy database and the system won’t boot up.

In order to cope with this configuration the status of loading policy db needs to be checked, once it failed we have to mount the system partition and do patch_sepolicy() again.

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2017-12-31 21:30:56 +08:00
topjohnwu
d8c51cb286 Update sepolicy handling 2017-12-31 19:32:04 +08:00
topjohnwu
2f79d0c3b3 Fix segfault while patching dtb 2017-12-31 19:30:56 +08:00
topjohnwu
d8bb3af06b Miscellaneous 2017-12-29 04:25:30 +08:00
topjohnwu
e139e8777b Fix faulty magiskboot ramdisk patch code 2017-12-29 04:25:03 +08:00
35 changed files with 571 additions and 439 deletions

View File

@@ -43,12 +43,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
**MagiskManager** (`app`)
* Copyright 2016-2017, John Wu (@topjohnwu)
* Copyright 2016-2018, John Wu (@topjohnwu)
* All contributors and translators on Github
**MagiskSU** (`core/jni/su`)
* Copyright 2016-2017, John Wu (@topjohnwu)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2015, Pierre-Hugues Husson (phh@phh.me)
* Copyright 2013, Koushik Dutta (@koush)
* Copyright 2010, Adam Shanks (@ChainsDD)
@@ -56,18 +56,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
**MagiskPolicy** (`core/jni/magiskpolicy`)
* Copyright 2016-2017, John Wu (@topjohnwu)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2015, Pierre-Hugues Husson (phh@phh.me)
* Copyright 2015, Joshua Brindle (@joshua_brindle)
**MagiskHide** (`core/jni/magiskhide`)
* Copyright 2016-2017, John Wu (@topjohnwu)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2016, Pierre-Hugues Husson (phh@phh.me)
**resetprop** (`core/jni/resetprop`)
* Copyright 2016-2017 John Wu (@topjohnwu)
* Copyright 2016-2018 John Wu (@topjohnwu)
* Copyright 2016 nkk71 (nkk71x@gmail.com)
**External Dependencies** (`core/jni/external`)
@@ -78,4 +78,4 @@ All of them are either GPL or GPL compatible.
**Others Not Mentioned**
* Copyright 2016-2017, John Wu (@topjohnwu)
* Copyright 2016-2018, John Wu (@topjohnwu)

2
app

Submodule app updated: de2285d5e9...759e905c3c

View File

@@ -140,14 +140,14 @@ static void pm_setenv(struct vector *v) {
static void exec_common_script(const char* stage) {
DIR *dir;
struct dirent *entry;
snprintf(buf, PATH_MAX, "%s/%s.d", COREDIR, stage);
snprintf(buf2, PATH_MAX, "%s/%s.d", COREDIR, stage);
if (!(dir = xopendir(buf)))
if (!(dir = xopendir(buf2)))
return;
while ((entry = xreaddir(dir))) {
if (entry->d_type == DT_REG) {
snprintf(buf2, PATH_MAX, "%s/%s", buf, entry->d_name);
snprintf(buf2, PATH_MAX, "%s/%s.d/%s", COREDIR, stage, entry->d_name);
if (access(buf2, X_OK) == -1)
continue;
LOGI("%s.d: exec [%s]\n", stage, entry->d_name);
@@ -274,7 +274,7 @@ static void clone_skeleton(struct node_entry *node) {
char *con;
xstat(full_path, &s);
getfilecon(full_path, &con);
LOGI("tmpfs: %s\n", full_path);
LOGI("mnt_tmpfs : %s\n", full_path);
xmount("tmpfs", full_path, "tmpfs", 0, NULL);
chmod(full_path, s.st_mode & 0777);
chown(full_path, s.st_uid, s.st_gid);
@@ -295,7 +295,7 @@ static void clone_skeleton(struct node_entry *node) {
if (child->parent->parent == NULL && strcmp(child->name, "vendor") == 0) {
if (IS_LNK(child)) {
cp_afc(MIRRDIR "/system/vendor", "/system/vendor");
LOGI("cplink: %s -> %s\n", MIRRDIR "/system/vendor", "/system/vendor");
LOGI("creat_link: %s <- %s\n", "/system/vendor", MIRRDIR "/system/vendor");
}
// Skip
continue;
@@ -315,9 +315,9 @@ static void clone_skeleton(struct node_entry *node) {
// Copy symlinks directly
cp_afc(buf2, buf);
#ifdef MAGISK_DEBUG
LOGI("cplink: %s -> %s\n",buf2, buf);
LOGI("creat_link: %s <- %s\n",buf, buf2);
#else
LOGI("cplink: %s\n", buf);
LOGI("creat_link: %s\n", buf);
#endif
} else {
snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name);
@@ -647,23 +647,30 @@ void late_start(int client) {
core_only:
// Install Magisk Manager if exists
if (access(MANAGERAPK, F_OK) == 0) {
rename(MANAGERAPK, "/data/magisk.apk");
setfilecon("/data/magisk.apk", "u:object_r:su_file:s0");
while (1) {
sleep(5);
int apk_res = -1, pid;
pid = exec_command(1, &apk_res, pm_setenv,
"app_process",
"/system/bin", "com.android.commands.pm.Pm",
"install", "-r", MANAGERAPK, NULL);
"install", "-r", "/data/magisk.apk", NULL);
if (pid != -1) {
int err = 0;
while (fdgets(buf, PATH_MAX, apk_res) > 0) {
LOGD("apk_install: %s", buf);
err |= strstr(buf, "Error:") != NULL;
}
waitpid(pid, NULL, 0);
fdgets(buf, PATH_MAX, apk_res);
close(apk_res);
// Keep trying until pm is started
if (strstr(buf, "Error:") == NULL)
break;
if (err)
continue;
break;
}
}
unlink(MANAGERAPK);
unlink("/data/magisk.apk");
}
// All boot stage done, cleanup everything

View File

@@ -129,11 +129,6 @@ void daemon_init() {
unlink("/data/magisk_debug.log");
chmod("/data/adb", 0700);
// Use shell glob to match files
exec_command_sync("sh", "-c",
"mv -f /data/adb/magisk/stock_*.img.gz /data;"
"rm -f /data/user*/*/magisk.db;", NULL);
LOGI("* Creating /sbin overlay");
DIR *dir;
struct dirent *entry;
@@ -191,7 +186,7 @@ void daemon_init() {
// Check whether skip_initramfs device
vec_for_each(&mounts, line) {
if (strstr(line, " /system_root ")) {
xmkdir_p(MIRRDIR "/system", 0755);
xmkdirs(MIRRDIR "/system", 0755);
bind_mount("/system_root/system", MIRRDIR "/system");
skip_initramfs = 1;
break;
@@ -200,7 +195,7 @@ void daemon_init() {
vec_for_each(&mounts, line) {
if (!skip_initramfs && strstr(line, " /system ")) {
sscanf(line, "%s", buf);
xmkdir_p(MIRRDIR "/system", 0755);
xmkdirs(MIRRDIR "/system", 0755);
xmount(buf, MIRRDIR "/system", "ext4", MS_RDONLY, NULL);
#ifdef MAGISK_DEBUG
LOGI("mount: %s -> %s\n", buf, MIRRDIR "/system");
@@ -210,7 +205,7 @@ void daemon_init() {
} else if (strstr(line, " /vendor ")) {
seperate_vendor = 1;
sscanf(line, "%s", buf);
xmkdir_p(MIRRDIR "/vendor", 0755);
xmkdirs(MIRRDIR "/vendor", 0755);
xmount(buf, MIRRDIR "/vendor", "ext4", MS_RDONLY, NULL);
#ifdef MAGISK_DEBUG
LOGI("mount: %s -> %s\n", buf, MIRRDIR "/vendor");
@@ -229,11 +224,11 @@ void daemon_init() {
LOGI("link: %s\n", MIRRDIR "/vendor");
#endif
}
xmkdir_p(MIRRDIR "/bin", 0755);
xmkdirs(MIRRDIR "/bin", 0755);
bind_mount(DATABIN, MIRRDIR "/bin");
LOGI("* Setting up internal busybox");
xmkdir_p(BBPATH, 0755);
xmkdirs(BBPATH, 0755);
exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL);
xsymlink(MIRRDIR "/bin/busybox", BBPATH "/busybox");
}

View File

@@ -55,7 +55,7 @@ static void *logger_thread(void *args) {
while (1) {
// Start logcat
log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "all" , "-v", "threadtime", "-s", "am_proc_start", "Magisk", NULL);
log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "events", "-b", "main", "-v", "threadtime", "-s", "am_proc_start", "-s", "Magisk", NULL);
while (fdgets(line, sizeof(line), log_fd)) {
for (int i = 0; i < (sizeof(log_events) / sizeof(struct log_listener)); ++i) {
if (log_events[i].fd > 0 && log_events[i].filter(line)) {
@@ -74,7 +74,7 @@ static void *logger_thread(void *args) {
waitpid(log_pid, NULL, 0);
// Clear buffer before restart
exec_command_sync("logcat", "-b", "all", "-c", NULL);
exec_command_sync("logcat", "-b", "events", "-b", "main", "-c", NULL);
}
// Should never be here, but well...

View File

@@ -77,7 +77,7 @@ static void parse_cmdline(struct cmdline *cmd) {
char cmdline[4096];
mkdir("/proc", 0555);
mount("proc", "/proc", "proc", 0, NULL);
xmount("proc", "/proc", "proc", 0, NULL);
int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0';
close(fd);
@@ -305,16 +305,20 @@ static int verify_precompiled() {
return strcmp(sys_sha, ven_sha) == 0;
}
static void patch_sepolicy() {
static int patch_sepolicy() {
if (access("/sepolicy", R_OK) == 0)
load_policydb("/sepolicy");
else if (access(SPLIT_PRECOMPILE, R_OK) == 0 && verify_precompiled())
load_policydb(SPLIT_PRECOMPILE);
else if (access(SPLIT_PLAT_CIL, R_OK) == 0)
compile_cil();
else
return 1;
sepol_magisk_rules();
dump_policydb("/sepolicy");
return 0;
}
#define BUFSIZE (1 << 20)
@@ -364,7 +368,8 @@ static void magisk_init_daemon() {
sepol_allow("su", ALL, ALL, ALL);
// Wait till init cold boot done
wait_till_exists("/dev/.coldboot_done");
while (access("/dev/.coldboot_done", F_OK))
usleep(1);
int null = open("/dev/null", O_RDWR | O_CLOEXEC);
dup3(null, STDIN_FILENO, O_CLOEXEC);
@@ -450,7 +455,7 @@ int main(int argc, char *argv[]) {
frm_rf(root);
mkdir("/sys", 0755);
mount("sysfs", "/sys", "sysfs", 0, NULL);
xmount("sysfs", "/sys", "sysfs", 0, NULL);
char partname[32];
snprintf(partname, sizeof(partname), "system%s", cmd.slot);
@@ -459,20 +464,20 @@ int main(int argc, char *argv[]) {
setup_block(&dev, partname);
mkdir("/system_root", 0755);
mount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
// Exclude system folder
excl_list = (char *[]) { "system", NULL };
clone_dir(system_root, root);
mkdir("/system", 0755);
mount("/system_root/system", "/system", NULL, MS_BIND, NULL);
xmount("/system_root/system", "/system", NULL, MS_BIND, NULL);
snprintf(partname, sizeof(partname), "vendor%s", cmd.slot);
// We need to mount independent vendor partition
if (setup_block(&dev, partname) == 0)
mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
xmount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
close(system_root);
} else {
@@ -507,7 +512,21 @@ int main(int argc, char *argv[]) {
mv_dir(overlay, root);
patch_ramdisk(root);
patch_sepolicy();
if (patch_sepolicy()) {
/* Non skip_initramfs devices using separate sepolicy
* Mount /system and try to load again */
xmount("sysfs", "/sys", "sysfs", 0, NULL);
struct device dev;
setup_block(&dev, "system");
xmount(dev.path, "/system", "ext4", MS_RDONLY, NULL);
// We need to mount independent vendor partition
if (setup_block(&dev, "vendor") == 0)
xmount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
patch_sepolicy();
umount("/system");
}
if (fork_dont_care() == 0) {
strcpy(argv[0], "magiskinit");

View File

@@ -61,7 +61,7 @@ int xumount(const char *target);
int xumount2(const char *target, int flags);
int xrename(const char *oldpath, const char *newpath);
int xmkdir(const char *pathname, mode_t mode);
int xmkdir_p(const char *pathname, mode_t mode);
int xmkdirs(const char *pathname, mode_t mode);
int xmkdirat(int dirfd, const char *pathname, mode_t mode);
void *xmmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
@@ -101,7 +101,7 @@ struct file_attr {
};
int fd_getpath(int fd, char *path, size_t size);
int mkdir_p(const char *pathname, mode_t mode);
int mkdirs(const char *pathname, mode_t mode);
void in_order_walk(int dirfd, void (*callback)(int, struct dirent*));
void rm_rf(const char *path);
void frm_rf(int dirfd);

View File

@@ -63,8 +63,10 @@ int parse_img(const char *image, boot_img *boot) {
// Parse image
fprintf(stderr, "Parsing boot image: [%s]\n", image);
for (size_t pos = 0; pos < boot->map_size; pos += 256) {
switch (check_type(boot->map_addr + pos)) {
for (void *head = boot->map_addr; head < boot->map_addr + boot->map_size; head += 256) {
size_t pos = 0;
switch (check_type(head)) {
case CHROMEOS:
// The caller should know it's chromeos, as it needs additional signing
boot->flags |= CHROMEOS_FLAG;
@@ -75,33 +77,33 @@ int parse_img(const char *image, boot_img *boot) {
exit(ELF64_RET);
case AOSP:
// Read the header
memcpy(&boot->hdr, boot->map_addr + pos, sizeof(boot->hdr));
memcpy(&boot->hdr, head + pos, sizeof(boot->hdr));
pos += boot->hdr.page_size;
print_hdr(&boot->hdr);
boot->kernel = boot->map_addr + pos;
boot->kernel = head + pos;
pos += boot->hdr.kernel_size;
mem_align(&pos, boot->hdr.page_size);
boot->ramdisk = boot->map_addr + pos;
boot->ramdisk = head + pos;
pos += boot->hdr.ramdisk_size;
mem_align(&pos, boot->hdr.page_size);
if (boot->hdr.second_size) {
boot->second = boot->map_addr + pos;
boot->second = head + pos;
pos += boot->hdr.second_size;
mem_align(&pos, boot->hdr.page_size);
}
if (boot->hdr.extra_size) {
boot->extra = boot->map_addr + pos;
boot->extra = head + pos;
pos += boot->hdr.extra_size;
mem_align(&pos, boot->hdr.page_size);
}
if (pos < boot->map_size) {
boot->tail = boot->map_addr + pos;
boot->tail = head + pos;
boot->tail_size = boot->map_size - pos;
}

View File

@@ -78,8 +78,17 @@ static void dtb_patch(const char *file, int patch) {
fdt_for_each_subnode(block, fdt, fstab) {
fprintf(stderr, "Found block [%s] in fstab\n", fdt_get_name(fdt, block, NULL));
uint32_t value_size;
void *value = (char *) fdt_getprop(fdt, block, "fsmgr_flags", &value_size);
found |= patch_verity(&value, &value_size, patch);
void *value = (void *) fdt_getprop(fdt, block, "fsmgr_flags", &value_size);
if (patch) {
void *dup = xmalloc(value_size);
memcpy(dup, value, value_size);
memset(value, 0, value_size);
found |= patch_verity(&dup, &value_size, 1);
memcpy(value, dup, value_size);
free(dup);
} else {
found |= patch_verity(&value, &value_size, 0);
}
}
}
}

View File

@@ -73,12 +73,12 @@ static void usage(char *arg0) {
" --dtb-<cmd> <dtb>\n"
" Do dtb related cmds to <dtb> (modifications are done directly)\n"
" Supported commands:\n"
" -dump\n"
" dump\n"
" Dump all contents from dtb for debugging\n"
" -test\n"
" test\n"
" Check if fstab has verity/avb flags\n"
" Return value: 0/no flags 1/flag exists"
" -patch\n"
" Return value: 0/no flags 1/flag exists\n"
" patch\n"
" Search for fstab and remove verity/avb\n"
"\n"
" --compress[=method] <infile> [outfile]\n"

View File

@@ -9,6 +9,8 @@
#include "cpio.h"
static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
fprintf(stderr, "Patch with flag KEEPVERITY=[%s] KEEPFORCEENCRYPT=[%s]\n",
keepverity ? "true" : "false", keepforceencrypt ? "true" : "false");
cpio_entry *e;
vec_for_each(v, e) {
if (!e) continue;
@@ -19,6 +21,7 @@ static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
fprintf(stderr, "Remove [verity_key]\n");
cpio_free(e);
vec_cur(v) = NULL;
continue;
}
}
if (!keepforceencrypt) {
@@ -134,7 +137,7 @@ static void cpio_backup(struct vector *v, struct vector *bak, const char *orig,
backup = 1;
fprintf(stderr, "Backup mismatch entry: ");
} else {
// Someting new in ramdisk, record in rem
// Something new in ramdisk, record in rem
++j;
rem->data = xrealloc(rem->data, rem->filesize + strlen(n->filename) + 1);
memcpy(rem->data + rem->filesize, n->filename, strlen(n->filename) + 1);

View File

@@ -70,8 +70,6 @@ static void store_zygote_ns(int pid) {
static void lazy_unmount(const char* mountpoint) {
if (umount2(mountpoint, MNT_DETACH) != -1)
LOGD("hide_daemon: Unmounted (%s)\n", mountpoint);
else
LOGD("hide_daemon: Unmount Failed (%s)\n", mountpoint);
}
static void hide_daemon(int pid, int ppid) {
@@ -176,8 +174,8 @@ void proc_monitor() {
// Get the mount namespace of zygote
zygote_num = 0;
while(!zygote_num) {
// Check zygote every 2 secs
sleep(2);
// Check zygote every 10 ms
usleep(10000);
ps_filter_proc_name("zygote", store_zygote_ns);
}
ps_filter_proc_name("zygote64", store_zygote_ns);

View File

@@ -34,7 +34,7 @@ int fd_getpath(int fd, char *path, size_t size) {
return 0;
}
int mkdir_p(const char *pathname, mode_t mode) {
int mkdirs(const char *pathname, mode_t mode) {
char *path = strdup(pathname), *p;
errno = 0;
for (p = path + 1; *p; ++p) {
@@ -107,7 +107,7 @@ void mv_f(const char *source, const char *destination) {
struct file_attr a;
if (S_ISDIR(st.st_mode)) {
xmkdir_p(destination, st.st_mode & 0777);
xmkdirs(destination, st.st_mode & 0777);
src = xopen(source, O_RDONLY | O_CLOEXEC);
dest = xopen(destination, O_RDONLY | O_CLOEXEC);
fclone_attr(src, dest);
@@ -162,7 +162,7 @@ void cp_afc(const char *source, const char *destination) {
getattr(source, &a);
if (S_ISDIR(a.st.st_mode)) {
xmkdir_p(destination, a.st.st_mode & 0777);
xmkdirs(destination, a.st.st_mode & 0777);
src = xopen(source, O_RDONLY | O_CLOEXEC);
dest = xopen(destination, O_RDONLY | O_CLOEXEC);
fsetattr(dest, &a);

View File

@@ -139,9 +139,9 @@ char *mount_image(const char *img, const char *target) {
if (access(img, F_OK) == -1)
return NULL;
if (access(target, F_OK) == -1) {
if (xmkdir_p(target, 0755) == -1) {
if (xmkdirs(target, 0755) == -1) {
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xmkdir_p(target, 0755);
xmkdirs(target, 0755);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
}
}

View File

@@ -111,7 +111,12 @@ static int is_num(const char *s) {
ssize_t fdgets(char *buf, const size_t size, int fd) {
ssize_t len = 0;
buf[0] = '\0';
while (read(fd, buf + len, 1) >= 0 && len < size - 1) {
while (len < size - 1) {
int ret = read(fd, buf + len, 1);
if (ret < 0)
return -1;
if (ret == 0)
break;
if (buf[len] == '\0' || buf[len++] == '\n') {
buf[len] = '\0';
break;
@@ -282,7 +287,7 @@ int exec_command(int err, int *fd, void (*setupenv)(struct vector*), const char
int bind_mount(const char *from, const char *to) {
int ret = xmount(from, to, NULL, MS_BIND, NULL);
#ifdef MAGISK_DEBUG
LOGI("bind_mount: %s -> %s\n", from, to);
LOGI("bind_mount: %s <- %s\n", to, from);
#else
LOGI("bind_mount: %s\n", to);
#endif
@@ -304,7 +309,7 @@ int switch_mnt_ns(int pid) {
fd = xopen(mnt, O_RDONLY);
if (fd < 0) return 1;
// Switch to its namespace
ret = setns(fd, 0);
ret = xsetns(fd, 0);
close(fd);
return ret;
}

View File

@@ -4,19 +4,19 @@
#include "utils.h"
static int check_verity_pattern(const char *s) {
int pos = 0;
if (s[0] == ',') ++pos;
if (strncmp(s + pos, "verify", 6) == 0)
pos += 6;
else if (strncmp(s + pos, "avb", 3) == 0)
pos += 3;
int skip = 0;
if (s[0] == ',') ++skip;
if (strncmp(s + skip, "verify", 6) == 0)
skip += 6;
else if (strncmp(s + skip, "avb", 3) == 0)
skip += 3;
else
return -1;
if (s[pos] == '=') {
while (s[pos] != '\0' && s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos;
if (s[skip] == '=') {
while (s[skip] != '\0' && s[skip] != ' ' && s[skip] != '\n' && s[skip] != ',') ++skip;
}
return pos;
return skip;
}
static int check_encryption_pattern(const char *s) {
@@ -59,34 +59,41 @@ void patch_init_rc(void **buf, size_t *size) {
}
int patch_verity(void **buf, uint32_t *size, int patch) {
int skip, found = 0;
for (int pos = 0; pos < *size; ++pos) {
if ((skip = check_verity_pattern(*buf + pos)) > 0) {
found = 1;
fprintf(stderr, "%s pattern [%.*s]\n", patch ? "Remove" : "Found", skip, (char *) *buf + pos);
if (patch) {
memcpy(*buf + pos, *buf + pos + skip, *size - pos - skip);
memset(*buf + *size - skip, '\0', skip);
*size -= skip;
} else {
pos += skip - 1;
}
int skip, src_size = *size;
char *src = *buf, *patched = patch ? xcalloc(src_size, 1) : NULL;
for (int read = 0, write = 0; read < src_size; ++read, ++write) {
if ((skip = check_verity_pattern(src + read)) > 0) {
if (!patch)
return 1;
fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read);
read += skip;
*size -= skip;
}
if (patch)
patched[write] = src[read];
}
return found;
if (patch) {
free(*buf);
*buf = patched;
}
return 0;
}
void patch_encryption(void **buf, uint32_t *size) {
int skip;
for (int pos = 0; pos < *size; ++pos) {
if ((skip = check_encryption_pattern(*buf + pos)) > 0) {
fprintf(stderr, "Replace pattern [%.*s] with [encryptable]\n", skip, (char *) *buf + pos);
memcpy(*buf + pos, "encryptable", 11);
memcpy(*buf + pos + 11, *buf + pos + skip, *size - pos - skip);
memset(*buf + *size - skip + 11, '\0', skip - 11);
int skip, src_size = *size;
char *src = *buf, *patched = xcalloc(src_size, 1);
for (int read = 0, write = 0; read < src_size; ++read, ++write) {
if ((skip = check_encryption_pattern(src + read)) > 0) {
fprintf(stderr, "Replace pattern [%.*s] with [encryptable]\n", skip, src + read);
memcpy(patched + read, "encryptable", 11);
read += skip;
write += 11;
*size -= (skip - 11);
}
patched[write] = src[read];
}
free(*buf);
*buf = patched;
}

View File

@@ -156,14 +156,6 @@ int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
return ret;
}
int xconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
int ret = connect(sockfd, addr, addrlen);
if (ret == -1) {
PLOGE("connect");
}
return ret;
}
int xlisten(int sockfd, int backlog) {
int ret = listen(sockfd, backlog);
if (ret == -1) {
@@ -229,14 +221,6 @@ int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
return errno;
}
int xsocketpair(int domain, int type, int protocol, int sv[2]) {
int ret = socketpair(domain, type, protocol, sv);
if (ret == -1) {
PLOGE("socketpair");
}
return ret;
}
int xstat(const char *pathname, struct stat *buf) {
int ret = stat(pathname, buf);
if (ret == -1) {
@@ -292,7 +276,7 @@ int xsymlink(const char *target, const char *linkpath) {
int xmount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data) {
int ret = mount(source, target, filesystemtype, mountflags, data);
int ret = mount(source, target, filesystemtype, MS_SILENT | mountflags, data);
if (ret == -1) {
PLOGE("mount %s->%s", source, target);
}
@@ -331,10 +315,10 @@ int xmkdir(const char *pathname, mode_t mode) {
return ret;
}
int xmkdir_p(const char *pathname, mode_t mode) {
int ret = mkdir_p(pathname, mode);
int xmkdirs(const char *pathname, mode_t mode) {
int ret = mkdirs(pathname, mode);
if (ret == -1) {
PLOGE("mkdir_p %s", pathname);
PLOGE("mkdirs %s", pathname);
}
return ret;
}

View File

@@ -1,28 +1,36 @@
# Magisk Documentations
(Updated on 2017.9.28) ([Changelog](changelog.md))
(Updated on 2018.1.8) ([Changelog](changelog.md))
## Table of Contents
- [Introduction](#introduction)
- [Procedure Diagram](https://cdn.rawgit.com/topjohnwu/Magisk/cc1809688299f1f8b5db494a234850852712c0c9/docs/procedures.html)
- [Magisk Details](details.md)
- [Tips and Tricks](tips.md)
- [OTA Installation Tips](tips.md#ota-installation-tips)
The following are for developers
- [Procedure Diagram](https://cdn.rawgit.com/topjohnwu/Magisk/7d1082b1cb91db90ed0a29d8b092723fc3d69c58/docs/procedures.html)
- [Magisk Details](details.md)
- [Boot Stages](details.md#boot-stages)
- [Magic Mount Details](details.md#magic-mount-details)
- [Simple Mount Details](details.md#simple-mount-details)
- [Available Applets](applets.md)
- [magisk](applets.md#magisk)
- [su](applets.md#su)
- [resetprop](applets.md#resetprop)
- [magiskpolicy](applets.md#magiskpolicy)
- [magiskhide](applets.md#magiskhide)
- [Modules and Repos](module_repo.md)
- [Modules and Templates](module_repo.md#magisk-module-format)
- [Submit Modules to Repo](module_repo.md#submit-your-module-to-magisk-modules-repo)
- [Available Tools](tools.md)
- [magiskboot](tools.md#magiskboot)
- [magiskinit](tools.md#magiskinit)
- [magiskpolicy](tools.md#magiskpolicy)
- [magisk](tools.md#magisk)
- [su](tools.md#su)
- [resetprop](tools.md#resetprop)
- [magiskhide](tools.md#magiskhide)
- [Modules](modules.md)
- [Modules and Templates](modules.md#magisk-module-format)
- [Submit Modules to Repo](https://github.com/topjohnwu/Magisk_Repo_Submissions)
- [Tips and Tricks](tips.md)
- [OTA Installation Tips](tips.md#ota-installation-tips)
- [Remove Files](tips.md#remove-files)
- [Remove Folders](tips.md#remove-folders)
## Introduction
Magisk is a suite of open source tools for devices running Android version higher than 5.0 Lollipop (API 21). It establishes an environment which covers most Android aftermarket customization needs, such as root, boot scripts, SELinux patches, dm-verity/forceencrypt patches etc.. Furthermore, Magisk also provides a **Systemless Interface** to alter the system (or vendor) arbitrarily while the actual partitions stay completely intact, all of which accomplished by only patching the boot image, and adding some files into `/data`. With its systemless nature along with several other hacks, Magisk can hide modifications from device integrity verifications, one of the main target is to hide from [Google's SafetyNet API](https://developer.android.com/training/safetynet/index.html).
Magisk is a suite of open source tools for devices running Android version higher than 5.0 Lollipop (API 21). It establishes an environment which covers most stuffs you need for Android customization, such as root, boot scripts, SELinux patches, AVB2.0 / dm-verity / forceencrypt patches etc..
Furthermore, Magisk provides a **Systemless Interface** to alter the system (or vendor) arbitrarily while the actual partitions stay completely intact, all of which accomplished by only patching the boot image. With its systemless nature along with several other hacks, Magisk can hide modifications from nearly any existing system integrity verifications, one of the main target is to hide from [Google's SafetyNet API](https://developer.android.com/training/safetynet/index.html).

View File

@@ -1,166 +0,0 @@
## Available Applets
Magisk has a core binary which acts as a multi-call program with many applets. Here is an introduction to all available applets.
### magisk
The magisk binary itself provides a lot of utility functions when called with the name `magisk`. They are used in both Magisk installation and module installation. The entry point for `init` to invoke magisk's boot procedures are also listed here.
Command help message:
```
Usage: magisk [applet [arguments]...]
or: magisk [options]...
Options:
-c print current binary version
-v print running daemon version
-V print running daemon version code
--list list all availible applets
--install [SOURCE] DIR symlink all applets to DIR. SOURCE is optional
--createimg IMG SIZE create ext4 image. SIZE is interpreted in MB
--imgsize IMG report ext4 image used/total size
--resizeimg IMG SIZE resize ext4 image. SIZE is interpreted in MB
--mountimg IMG PATH mount IMG to PATH and prints the loop device
--umountimg PATH LOOP unmount PATH and delete LOOP device
--[boot stage] start boot stage service
--unlock-blocks set BLKROSET flag to OFF for all block devices
Supported boot stages:
post-fs, post-fs-data, service
Supported applets:
su, resetprop, magiskpolicy, supolicy, magiskhide
```
### su
The MagiskSU entrypoint. Call `su` to gain a root shell.
Command help message:
```
Usage: su [options] [--] [-] [LOGIN] [--] [args...]
Options:
-c, --command COMMAND pass COMMAND to the invoked shell
-h, --help display this help message and exit
-, -l, --login pretend the shell to be a login shell
-m, -p,
--preserve-environment do not change environment variables
-s, --shell SHELL use SHELL instead of the default /system/bin/sh
-u display the multiuser mode and exit
-v, --version display version number and exit
-V display version code and exit,
this is used almost exclusively by Superuser.apk
-mm, -M,
--mount-master run in the global mount namespace,
use if you need to publicly apply mounts
```
Note: even though the `-Z, --context` option is not listed above, it actually still exists. However MagiskSU will silently ignore the option since it's not needed anymore. It is still left over because some apps still request root shell with specific contexts as an option.
### resetprop
An advanced system prop manipulation utility; you can arbitrarily alter system props using this tool. Here's some background knowledge:
> System props are stored in a hybrid trie/binary tree data structure in memory; it was originally designed to only support adding nodes, and no nodes should be removed. Props can be read by many processes (e.g. via the `getprop` command); however, only the `init` process have write access to the property data. `init` provides a `property_service` to accept property update requests, so all property changes are monitored and controlled by `init` Restrictions such as **read-only** props (props that starts with `ro.`), which can only be set once and cannot be changed afterwards, is therefore implemented in `init`.
**resetprop** acts just like `init`: directly access the data structure, bypassing the whole `property_service` part. Doing so, we gain **arbitrary modification** power, including altering read-only props and deleting properties. Delete properties, which was stated *"forbidden"* in the data structure, is implemented through some tricks in the data structure.
One subtle thing to be aware of is that if we change props by directly modifying the data structure, `on property:foo=bar` triggers registered in `*.rc` scripts will not be triggered properly. This may be a good thing or a bad thing, depending on what behavior you expect. I made the default behavior to match the original setprop command, which **WILL** trigger events, but of course I provide a flag (`-n`) to disable it if you need this special behavior.
Command help message:
```
Usage: resetprop [options] [args...]
Options:
-v show verbose output
-n only modify property in memory
resetprop NAME VALUE set property entry NAME with VALUE
resetprop --file FILE load props from FILE
resetprop --delete NAME remove prop entry NAME
```
### magiskpolicy
(This tool is aliased to `supolicy` for compatibility)
A tool to patch `sepolicy`. **magiskpolicy** also comes with built-in rules to unleash restrictions to make Magisk work properly. `sepolicy` is a compiled binary containing SELinux rules; we directly patch rules in the binary format since we don't have access to the SELinux policy source (`*.te`) files.
The Magisk daemon itself, the root shell, and all processes spawned from the daemon and root shell are all running in the context `u:r:su:s0`. This context is not only patched to be permissive, but also patched to allow any transition from `u:r:su:s0` to any domain. This was done because Samsung devices do not support permissive out of the box.
The built in patches are split to 3 parts: minimal, medium, and large. The full patch will result in a huge policy file, which might cause the `sepolicy` file unable to fit in `boot.img`.
- The minimal patch is just enough to start Magisk daemon and allow the daemon to further patch the policy during boot time (which is called **live patch**). It is done at installation and directly into `boot.img`.
- The medium patch covers most common operations, and is live patched as soon as Magisk daemon is started (blocking boot process).
- The large patch contains the full patch. Due to the concern of greatly increasing the boot time, it is designed to run in the background until it's joined in the non-blocking late_start bootstage.
What this all means is that **only late_start service mode is guaranteed to run in a fully patched environment**. If any script is not time critical, it is **highly recommended to run those scripts in late_start service mode**.
Command help message:
```
Usage: magiskpolicy [--options...] [policystatements...]
Options:
--live directly load patched policy to device
--minimal minimal patches, used for boot image patches
--load <infile> load policies from <infile>
(load from live policies if not specified)
--save <outfile> save policies to <outfile>
One policy statement should be treated as one parameter;
this means a full policy statement should be enclosed in quotes;
multiple policy statements can be provided in a single command
The statements has a format of "<action> [args...]"
Use '*' in args to represent every possible match.
Collections wrapped in curly brackets can also be used as args.
Supported policy statements:
Type 1:
"<action> source-class target-class permission-class permission"
Action: allow, deny, auditallow, auditdeny
Type 2:
"<action> source-class target-class permission-class ioctl range"
Action: allowxperm, auditallowxperm, dontauditxperm
Type 3:
"<action> class"
Action: create, permissive, enforcing
Type 4:
"attradd class attribute"
Type 5:
"typetrans source-class target-class permission-class default-class (optional: object-name)"
Notes:
- typetrans does not support the all match '*' syntax
- permission-class cannot be collections
- source-class and target-class can also be attributes
Example: allow { source1 source2 } { target1 target2 } permission-class *
Will be expanded to:
allow source1 target1 permission-class { all-permissions }
allow source1 target2 permission-class { all-permissions }
allow source2 target1 permission-class { all-permissions }
allow source2 target2 permission-class { all-permissions }
```
### magiskhide
This is the CLI to control the state of MagiskHide.
Command help message:
```
Usage: magiskhide [--options [arguments...] ]
Options:
--enable Start magiskhide
--disable Stop magiskhide
--add PROCESS Add PROCESS to the hide list
--rm PROCESS Remove PROCESS from the hide list
--ls Print out the current hide list
```

View File

@@ -4,3 +4,5 @@
- 2017.9.28
- Update applets info to Magisk v14.1
- Add OTA tips
- 2017.1.8
- Update to Magisk v15.2

View File

@@ -2,59 +2,58 @@
If you are working on complicated projects, you shall need more control to the whole process. Magisk can run scripts in different boot stages, so you can fine tune exactly what you want to do. It's recommended to read this documentation along with the procedure graph.
- post-fs mode
- **This stage is BLOCKING. Boot process will NOT continue until everything is done, or 20 seconds has passed**
- Happens after most partitions are mounted, except `/data`
- Magisk will bind mount files under `/cache/magisk_mount/system` to corresponding paths
- **This stage is BLOCKING. Boot process will NOT continue until everything is done, or 10 seconds has passed**
- Happens after most partitions are mounted. `/data` might not be available since `vold` is not started yet
- Magisk will bind mount files under `/cache/magisk_mount/system` and `/cache/magisk_mount/vendor`
- It is only **Simple Mount**, which means it will replace existing files, but cannot add/remove files.
- This part is mostly deprecated (reasons in details)
- post-fs-data mode
- **This stage is BLOCKING. Boot process will NOT continue until everything is done, or 60 seconds has passed**
- **This stage is BLOCKING. Boot process will NOT continue until everything is done, or 10 seconds has passed**
- Happens after `/data` is ready (including the case when `/data` is encrypted)
- Happens before Zygote and system servers are started (which means pretty much everything)
- Mirrors will be mounted. These mirrors play a critical role in **Magic Mount**
- `/data/magisk.img` will be merged, trimmed, and mounted to `/magisk`
- Magisk will run scripts under `/magisk/.core/post-fs-data.d`
- Magisk will run scripts: `/magisk/$MODID/post-fs-data.sh` (placed in each module directory)
- `/data/adb/magisk.img` will be merged, trimmed, and mounted to `MOUNTPOINT=/sbin/.core/img`
- Magisk will run scripts under `$MOUNTPOINT/.core/post-fs-data.d`
- Magisk will run scripts: `$MOUNTPOINT/$MODID/post-fs-data.sh` (placed in each module directory)
- Magisk will finally **Magisk Mount** module files
- late_start service mode
- **This stage is NON-BLOCKING, it will run in parallel with other processes**
- Happens when class late_start is started
- Put time consuming but non time critical tasks here. Boot process will be stuck if it took too long to finish your tasks in previous modes
- SELinux is guaranteed to be fully patched in this stage; **it is recommended to run most scripts in this stage**, unless your scripts require some time critical operations
- Magisk will run scripts under `/magisk/.core/service.d`
- Magisk will run scripts: `/magisk/$MODID/service.sh` (placed in each module directory)
- Happens when class late_start is triggered
- The daemon will wait for the full `sepolicy` patch before running this stage, so SELinux is guaranteed to be fully patched
- Put time consuming scripts here. Boot process will get stuck if it took too long to finish your tasks in `post-fs-data`
- **It is recommended to run all scripts in this stage**, unless your scripts requires doing stuffs before Zygote is started
- Magisk will run scripts under `$MOUNTPOINT/.core/service.d`
- Magisk will run scripts: `$MOUNTPOINT/$MODID/service.sh` (placed in each module directory)
## Magic Mount Details
### Terminology
- **Item**: A folder, file, or symbolic link
- **Leaf**: The very end of a directory structure tree, can be either a file or symbolic link
- **Leaf**: An item that is on the very end of a directory structure tree. It can be either a file or symbolic link
- **`$MODPATH`**: A variable to represent the path of a module folder
- **Source item**: An item under `$MODPATH/system`, for example, `$MODPATH/system/build.prop` is a source item
- **Existing item**: An item under `/system`, for example, `/system/bin/app_process` is an existing item
- **Target item**: A corresponding item of a source item. For example, the target item of `$MODPATH/system/build.prop` is `/system/build.prop`
- **Source item**: An item under `$MODPATH/system`, for example, `$MODPATH/system/bin/app_process32` is a source item
- **Existing item**: An item in the actual filesystem, for example, `/system/bin/app_process32` is an existing item
- **Target item**: The corresponding item of a source item. For example, the target item of `$MODPATH/system/bin/app_process32` is `/system/bin/app_process32`
Note: A target item does not imply it is an existing item. A target item might not exist in the actual `/system`
Note: A target item **does not** imply it is an existing item. A target item might not exist in the actual filesystem
### Policies
- For a source leaf: if its target item is also an existing item, the existing item will be replaced with the source leaf
- For a source leaf: if its target item is not an existing item, the source leaf will be added to the path of its target item
- For any existing item that's not a target item, it will stay intact
Above is the rule of thumb. Basically it means that Magic Mount merges the files from `$MODPATH/system` into the real `/system`. A simpler way to understand is to think as it dirty copies the contents from `$MODPATH/system` into `/system`.
Above is the rule of thumb. Basically it means that Magic Mount merges the two folders, `$MODPATH/system` into `/system`. A simpler way to understand is to think as the items is dirty copied from `$MODPATH/system` into `/system`.
However, an addition rule will override the above policies:
- For a source folder containing the file `.replace`, the source folder will be treated as if it is a source leaf. That is, the items within the target folder will be completely discarded, and the target folder will be replaced with the source folder.
- For a source folder containing the file `.replace`, the source folder will be treated as if it is a leaf. That is, the items within the target folder will be completely discarded, and the target folder will be replaced with the source folder.
Directories containing a file named `.replace` will NOT be merged into the system. It will directly replace the target directory. A simpler way to understand is to think as if it wipes the target folder, and then copies the whole folder to the target path.
Directories containing a file named `.replace` will **NOT** be merged, instead it directly replaces the target directory. A simpler way to understand is to think as if it wipes the target folder, and then copies the whole folder to the target path.
### Notes
- Sometimes, completely replacing a folder is inevitable. For example you want to replace `/system/priv-app/SystemUI` in your stock rom. In stock roms, system apps usually comes with pre-optimized files. If your replacement `SystemUI.apk` is deodexed (which is most likely the case), you would want to replace the whole `/system/priv-app/SystemUI` to make sure the folder only contains the modified `SystemUI.apk` and **NOT** merge with the pre-optimized files.
- If you want to replace files in `/vendor`, please place it under `$MODPATH/system/vendor`. Magisk will handle both cases, whether the vendor partition is separated or not under-the-hood, developers don't need to bother.
- Sometimes, completely replacing a folder is inevitable. For example you want to replace `/system/priv-app/SystemUI` in your stock rom. In stock roms, system apps usually comes with pre-optimized files. If your replacement `SystemUI.apk` is deodexed (which is most likely the case), you would want to replace the whole `/system/priv-app/SystemUI` to make sure the folder only contains the modified `SystemUI.apk` without the pre-optimized files.
- If you are using the [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template), you can create a list of folders you want to replace in the file `config.sh`. The installation scripts will handle the creation of `.replace` files into the listed folders for you.
- Adding non-existing target items is a relatively expensive operation. Magisk would need to do **MANY** under-the-hood tasks to achieve it. Replacing a whole folder is recommended if viable, it reduces the complexity of the construction of the mounting tree and could speed up the booting time
## Simple Mount Details
Some files require to be mounted much earlier in the boot process, currently known are bootanimation and some libs (most users won't change them). You can simply place your modified files into the corresponding path under `/cache/magisk_mount`. At boot time, Magisk will **clone all the attributes from the target file**, which includes selinux context, permission mode, owner, group. It'll then bind mount the file to the target. This means you don't need to worry about the metadatas for files placed under `/cache/magisk_mount`: copy the file to the correct place, reboot then you're done!
(Note: this part is mostly deprecated, since starting with devices using A/B partitions, there is no longer a dedicated partition for cache because OTAs are applied live at boot. Instead, `/cache` now points to `/data/cache`, which means `post-fs` mode does not have access to `/cache` anymore)
This mode does not feature the same complex Magic Mount implementation, it will mount a source leaf to an existing target item under `/system`.
For example, you want to replace `/system/media/bootanimation.zip`, copy your new boot animation zip to `/cache/magisk_mount/system/media/bootanimation.zip,` Magisk will mount your files in the next reboot.
Some files require to be mounted much earlier in the boot process, currently known are bootanimation and some libs (most users won't change them). You can simply place your modified files into the corresponding path under `/cache/magisk_mount`. For example, you want to replace `/system/media/bootanimation.zip`, copy your new boot animation zip to `/cache/magisk_mount/system/media/bootanimation.zip`, and Magisk will mount your files in the next reboot. Magisk will **clone all the attributes from the target file**, which includes selinux context, permission mode, owner, group. This means you don't need to worry about the metadata for files placed under `/cache/magisk_mount`: just copy the file to the correct place, reboot then you're done!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

BIN
docs/images/restore_img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

View File

@@ -1,76 +0,0 @@
# Magisk Modules and Online Repo
## Magisk Module Format
The Magisk module is a folder under `magisk`, which has a structure as described below:
```
magisk
├── .
├── .
├── a_module <--- The ID of the module, should match with module.prop
│   ├── auto_mount <--- If this file exists, auto mount is enabled
│   ├── disable <--- If this file exists, the module is disabled
│   ├── module.prop <--- This files stores the indentity and properties of the module
│   ├── post-fs-data.sh <--- This script will be executed in post-fs-data
│   ├── remove <--- If this file exists, the module will be removed next reboot
│   ├── service.sh <--- This script will be executed in late_start service
│   ├── system.prop <--- This file will be loaded as system props
│   ├── system <--- If auto mount is enabled, Magisk will "Magic Mount" this folder
│   │   ├── app
│   │   ├── .
│   │   └── .
│   ├── vendor <--- Auto generated. A symlink to $MODID/system/vendor
│   ├── . <--- Any other files/folders are allowed
│   └── .
├── another_module
│   ├── .
│   └── .
├── .
├── .
```
## Magisk Module Template
The **Magisk Module Template** is hosted **[here](https://github.com/topjohnwu/magisk-module-template)**.
It is a template to create a flashable zip to install Magisk Modules. It is created to be simple to use so that anyone can create their own modules easily. The template itself contains minimal scripting for installation; most of the functions are located externally in [util_functions.sh](https://github.com/topjohnwu/Magisk/blob/master/scripts/util_functions.sh), which will be installed along with Magisk, and can be upgraded through a Magisk upgrade without the need of a template update.
The template should meet most modules' needs. Add files into `system`, which will be cloned into `/system` by Magisk after installing the module, and in addition to module files, `system.prop`, `post-fs-data.sh`, `service.sh` are also installable through this template.
Here are some files you would want to know:
- `config.sh`: A simple script used as a configuration file for the actual installation file to correctly install your module. It is the place you can select which features your module needs/disables.
- `module.prop`: This file contains your module's indentity and properties, including name and versions etc.. This file will be used to identify your module on an actual device and in the [Magisk Modules Repo](https://github.com/Magisk-Modules-Repo)
- `common/*`: These files will be installed to the module with the correspond role
- `META-INF/com/google/android/update-binary`: The actual installation script. Modify this file for advanced custom behavior
## Create a Magisk Module With The Template
1. Clone / download [this repo](https://github.com/topjohnwu/magisk-module-template)
1. Open `config.sh` and carefully read the fully documented file. Follow the instructions within the script
1. You should at least have `config.sh` and `module.prop` modified
1. Directly zip all files; the result zip file is a flashable zip that can be used in both Magisk Manager and custom recoveries
1. Please check [**Notes**](#notes) for several precautions
## Submit Your Module to Magisk Modules Repo
If you want to share your module with others, you can submit your modules to [Magisk Modules Repo](https://github.com/Magisk-Modules-Repo). You would need some basic `git` knowledge here.
1. Create a module as stated above, and test if it works properly
1. Fork [this repo](https://github.com/topjohnwu/magisk-module-template) to your account
1. Commit and push your changes to your forked repo
1. Open an issue in [topjohnwu/Magisk_Repo_Central](https://github.com/topjohnwu/Magisk_Repo_Central/issues/new) with your repo link
1. I will review your module, and once accepted, your repo should be cloned into [Magisk-Modules-Repo](https://github.com/Magisk-Modules-Repo)
1. You should receive an email to become the collaborator so you can edit the repo in the future.
#### Once your module is live on the Modules Repo, the description of your repo should be the ID of your module. Please do NOT change the description, repeat, do NOT change the description.
![repo_description.png](images/repo_description.png)
## Notes
- The Module Template depends on external scripts, be aware of the minimal required Magisk version of the template.
- **Windows users please check here!!** The line endings of all text files should be in the **Unix format**. Please use advanced text editors like Sublime, Atom, Notepad++ etc. to edit **ALL** text files, **NEVER** use Windows Notepad.
- In `module.prop`, `version` can be an arbitrary string, so any fancy version name (e.g. ultra-beta-v1.1.1.1) is allowed. However, `versionCode` **MUST** be an integer. The value is used for version comparison.
- Make sure your module ID **does not contain any spaces**.
## Notes For Repo Developers
- Magisk Manager monitors all repo's `master` branch. Any changes to the branch `master` will be reflected to all users immediately. If you are working on an update for a module, please work on another branch, make sure it works, then finally merge the changes back to `master`.
- Once you finished upgrading your repo, increase at least the `versionCode` in `module.prop`. Magisk Manager uses this value to compare with the local installed module to determine whether an update is availible.
- The description of your repo should be the same as your module ID. If you changed your description, Magisk Manager will fail to identify your repo, and cannot relate installed module to the online repo together.

49
docs/modules.md Normal file
View File

@@ -0,0 +1,49 @@
# Magisk Modules
## Magisk Module Format
A Magisk module is a folder placed in the root folder in `magisk.img`, which has a structure as described below:
```
$MOUNTPOINT
├── .
├── .
├── $MODID <--- The ID of the module, should match with module.prop
│   ├── auto_mount <--- If this file exists, auto mount is enabled
│   ├── disable <--- If this file exists, the module is disabled
│   ├── module.prop <--- This files stores the identity and properties of the module
│   ├── post-fs-data.sh <--- This script will be executed in post-fs-data
│   ├── remove <--- If this file exists, the module will be removed next reboot
│   ├── service.sh <--- This script will be executed in late_start service
│   ├── system.prop <--- This file will be loaded as system props
│   ├── system <--- If auto mount is enabled, Magisk will "Magic Mount" this folder
│   │   ├── .
│   │   ├── .
│   │   └── .
│   ├── vendor <--- Auto generated. A symlink to $MODID/system/vendor
│   ├── . <--- Any other files/folders are allowed
│   └── .
├── another_module
│   ├── .
│   └── .
├── .
├── .
```
You are not required to use my Magisk Module Template to create a module. As long as you place files with the structure above, it will be recognized as a module.
## Magisk Module Template
The **Magisk Module Template** is hosted **[here](https://github.com/topjohnwu/magisk-module-template)**.
It is a template to create a flashable zip to install Magisk Modules. It is designed to be simple to use so that anyone can create their own modules easily. The template itself contains minimal scripting for installation; most of the functions are located externally in [util_functions.sh](https://github.com/topjohnwu/Magisk/blob/master/scripts/util_functions.sh), which will be installed along with Magisk, and can be upgraded through a Magisk upgrade without the need of a template update.
Here are some files you would want to know:
- `config.sh`: A simple script used as a configuration file. It is the place to configure which features your module needs/disables. A detailed instructions on how to use the template is also written in this file.
- `module.prop`: This file contains your module's indentity and properties, including name and versions etc.. This file will be used to identify your module on an actual device and in the [Magisk Modules Repo](https://github.com/Magisk-Modules-Repo)
- `common/*`: Boot stage scripts and `system.prop`
- `META-INF/com/google/android/update-binary`: The actual installation script. Modify this file for advanced custom behavior
And here are some notes to be aware of:
- The template depends on external Magisk scripts, please specify the correct `minMagisk` value in `module.prop` with the template version your module is based on, or the minimum Magisk version your module is tested on.
- **Windows users please check here!!** The line endings of all text files should be in the **Unix format**. Please use advanced text editors like Sublime, Atom, Notepad++ etc. to edit **ALL** text files, **NEVER** use Windows Notepad.
- In `module.prop`, `version` can be an arbitrary string, so any fancy version name (e.g. `ultra-beta-v1.1.1.1`) is allowed. However, `versionCode` **MUST** be an integer. The value is used for version comparison.
- Make sure your module ID **does not contain any spaces**.

File diff suppressed because one or more lines are too long

View File

@@ -10,8 +10,8 @@ Magisk do modifications systemless-ly, which means applying official OTAs is muc
#### Prerequisites
1. Please disable *Automatic system updates* in developer options, so it won't install OTAs without your acknowledgement.
<img src="images/disable_auto_ota.png" width="250">
1. When an OTA is available, please go to Magisk Manager → Uninstall → Restore Stock Boot. **Do not reboot immediately or you will have Magisk uninstalled.** This will restore your boot back to 100% untouched stock boot image in order to pass boot verification. **This step is required before doing any of the following steps written below!**
<img src="images/restore_boot.png" width="250">
1. When an OTA is available, please go to Magisk Manager → Uninstall → Restore Images. **Do not reboot immediately or you will have Magisk uninstalled.** This will restore your boot (or dtbo if available) back to 100% untouched stock images in order to pass verifications. **This step is required before doing any of the following steps written below!**
<img src="images/restore_img.png" width="250">
#### Devices with A/B Partitions
(Includes Pixel family)
@@ -36,7 +36,7 @@ The [FlashFire](https://play.google.com/store/apps/details?id=eu.chainfire.flash
1. Press the big **Flash** button, after a few minutes it should reboot updated with Magisk installed.
#### Other Devices - General Case
Unfortunately, there are no real good ways to apply OTAs on all devices. Also, the tutorial provided below will not preserve Magisk - you will have to manually re-root your device after the upgrade, and this will require PC access. Here I share my personal experience with my daily driver - HTC U11.
Unfortunately, there are no real good ways to apply OTAs on all devices. Also, the tutorial provided below will not preserve Magisk - you will have to manually re-root your device after the upgrade, and this will require PC access. Here I share my personal experience with HTC U11.
1. To properly install OTAs, you should have your stock recovery installed on your device. If you have custom recovery installed, you can restore it from your previous backup, or dumps found online, or factory images provided by OEMs.
If you decide to start by installing Magisk without touching your recovery partition, you have a few choices, either way you will end up with a Magisk rooted device, but recovery remain stock untouched:
@@ -47,7 +47,7 @@ If you decide to start by installing Magisk without touching your recovery parti
1. Once it's done you will be left with an upgraded, 100% stock, un-rooted device. You will have to manually flash Magisk back. Consider using the methods stated in step 1. to flash Magisk without touching the recovery partition if you want to receive stock OTAs frequently.
## Remove Files
How to efficiently remove a file systemless-ly? To actually make the file **disappear** is complicated (possible, not worth the effort). **Replacing it with a dummy file should be good enough**! Create an empty file with the same name and place it in the same path within a module, it shall replace your target file with a dummy file.
How to remove a file systemless-ly? To actually make the file **disappear** is complicated (possible, not worth the effort). **Replacing it with a dummy file should be good enough**! Create an empty file with the same name and place it in the same path within a module, it shall replace your target file with a dummy file.
## Remove Folders
Same as mentioned above, actually making the folder to **disappear** is not worth the effort. **Replacing it with an empty folder should be good enough**! A handy trick for module developers using [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template) is to add the folder you want to remove into the `REPLACE` list within `config.sh`. If your module doesn't provide a correspond folder, it will create an empty folder, and automatically add `.replace` into the empty folder so the dummy folder will properly replace the one in `/system`.

287
docs/tools.md Normal file
View File

@@ -0,0 +1,287 @@
## Available Tools
Magisk comes with a lot of tools for installation, programs running as a daemon, and utilities for developers. This documentation covers 3 binaries, and many more tools are available as applets. The relation between tools are shown below:
```
magiskboot /* binary */
magiskinit /* binary */
magiskpolicy -> magiskinit
supolicy -> magiskinit /* alias of magiskpolicy */
magisk /* binary */
magiskhide -> magisk
resetprop -> magisk
su -> magisk
```
### magiskboot
A tool to unpack / repack boot images, parse and patch cpio and dtbs, hex patch binaries, compress / decompress with multiple algorithms. It is used to install Magisk into boot images.
`magiskboot` natively supports (which means it does not call external tools) all popular compression methods including `gzip` (used everywhere for compressing kernel and ramdisk), `lz4` (used to compress kernel in modern devices like Pixel), `lz4_legacy` (legacy LZ4 block format with special metadata used [only on LG](https://events.static.linuxfound.org/sites/events/files/lcjpcojp13_klee.pdf) to compress kernel), `lzma` (LZMA1 algorithm natively supported in Linux kernel, used in some custom kernel to compress ramdisk), `xz` (LZMA2 algorithm, very high compression rate, used in Magisk for high compression mode and storing binaries), and `bzip2` (used in desktop Linux boot images to create bzImage, haven't seen on Android yet).
The concept of `magiskboot` is to keep the images as intact as possible. For unpacking, it extracts the large chunks of data (kernel, ramdisk, second, dtb, extra etc.) and decompress them if possible. When repacking a boot image, the original boot image has to be provided so it can use the original headers (including MTK specific headers) with only changing the necessary entries such as the data chunk sizes, and re-compress all data with the original compression method. The same concept also applies to CPIO patching: it does not extract all files, modify in file system, archive all files back to cpio as usually done to create Linux `initramfs`, instead we do modifications directly in the cpio level in memory without involving any data extraction.
Command help message:
```
Usage: magiskboot <action> [args...]
Supported actions:
--parse <bootimg>
Parse <bootimg> only, do not unpack. Return values:
0:OK 1:error 2:insufficient boot partition size
3:chromeos 4:ELF32 5:ELF64
--unpack <bootimg>
Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb), (extra) into
the current directory. Return value is the same as --parse
--repack <origbootimg> [outbootimg]
Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory
to [outbootimg], or new-boot.img if not specified.
It will compress ramdisk.cpio with the same method used in <origbootimg>,
or attempt to find ramdisk.cpio.[ext], and repack directly with the
compressed ramdisk file
--hexpatch <file> <hexpattern1> <hexpattern2>
Search <hexpattern1> in <file>, and replace with <hexpattern2>
--cpio <incpio> [commands...]
Do cpio commands to <incpio> (modifications are done directly)
Each command is a single argument, use quotes if necessary
Supported commands:
rm [-r] ENTRY
Remove ENTRY, specify [-r] to remove recursively
mkdir MODE ENTRY
Create directory ENTRY in permissions MODE
ln TARGET ENTRY
Create a symlink to TARGET with the name ENTRY
mv SOURCE DEST
Move SOURCE to DEST
add MODE ENTRY INFILE
Add INFILE as ENTRY in permissions MODE; replaces ENTRY if exists
extract [ENTRY OUT]
Extract ENTRY to OUT, or extract all entries to current directory
test
Test the current cpio's patch status. Return value:
0:stock 1:Magisk 2:other (phh, SuperSU, Xposed)
patch KEEPVERITY KEEPFORCEENCRYPT
Ramdisk patches. KEEP**** are boolean values
backup ORIG [SHA1]
Create ramdisk backups from ORIG
SHA1 of stock boot image is optional
restore
Restore ramdisk from ramdisk backup stored within incpio
magisk ORIG HIGHCOMP KEEPVERITY KEEPFORCEENCRYPT [SHA1]
Do Magisk patches and backups all in one step
Create ramdisk backups from ORIG
HIGHCOMP, KEEP**** are boolean values
SHA1 of stock boot image is optional
sha1
Print stock boot SHA1 if previously stored
--dtb-<cmd> <dtb>
Do dtb related cmds to <dtb> (modifications are done directly)
Supported commands:
dump
Dump all contents from dtb for debugging
test
Check if fstab has verity/avb flags. Return value:
0:no flags 1:flag exists
patch
Search for fstab and remove verity/avb
--compress[=method] <infile> [outfile]
Compress <infile> with [method] (default: gzip), optionally to [outfile]
<infile>/[outfile] can be '-' to be STDIN/STDOUT
Supported methods: gzip xz lzma bzip2 lz4 lz4_legacy
--decompress <infile> [outfile]
Detect method and decompress <infile>, optionally to [outfile]
<infile>/[outfile] can be '-' to be STDIN/STDOUT
Supported methods: gzip xz lzma bzip2 lz4 lz4_legacy
--sha1 <file>
Print the SHA1 checksum for <file>
--cleanup
Cleanup the current working directory
```
### magiskinit
This tool is created to unify Magisk support for both legacy "normal" devices and new `skip_initramfs` devices. The compiled binary will replace `init` in the ramdisk, so things could be done even before `init` is started.
`magiskinit` is responsible for constructing a proper rootfs on devices which the actual rootfs is placed in the system partition instead of ramdisk in `boot.img`, such as the Pixel familiy and most Treble enabled devices, or I like to call it `skip_initramfs` devices: it will parse kernel cmdline, mount sysfs, parse through uevent files to make the system (or vendor if available) block device node, then copy rootfs files from system. For normal "traditional" devices, it will simply swap `init` back to the original one and continue on to the next stage.
With a proper rootfs, `magiskinit` goes on and does all pre-init operations to setup a Magisk environment. It patches rootfs on the fly, providing fundamental support such as patching `init`, `init.rc`, run preliminary `sepolicy` patches, and extracts `magisk` and `init.magisk.rc` (these two files are embedded into `magiskinit`). Once all is done, it will spawn another process (`magiskinit_daemon`) to asynchronously run a full `sepolicy` patch, then starts monitoring the main Magisk daemon to make sure it is always running (a.k.a invincible mode); at the same time, it will execute the original `init` to hand the boot process back.
### magiskpolicy
(This tool is aliased to `supolicy` for compatibility with SuperSU's sepolicy tool)
This tool is an applet of `magiskinit`: once `magiskinit` had finished its mission in the pre-init stage, it will preserve an entry point for `magiskpolicy`. This tool could be used for advanced developers messing with `sepolicy`, a compiled binary containing SELinux rules. Normally Linux server admins directly modifies the SELinux policy sources (`*.te`) and recompile the `sepolicy` binary, but here we directly patch the binary file since we don't have access to the sources.
All processes spawned from the Magisk daemon, including root shells and all its forks, are running in the context `u:r:su:s0`. Magisk splits the built in patches into 2 parts: preliminary and full
- The preliminary patch should allow all Magisk internal procedures to run properly (can be done manually by the `--magisk` option). It also contains quite a few additional patches so most scripts can run in the daemon before the full patch is done
- The full patch adds the rule `allow su * * *` on top of the preliminary rules. This is done because stock Samsung ROMs do not support permissive; adding this rule makes the domain effectively permissive. Due to the concern of greatly increasing the boot time, the Magisk daemon will not wait for this patch to finish until the boot stage `late_start` triggers. What this means is that **only `late_start` service mode is guaranteed to run in a fully patched environment**. For non-Samsung devices it doesn't matter because `u:r:su:s0` is permissive anyways, but for full compatibility, it is **highly recommended to run boot scripts in `late_start` service mode**.
Command help message:
```
Usage: magiskpolicy [--options...] [policystatements...]
Options:
--live directly apply patched policy live
--magisk built-in rules for a Magisk selinux environment
--load FILE load policies from <infile>
--save FILE save policies to <outfile>
If no input file is specified, it will load from current policies
If neither --live nor --save is specified, nothing will happen
One policy statement should be treated as one parameter;
this means a full policy statement should be enclosed in quotes;
multiple policy statements can be provided in a single command
The statements has a format of "<action> [args...]"
Use '*' in args to represent every possible match.
Collections wrapped in curly brackets can also be used as args.
Supported policy statements:
Type 1:
"<action> source-class target-class permission-class permission"
Action: allow, deny, auditallow, auditdeny
Type 2:
"<action> source-class target-class permission-class ioctl range"
Action: allowxperm, auditallowxperm, dontauditxperm
Type 3:
"<action> class"
Action: create, permissive, enforcing
Type 4:
"attradd class attribute"
Type 5:
"typetrans source-class target-class permission-class default-class (optional: object-name)"
Notes:
- typetrans does not support the all match '*' syntax
- permission-class cannot be collections
- source-class and target-class can also be attributes
Example: allow { source1 source2 } { target1 target2 } permission-class *
Will be expanded to:
allow source1 target1 permission-class { all-permissions }
allow source1 target2 permission-class { all-permissions }
allow source2 target1 permission-class { all-permissions }
allow source2 target2 permission-class { all-permissions }
```
### magisk
The magisk binary contains all the magic of Magisk, providing all the features Magisk has to offer. When called with the name `magisk`, it works as an utility tool with many helper functions, and also the entry point for `init` to start Magisk services. These helper functions are extensively used by the [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template) and Magisk Manager.
Command help message:
```
Usage: magisk [applet [arguments]...]
or: magisk [options]...
Options:
-c print current binary version
-v print running daemon version
-V print running daemon version code
--list list all available applets
--install [SOURCE] DIR symlink all applets to DIR. SOURCE is optional
--createimg IMG SIZE create ext4 image. SIZE is interpreted in MB
--imgsize IMG report ext4 image used/total size
--resizeimg IMG SIZE resize ext4 image. SIZE is interpreted in MB
--mountimg IMG PATH mount IMG to PATH and prints the loop device
--umountimg PATH LOOP unmount PATH and delete LOOP device
--[init service] start init service
--unlock-blocks set BLKROSET flag to OFF for all block devices
--restorecon fix selinux context on Magisk files and folders
--clone-attr SRC DEST clone permission, owner, and selinux context
Supported init services:
daemon, post-fs, post-fs-data, service
Supported applets:
su, resetprop, magiskhide
```
### su
An applet of `magisk`, the MagiskSU entry point, the good old `su` command.
Command help message:
```
Usage: su [options] [-] [user [argument...]]
Options:
-c, --command COMMAND pass COMMAND to the invoked shell
-h, --help display this help message and exit
-, -l, --login pretend the shell to be a login shell
-m, -p,
--preserve-environment preserve the entire environment
-s, --shell SHELL use SHELL instead of the default /system/bin/sh
-v, --version display version number and exit
-V display version code and exit,
this is used almost exclusively by Superuser.apk
-mm, -M,
--mount-master run in the global mount namespace,
use if you need to publicly apply mounts
```
Note: even though the `-Z, --context` option is not listed above, it actually still exists for compatibility with apps using SuperSU. However MagiskSU will silently ignore the option since it's no more relevant.
### resetprop
An applet of `magisk`, an advanced system property manipulation utility. Here's some background knowledge:
System properties are stored in a hybrid trie/binary tree data structure in memory. These properties are allowed to be read by many processes (natively via `libcutils`, in shells via the `getprop` command); however, only the `init` process have direct write access to the memory of property data. `init` provides a `property_service` to accept property update requests and acts as a gatekeeper, doing things such as preventing **read-only** props to be overridden and storing **persist** props to non-volatile storages. In addition, property triggers registered in `*.rc` scripts are also handled here.
`resetprop` is created by pulling out the portion of source code managing properties from AOSP and try to mimic what `init` is doing. With some hackery the result is that we have direct access to the data structure, bypassing the need to go through `property_service` to gain arbitrary control. Here is a small implementation detail: the data structure and the stack-like memory allocation method does not support removing props (they are **designed NOT** to be removed); prop deletion is accomplished by detaching the target node from the tree structure, making it effectively invisible. As we cannot reclaim the memory allocated to store the property, this wastes a few bytes of memory but it shouldn't be a big deal unless you are adding and deleting hundreds of thousands of props over and over again.
Due to the fact that we bypassed `property_service`, there are a few things developer should to be aware of:
- `on property:foo=bar` triggers registered in `*.rc` scripts will not be triggered when props are changed. This could be a good thing or a bad thing, depending on what behavior you expect. The default behavior of `resetprop` matches the original `setprop`, which **WILL** trigger events (implemented by deleting the prop and set the props via `property_service`), but there is a flag (`-n`) to disable it if you need this special behavior.
- persist props are stored both in memory and in `/data/property`. By default, deleting props will **NOT** remove it from persistent storage, meaning the prop will be restored after the next reboot; reading props will **NOT** read from persistent storage, as this is the behavior of normal `getprop`. With the flag `-p` enabled, deleting props will remove the prop **BOTH** in memory and `/data/property`; props will be read from **BOTH** in memory and persistent storage.
Command help message:
```
Usage: resetprop [flags] [options...]
Options:
-h, --help show this message
(no arguments) print all properties
NAME get property
NAME VALUE set property entry NAME with VALUE
--file FILE load props from FILE
--delete NAME delete property
Flags:
-v print verbose output to stderr
-n set properties without init triggers
only affects setprop
-p access actual persist storage
only affects getprop and deleteprop
```
### magiskhide
An applet of `magisk`, the CLI to control MagiskHide. Use this tool to communicate with the daemon to change MagiskHide settings.
Command help message:
```
Usage: magiskhide [--options [arguments...] ]
Options:
--enable Start magiskhide
--disable Stop magiskhide
--add PROCESS Add PROCESS to the hide list
--rm PROCESS Remove PROCESS from the hide list
--ls Print out the current hide list
```

View File

@@ -13,8 +13,6 @@
main() {
# Magisk binaries
MAGISKBIN=/data/adb/magisk
# This script always runs in recovery
BOOTMODE=false
mount /data 2>/dev/null
@@ -41,7 +39,6 @@ main() {
remove_system_su
find_boot_image
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print "- Found boot image: $BOOTIMAGE"
@@ -59,13 +56,6 @@ main() {
mv stock_boot* /data
fi
patch_dtbo_image
if [ -f stock_dtbo* ]; then
rm -f /data/stock_dtbo* 2>/dev/null
mv stock_dtbo* /data
fi
cd /
recovery_cleanup

View File

@@ -83,8 +83,6 @@ chmod -R 755 .
# Unpack
##########################################################################################
migrate_boot_backup
CHROMEOS=false
ui_print "- Unpacking boot image"

View File

@@ -13,10 +13,6 @@
# Preparation
##########################################################################################
# Detect whether in boot mode
ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false
$BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true
# This path should work in any cases
TMPDIR=/dev/tmp
@@ -24,7 +20,6 @@ INSTALLER=$TMPDIR/install
COMMONDIR=$INSTALLER/common
APK=$COMMONDIR/magisk.apk
CHROMEDIR=$INSTALLER/chromeos
COREDIR=/magisk/.core
# Default permissions
umask 022
@@ -83,8 +78,8 @@ if is_mounted /data; then
chmod 700 /data/adb 2>/dev/null
# Some legacy migration
mv /data/magisk/stock_boot* /data 2>/dev/null
[ -L /data/magisk.img ] || mv /data/magisk.img /data/adb/magisk.img
run_migrations
[ -L /data/magisk.img ] || mv /data/magisk.img /data/adb/magisk.img 2>/dev/null
else
MAGISKBIN=/cache/data_bin
fi
@@ -113,7 +108,6 @@ $BOOTMODE || recovery_actions
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print "- Found boot image: $BOOTIMAGE"
find_dtbo_image
if [ ! -z $DTBOIMAGE ]; then
ui_print "- Found dtbo image: $DTBOIMAGE"
# Disable dtbo patch by default

View File

@@ -34,20 +34,16 @@ fi
if $BOOTMODE; then
# Load utility functions
. $MAGISKBIN/util_functions.sh
BOOTMODE=true
boot_actions
mount_partitions
fi
cd $MAGISKBIN
# Find the boot image
find_boot_image
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print "- Found Boot Image: $BOOTIMAGE"
migrate_boot_backup
ui_print "- Unpacking boot image"
./magiskboot --unpack "$BOOTIMAGE"
CHROMEOS=false

View File

@@ -10,9 +10,14 @@
#MAGISK_VERSION_STUB
SCRIPT_VERSION=$MAGISK_VER_CODE
# Detect whether in boot mode
ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false
$BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true
$BOOTMODE || id | grep -q 'uid=0' || BOOTMODE=true
# Default location, will override if needed
MAGISKBIN=/data/adb/magisk
[ -z $MAGISKBIN ] && MOUNTPATH=/sbin/.core/img
[ -z $MOUNTPATH ] && MOUNTPATH=/sbin/.core/img
[ -z $IMG ] && IMG=/data/adb/magisk.img
BOOTSIGNER="/system/bin/dalvikvm -Xnodex2oat -Xnoimage-dex2oat -cp \$APK com.topjohnwu.magisk.utils.BootSigner"
@@ -47,7 +52,12 @@ mount_partitions() {
SLOT=_`getprop ro.boot.slot`
[ $SLOT = "_" ] && SLOT=
fi
# Check the boot image to make sure the slot actually make sense
find_boot_image
find_dtbo_image
[ -z $SLOT ] || ui_print "- A/B partition detected, current slot: $SLOT"
ui_print "- Mounting /system, /vendor"
is_mounted /system || [ -f /system/build.prop ] || mount -o ro /system 2>/dev/null
if ! is_mounted /system && ! [ -f /system/build.prop ]; then
@@ -86,7 +96,7 @@ getvar() {
local VARNAME=$1
local VALUE=$(eval echo \$$VARNAME)
[ ! -z $VALUE ] && return
for DIR in /.backup /data /cache /system; do
for DIR in /.backup /dev /data /cache /system; do
VALUE=`grep_prop $VARNAME $DIR/.magisk`
[ ! -z $VALUE ] && break;
done
@@ -105,7 +115,10 @@ find_boot_image() {
BOOTIMAGE=
if [ ! -z $SLOT ]; then
BOOTIMAGE=`find /dev/block -iname boot$SLOT | head -n 1` 2>/dev/null
else
fi
if [ -z "$BOOTIMAGE" ]; then
# The slot info is incorrect...
SLOT=
for BLOCK in boot_a kern-a android_boot kernel boot lnx bootimg; do
BOOTIMAGE=`find /dev/block -iname $BLOCK | head -n 1` 2>/dev/null
[ ! -z $BOOTIMAGE ] && break
@@ -118,10 +131,10 @@ find_boot_image() {
[ ! -z $BOOTIMAGE ] && break
done
fi
BOOTIMAGE=`resolve_link $BOOTIMAGE`
[ ! -z "$BOOTIMAGE" ] && BOOTIMAGE=`resolve_link $BOOTIMAGE`
}
migrate_boot_backup() {
run_migrations() {
# Update the broken boot backup
if [ -f /data/stock_boot_.img.gz ]; then
$MAGISKBIN/magiskboot --decompress /data/stock_boot_.img.gz /data/stock_boot.img
@@ -134,8 +147,17 @@ migrate_boot_backup() {
mv /data/stock_boot.img $STOCKDUMP
$MAGISKBIN/magiskboot --compress $STOCKDUMP
fi
mv /data/magisk/stock_boot* /data 2>/dev/null
mv /data/magisk/adb/stock_boot* /data 2>/dev/null
# Move the stock backups
if [ -f /data/magisk/stock_boot* ]; then
rm -rf /data/stock_boot*
mv /data/magisk/stock_boot* /data 2>/dev/null
fi
if [ -f /data/adb/magisk/stock_boot* ]; then
rm -rf /data/stock_boot*
mv /data/adb/magisk/stock_boot* /data 2>/dev/null
fi
# Remove old dbs
rm -f /data/user*/*/magisk.db
}
flash_boot_image() {

View File

@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "27.0.2"
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.topjohnwu.snet"