Dynamic patch verity and forceencrypt flag

This commit is contained in:
topjohnwu 2017-12-07 03:21:13 +08:00
parent b4c0a255fc
commit baff9256c5
8 changed files with 121 additions and 56 deletions

View File

@ -47,10 +47,15 @@
#include "cpio.h" #include "cpio.h"
#include "magisk.h" #include "magisk.h"
// #define VLOG(fmt, ...) printf(fmt, __VA_ARGS__) /* Enable to debug */ #ifdef MAGISK_DEBUG
#define VLOG(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define VLOG(fmt, ...) #define VLOG(fmt, ...)
#endif
extern policydb_t *policydb;
int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL }; int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL };
static int keepverity = 0, keepencrypt = 0;
struct cmdline { struct cmdline {
int skip_initramfs; int skip_initramfs;
@ -65,8 +70,6 @@ struct device {
char path[64]; char path[64];
}; };
extern policydb_t *policydb;
static void parse_cmdline(struct cmdline *cmd) { static void parse_cmdline(struct cmdline *cmd) {
// cleanup // cleanup
cmd->skip_initramfs = 0; cmd->skip_initramfs = 0;
@ -143,7 +146,24 @@ static int setup_block(struct device *dev, const char *partname) {
return 0; return 0;
} }
static void patch_ramdisk() { static void fstab_patch_cb(int dirfd, struct dirent *entry) {
if (entry->d_type == DT_REG && strstr(entry->d_name, "fstab")) {
void *buf;
size_t _size;
uint32_t size;
full_read_at(dirfd, entry->d_name, &buf, &_size);
size = _size; /* Type conversion */
if (!keepverity)
patch_verity(&buf, &size, 1);
if (!keepencrypt)
patch_encryption(&buf, &size);
int fstab = xopenat(dirfd, entry->d_name, O_WRONLY | O_CLOEXEC);
write(fstab, buf, size);
close(fstab);
}
}
static void patch_ramdisk(int root) {
void *addr; void *addr;
size_t size; size_t size;
mmap_rw("/init", &addr, &size); mmap_rw("/init", &addr, &size);
@ -161,6 +181,23 @@ static void patch_ramdisk() {
write(fd, addr, size); write(fd, addr, size);
close(fd); close(fd);
free(addr); free(addr);
char *key, *value;
full_read("/.backup/.magisk", &addr, &size);
for (char *tok = strtok(addr, "\n"); tok; tok = strtok(NULL, "\n")) {
key = tok;
value = strchr(tok, '=') + 1;
value[-1] = '\0';
if (strcmp(key, "KEEPVERITY") == 0)
keepverity = strcmp(value, "true") == 0;
else if (strcmp(key, "KEEPFORCEENCRYPT") == 0)
keepencrypt = strcmp(value, "true") == 0;
}
excl_list = (char *[]) { "system_root", "system", "vendor", NULL };
in_order_walk(root, fstab_patch_cb);
if (!keepverity)
unlink("/verity_key");
} }
static int strend(const char *s1, const char *s2) { static int strend(const char *s1, const char *s2) {
@ -456,17 +493,13 @@ int main(int argc, char *argv[]) {
} }
} }
// Only patch initramfs if not intended to run in recovery (legacy devices) int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
// Only patch rootfs if not intended to run in recovery
if (access("/etc/recovery.fstab", F_OK) != 0) { if (access("/etc/recovery.fstab", F_OK) != 0) {
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
mv_dir(overlay, root); mv_dir(overlay, root);
// Clean up patch_ramdisk(root);
rmdir("/overlay");
close(overlay);
close(root);
patch_ramdisk();
patch_sepolicy(); patch_sepolicy();
if (fork_dont_care() == 0) { if (fork_dont_care() == 0) {
@ -475,7 +508,12 @@ int main(int argc, char *argv[]) {
} }
} }
// Clean up
close(overlay);
close(root);
umount("/vendor"); umount("/vendor");
rmdir("/overlay");
// Finally, give control back! // Finally, give control back!
execv("/init", argv); execv("/init", argv);
} }

View File

@ -20,7 +20,7 @@ typedef struct cpio_entry {
// uint32_t namesize; // uint32_t namesize;
// uint32_t check; // uint32_t check;
char *filename; char *filename;
char *data; void *data;
int remove; int remove;
} cpio_entry; } cpio_entry;

