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 "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, ...)
#endif
extern policydb_t *policydb;
int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL };
static int keepverity = 0, keepencrypt = 0;
struct cmdline {
int skip_initramfs;
@ -65,8 +70,6 @@ struct device {
char path[64];
};
extern policydb_t *policydb;
static void parse_cmdline(struct cmdline *cmd) {
// cleanup
cmd->skip_initramfs = 0;
@ -143,7 +146,24 @@ static int setup_block(struct device *dev, const char *partname) {
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;
size_t size;
mmap_rw("/init", &addr, &size);
@ -161,6 +181,23 @@ static void patch_ramdisk() {
write(fd, addr, size);
close(fd);
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) {
@ -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) {
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
mv_dir(overlay, root);
// Clean up
rmdir("/overlay");
close(overlay);
close(root);
patch_ramdisk();
patch_ramdisk(root);
patch_sepolicy();
if (fork_dont_care() == 0) {
@ -475,7 +508,12 @@ int main(int argc, char *argv[]) {
}
}
// Clean up
close(overlay);
close(root);
umount("/vendor");
rmdir("/overlay");
// Finally, give control back!
execv("/init", argv);
}

View File

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

View File

@ -102,6 +102,7 @@ struct file_attr {
int fd_getpath(int fd, char *path, size_t size);
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 frm_rf(int dirfd);
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);
int mmap_ro(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_at(int dirfd, const char *filename, 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 mem_align(size_t *pos, size_t align);
@ -142,7 +145,7 @@ void trim_img(const char *img);
// pattern.c
void patch_init_rc(void **buf, size_t *size);
int patch_verity(char **buf, uint32_t *size, int patch);
void patch_encryption(char **buf, uint32_t *size);
int patch_verity(void **buf, uint32_t *size, int patch);
void patch_encryption(void **buf, uint32_t *size);
#endif

View File

@ -78,7 +78,7 @@ 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;
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);
}
}

View File

@ -58,7 +58,7 @@ static char *cpio_stocksha1(struct vector *v) {
vec_for_each(v, f) {
if (strcmp(f->filename, "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) {
pos += 12;
memcpy(sha1, pos, 40);

View File

@ -17,13 +17,13 @@
#include "utils.h"
char **excl_list = (char *[]) { NULL };
char **excl_list = NULL;
static int is_excl(const char *name) {
for (int i = 0; excl_list[i]; ++i) {
if (strcmp(name, excl_list[i]) == 0)
return 1;
}
if (excl_list)
for (int i = 0; excl_list[i]; ++i)
if (strcmp(name, excl_list[i]) == 0)
return 1;
return 0;
}
@ -55,6 +55,36 @@ int mkdir_p(const char *pathname, mode_t mode) {
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) {
int fd = xopen(path, O_RDONLY | O_CLOEXEC);
if (fd < 0)
@ -65,27 +95,7 @@ void rm_rf(const char *path) {
}
void frm_rf(int dirfd) {
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;
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;
}
}
in_order_walk(dirfd, rm_cb);
}
/* 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);
}
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) {
int fd = xopen(filename, O_RDONLY);
if (fd < 0) {
@ -367,10 +384,18 @@ void full_read(const char *filename, void **buf, size_t *size) {
*size = 0;
return;
}
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = xmalloc(*size);
xxread(fd, *buf, *size);
fd_full_read(fd, buf, size);
close(fd);
}
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);
}

View File

@ -58,12 +58,12 @@ void patch_init_rc(void **buf, size_t *size) {
*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;
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, *buf + pos);
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);
@ -76,11 +76,11 @@ int patch_verity(char **buf, uint32_t *size, int patch) {
return found;
}
void patch_encryption(char **buf, uint32_t *size) {
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, *buf + pos);
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);

View File

@ -64,7 +64,7 @@ BOOTIMAGE="$1"
# Presets
[ -z $KEEPVERITY ] && KEEPVERITY=false
[ -z $KEEPFORCEENCRYPT ] && KEEPFORCEENCRYPT=false
[ -z $HIGH_COMP ] && HIGH_COMP=false
[ -z $HIGHCOMP ] && HIGHCOMP=false
chmod -R 755 .
@ -89,7 +89,7 @@ case $? in
2 )
ui_print "! Insufficient boot partition size detected"
ui_print "- Enable high compression mode"
HIGH_COMP=true
HIGHCOMP=true
;;
3 )
ui_print "- ChromeOS boot image detected"
@ -139,11 +139,10 @@ esac
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-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