View File

@ -102,6 +102,7 @@ struct file_attr {
int fd_getpath(int fd, char *path, size_t size); int fd_getpath(int fd, char *path, size_t size);
int mkdir_p(const char *pathname, mode_t mode); int mkdir_p(const char *pathname, mode_t mode);
void in_order_walk(int dirfd, void (*callback)(int, struct dirent*));
void rm_rf(const char *path); void rm_rf(const char *path);
void frm_rf(int dirfd); void frm_rf(int dirfd);
void mv_f(const char *source, const char *destination); void mv_f(const char *source, const char *destination);
@ -119,7 +120,9 @@ void clone_attr(const char *source, const char *target);
void restorecon(int dirfd, int force); void restorecon(int dirfd, int force);
int mmap_ro(const char *filename, void **buf, size_t *size); int mmap_ro(const char *filename, void **buf, size_t *size);
int mmap_rw(const char *filename, void **buf, size_t *size); int mmap_rw(const char *filename, void **buf, size_t *size);
void fd_full_read(int fd, void **buf, size_t *size);
void full_read(const char *filename, void **buf, size_t *size); void full_read(const char *filename, void **buf, size_t *size);
void full_read_at(int dirfd, const char *filename, void **buf, size_t *size);
void stream_full_read(int fd, void **buf, size_t *size); void stream_full_read(int fd, void **buf, size_t *size);
void write_zero(int fd, size_t size); void write_zero(int fd, size_t size);
void mem_align(size_t *pos, size_t align); void mem_align(size_t *pos, size_t align);
@ -142,7 +145,7 @@ void trim_img(const char *img);
// pattern.c // pattern.c
void patch_init_rc(void **buf, size_t *size); void patch_init_rc(void **buf, size_t *size);
int patch_verity(char **buf, uint32_t *size, int patch); int patch_verity(void **buf, uint32_t *size, int patch);
void patch_encryption(char **buf, uint32_t *size); void patch_encryption(void **buf, uint32_t *size);
#endif #endif

View File

@ -78,7 +78,7 @@ static void dtb_patch(const char *file, int patch) {
fdt_for_each_subnode(block, fdt, fstab) { fdt_for_each_subnode(block, fdt, fstab) {
fprintf(stderr, "Found block [%s] in fstab\n", fdt_get_name(fdt, block, NULL)); fprintf(stderr, "Found block [%s] in fstab\n", fdt_get_name(fdt, block, NULL));
uint32_t value_size; uint32_t value_size;
char *value = (char *) fdt_getprop(fdt, block, "fsmgr_flags", &value_size); void *value = (char *) fdt_getprop(fdt, block, "fsmgr_flags", &value_size);
found |= patch_verity(&value, &value_size, patch); found |= patch_verity(&value, &value_size, patch);
} }
} }

View File

@ -58,7 +58,7 @@ static char *cpio_stocksha1(struct vector *v) {
vec_for_each(v, f) { vec_for_each(v, f) {
if (strcmp(f->filename, "init.magisk.rc") == 0 if (strcmp(f->filename, "init.magisk.rc") == 0
|| strcmp(f->filename, "overlay/init.magisk.rc") == 0) { || strcmp(f->filename, "overlay/init.magisk.rc") == 0) {
for (char *pos = f->data; pos < f->data + f->filesize; pos = strchr(pos + 1, '\n') + 1) { for (void *pos = f->data; pos < f->data + f->filesize; pos = strchr(pos + 1, '\n') + 1) {
if (memcmp(pos, "# STOCKSHA1=", 12) == 0) { if (memcmp(pos, "# STOCKSHA1=", 12) == 0) {
pos += 12; pos += 12;
memcpy(sha1, pos, 40); memcpy(sha1, pos, 40);

View File

@ -17,13 +17,13 @@
#include "utils.h" #include "utils.h"
char **excl_list = (char *[]) { NULL }; char **excl_list = NULL;
static int is_excl(const char *name) { static int is_excl(const char *name) {
for (int i = 0; excl_list[i]; ++i) { if (excl_list)
if (strcmp(name, excl_list[i]) == 0) for (int i = 0; excl_list[i]; ++i)
return 1; if (strcmp(name, excl_list[i]) == 0)
} return 1;
return 0; return 0;
} }
@ -55,6 +55,36 @@ int mkdir_p(const char *pathname, mode_t mode) {
return 0; return 0;
} }
void in_order_walk(int dirfd, void (*callback)(int, struct dirent*)) {
struct dirent *entry;
int newfd;
DIR *dir = xfdopendir(dirfd);
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
if (is_excl(entry->d_name))
continue;
if (entry->d_type == DT_DIR) {
newfd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
in_order_walk(newfd, callback);
close(newfd);
}
callback(dirfd, entry);
}
}
static void rm_cb(int dirfd, struct dirent *entry) {
switch (entry->d_type) {
case DT_DIR:
unlinkat(dirfd, entry->d_name, AT_REMOVEDIR);
break;
default:
unlinkat(dirfd, entry->d_name, 0);
break;
}
}
void rm_rf(const char *path) { void rm_rf(const char *path) {
int fd = xopen(path, O_RDONLY | O_CLOEXEC); int fd = xopen(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) if (fd < 0)
@ -65,27 +95,7 @@ void rm_rf(const char *path) {
} }
void frm_rf(int dirfd) { void frm_rf(int dirfd) {
struct dirent *entry; in_order_walk(dirfd, rm_cb);
int newfd;
DIR *dir = xfdopendir(dirfd);
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
if (is_excl(entry->d_name))
continue;
switch (entry->d_type) {
case DT_DIR:
newfd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
frm_rf(newfd);
close(newfd);
unlinkat(dirfd, entry->d_name, AT_REMOVEDIR);
break;
default:
unlinkat(dirfd, entry->d_name, 0);
break;
}
}
} }
/* This will only on the same file system */ /* This will only on the same file system */
@ -360,6 +370,13 @@ int mmap_rw(const char *filename, void **buf, size_t *size) {
return _mmap(1, filename, buf, size); return _mmap(1, filename, buf, size);
} }
void fd_full_read(int fd, void **buf, size_t *size) {
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = xmalloc(*size);
xxread(fd, *buf, *size);
}
void full_read(const char *filename, void **buf, size_t *size) { void full_read(const char *filename, void **buf, size_t *size) {
int fd = xopen(filename, O_RDONLY); int fd = xopen(filename, O_RDONLY);
if (fd < 0) { if (fd < 0) {
@ -367,10 +384,18 @@ void full_read(const char *filename, void **buf, size_t *size) {
*size = 0; *size = 0;
return; return;
} }
*size = lseek(fd, 0, SEEK_END); fd_full_read(fd, buf, size);
lseek(fd, 0, SEEK_SET); close(fd);
*buf = xmalloc(*size); }
xxread(fd, *buf, *size);
void full_read_at(int dirfd, const char *filename, void **buf, size_t *size) {
int fd = xopenat(dirfd, filename, O_RDONLY);
if (fd < 0) {
*buf = NULL;
*size = 0;
return;
}
fd_full_read(fd, buf, size);
close(fd); close(fd);
} }

View File

@ -58,12 +58,12 @@ void patch_init_rc(void **buf, size_t *size) {
*buf = new_data; *buf = new_data;
} }
int patch_verity(char **buf, uint32_t *size, int patch) { int patch_verity(void **buf, uint32_t *size, int patch) {
int skip, found = 0; int skip, found = 0;
for (int pos = 0; pos < *size; ++pos) { for (int pos = 0; pos < *size; ++pos) {
if ((skip = check_verity_pattern(*buf + pos)) > 0) { if ((skip = check_verity_pattern(*buf + pos)) > 0) {
found = 1; found = 1;
fprintf(stderr, "%s pattern [%.*s]\n", patch ? "Remove" : "Found", skip, *buf + pos); fprintf(stderr, "%s pattern [%.*s]\n", patch ? "Remove" : "Found", skip, (char *) *buf + pos);
if (patch) { if (patch) {
memcpy(*buf + pos, *buf + pos + skip, *size - pos - skip); memcpy(*buf + pos, *buf + pos + skip, *size - pos - skip);
memset(*buf + *size - skip, '\0', skip); memset(*buf + *size - skip, '\0', skip);
@ -76,11 +76,11 @@ int patch_verity(char **buf, uint32_t *size, int patch) {
return found; return found;
} }
void patch_encryption(char **buf, uint32_t *size) { void patch_encryption(void **buf, uint32_t *size) {
int skip; int skip;
for (int pos = 0; pos < *size; ++pos) { for (int pos = 0; pos < *size; ++pos) {
if ((skip = check_encryption_pattern(*buf + pos)) > 0) { if ((skip = check_encryption_pattern(*buf + pos)) > 0) {
fprintf(stderr, "Replace pattern [%.*s] with [encryptable]\n", skip, *buf + pos); fprintf(stderr, "Replace pattern [%.*s] with [encryptable]\n", skip, (char *) *buf + pos);
memcpy(*buf + pos, "encryptable", 11); memcpy(*buf + pos, "encryptable", 11);
memcpy(*buf + pos + 11, *buf + pos + skip, *size - pos - skip); memcpy(*buf + pos + 11, *buf + pos + skip, *size - pos - skip);
memset(*buf + *size - skip + 11, '\0', skip - 11); memset(*buf + *size - skip + 11, '\0', skip - 11);

View File

@ -64,7 +64,7 @@ BOOTIMAGE="$1"
# Presets # Presets
[ -z $KEEPVERITY ] && KEEPVERITY=false [ -z $KEEPVERITY ] && KEEPVERITY=false
[ -z $KEEPFORCEENCRYPT ] && KEEPFORCEENCRYPT=false [ -z $KEEPFORCEENCRYPT ] && KEEPFORCEENCRYPT=false
[ -z $HIGH_COMP ] && HIGH_COMP=false [ -z $HIGHCOMP ] && HIGHCOMP=false
chmod -R 755 . chmod -R 755 .
@ -89,7 +89,7 @@ case $? in
2 ) 2 )
ui_print "! Insufficient boot partition size detected" ui_print "! Insufficient boot partition size detected"
ui_print "- Enable high compression mode" ui_print "- Enable high compression mode"
HIGH_COMP=true HIGHCOMP=true
;; ;;
3 ) 3 )
ui_print "- ChromeOS boot image detected" ui_print "- ChromeOS boot image detected"
@ -139,11 +139,10 @@ esac
ui_print "- Patching ramdisk" ui_print "- Patching ramdisk"
[ -f /sdcard/ramdisk-recovery.img ] && HIGH_COMP=true [ -f /sdcard/ramdisk-recovery.img ] && HIGHCOMP=true
./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT
./magiskboot --cpio-add ramdisk.cpio 750 init magiskinit ./magiskboot --cpio-add ramdisk.cpio 750 init magiskinit
./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig $HIGH_COMP $SHA1 ./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig $HIGHCOMP $KEEPVERITY $KEEPFORCEENCRYPT $SHA1
rm -f ramdisk.cpio.orig rm -f ramdisk.cpio.orig