diff --git a/native/src/base/files.cpp b/native/src/base/files.cpp index 9d72caa3c..b76f86360 100644 --- a/native/src/base/files.cpp +++ b/native/src/base/files.cpp @@ -463,11 +463,21 @@ bool byte_data::contains(string_view pattern, bool log) const { return false; } +bool byte_data::equals(const byte_data &o) const { + return sz == o.sz && memcmp(buf, o.buf, sz) == 0; +} + void byte_data::swap(byte_data &o) { std::swap(buf, o.buf); std::swap(sz, o.sz); } +heap_data byte_data::clone() const { + heap_data copy(sz); + memcpy(copy.buf, buf, sz); + return copy; +} + mmap_data::mmap_data(const char *name, bool rw) { int fd = xopen(name, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC); if (fd < 0) diff --git a/native/src/base/files.hpp b/native/src/base/files.hpp index 3d5a53c80..eae6342dc 100644 --- a/native/src/base/files.hpp +++ b/native/src/base/files.hpp @@ -43,15 +43,23 @@ struct mount_info { std::string fs_option; }; +struct heap_data; + struct byte_data { using str_pairs = std::initializer_list>; - uint8_t *buf = nullptr; - size_t sz = 0; + uint8_t *buf; + size_t sz; + + byte_data() : buf(nullptr), sz(0) {} + byte_data(void *buf, size_t sz) : buf(static_cast(buf)), sz(sz) {} + explicit byte_data(std::string_view str) : buf((uint8_t *) str.data()), sz(str.length()) {} int patch(str_pairs list) { return patch(true, list); } int patch(bool log, str_pairs list); bool contains(std::string_view pattern, bool log = true) const; + bool equals(const byte_data &o) const; + heap_data clone() const; protected: void swap(byte_data &o); }; @@ -65,7 +73,8 @@ clazz& operator=(clazz &&o) { swap(o); return *this; } struct heap_data : public byte_data { MOVE_ONLY(heap_data) - explicit heap_data(size_t sz) { this->sz = sz; buf = new uint8_t[sz]; } + explicit heap_data(size_t sz) : byte_data(new uint8_t[sz], sz) {} + heap_data(const void *buf, size_t sz) : heap_data(sz) { memcpy(this->buf, buf, sz); } ~heap_data() { delete[] buf; } }; diff --git a/native/src/boot/cpio.cpp b/native/src/boot/cpio.cpp index f0c0b72f7..f5764724e 100644 --- a/native/src/boot/cpio.cpp +++ b/native/src/boot/cpio.cpp @@ -43,11 +43,13 @@ static uint32_t x8u(const char *hex) { return val; } -cpio_entry::cpio_entry(uint32_t mode) : mode(mode), uid(0), gid(0), filesize(0), data(nullptr) {} +cpio_entry::cpio_entry(uint32_t mode) : mode(mode), uid(0), gid(0), data(0) {} + +cpio_entry::cpio_entry(uint32_t mode, const byte_data &data) : +mode(mode), uid(0), gid(0), data(data.clone()) {} cpio_entry::cpio_entry(const cpio_newc_header *h) : -mode(x8u(h->mode)), uid(x8u(h->uid)), gid(x8u(h->gid)), filesize(x8u(h->filesize)), data(nullptr) -{} +mode(x8u(h->mode)), uid(x8u(h->uid)), gid(x8u(h->gid)), data(x8u(h->filesize)) {} void cpio::dump(const char *file) { fprintf(stderr, "Dump cpio: [%s]\n", file); @@ -87,13 +89,13 @@ static void extract_entry(const cpio::entry_map::value_type &e, const char *file xmkdir(file, e.second->mode & 0777); } else if (S_ISREG(e.second->mode)) { int fd = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, e.second->mode & 0777); - xwrite(fd, e.second->data, e.second->filesize); + xwrite(fd, e.second->data.buf, e.second->data.sz); fchown(fd, e.second->uid, e.second->gid); close(fd); - } else if (S_ISLNK(e.second->mode) && e.second->filesize < 4096) { + } else if (S_ISLNK(e.second->mode) && e.second->data.sz < 4096) { char target[4096]; - memcpy(target, e.second->data, e.second->filesize); - target[e.second->filesize] = '\0'; + memcpy(target, e.second->data.buf, e.second->data.sz); + target[e.second->data.sz] = '\0'; symlink(target, file); } } @@ -132,7 +134,7 @@ void cpio::dump(FILE *out) { e.second->gid, 1, // e->nlink 0, // e->mtime - e.second->filesize, + (uint32_t) e.second->data.sz, 0, // e->devmajor 0, // e->devminor 0, // e->rdevmajor @@ -143,8 +145,8 @@ void cpio::dump(FILE *out) { do_out(header, 110); do_out(e.first.data(), e.first.size() + 1); out_align(); - if (e.second->filesize) { - do_out(e.second->data, e.second->filesize); + if (e.second->data.sz) { + do_out(e.second->data.buf, e.second->data.sz); out_align(); } } @@ -173,11 +175,8 @@ void cpio::insert(string_view name, cpio_entry *e) { } void cpio::add(mode_t mode, const char *name, const char *file) { - auto m = mmap_data(file); - auto e = new cpio_entry(S_IFREG | mode); - e->filesize = m.sz; - e->data = malloc(m.sz); - memcpy(e->data, m.buf, m.sz); + mmap_data m(file); + auto e = new cpio_entry(S_IFREG | mode, m); insert(name, e); fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode); } @@ -188,9 +187,8 @@ void cpio::mkdir(mode_t mode, const char *name) { } void cpio::ln(const char *target, const char *name) { - auto e = new cpio_entry(S_IFLNK); - e->filesize = strlen(target); - e->data = strdup(target); + byte_data link(target); + auto e = new cpio_entry(S_IFLNK, link); insert(name, e); fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target); } @@ -236,9 +234,8 @@ void cpio::load_cpio(const char *buf, size_t sz) { continue; } auto entry = new cpio_entry(hdr); - entry->data = malloc(entry->filesize); - memcpy(entry->data, buf + pos, entry->filesize); - pos += entry->filesize; + memcpy(entry->data.buf, buf + pos, entry->data.sz); + pos += entry->data.sz; insert(name, entry); pos_align(pos); } diff --git a/native/src/boot/cpio.hpp b/native/src/boot/cpio.hpp index 3a0f2d255..2782c1c68 100644 --- a/native/src/boot/cpio.hpp +++ b/native/src/boot/cpio.hpp @@ -6,18 +6,19 @@ #include #include +#include + struct cpio_newc_header; struct cpio_entry { uint32_t mode; uint32_t uid; uint32_t gid; - uint32_t filesize; - void *data; + heap_data data; - explicit cpio_entry(uint32_t mode = 0); + explicit cpio_entry(uint32_t mode); + explicit cpio_entry(uint32_t mode, const byte_data &data); explicit cpio_entry(const cpio_newc_header *h); - ~cpio_entry() { free(data); } }; class cpio { diff --git a/native/src/boot/dtb.cpp b/native/src/boot/dtb.cpp index fb5193492..935f1d62f 100644 --- a/native/src/boot/dtb.cpp +++ b/native/src/boot/dtb.cpp @@ -150,7 +150,8 @@ static bool dtb_patch(const char *file) { fdt_for_each_subnode(node, fdt, fstab) { int len; char *value = (char *) fdt_getprop(fdt, node, "fsmgr_flags", &len); - patched |= patch_verity(value, len) != len; + byte_data data(value, len); + patched |= patch_verity(data); } } } @@ -221,12 +222,11 @@ static bool fdt_patch(void *fdt) { const char *name = fdt_get_name(fdt, node, nullptr); // Force remove AVB for 2SI since it may bootloop some devices int len; - auto value = (const char *) fdt_getprop(fdt, node, "fsmgr_flags", &len); - string copy(value, len); - uint32_t new_len = patch_verity(copy.data(), len); - if (new_len != len) { + const void *value = fdt_getprop(fdt, node, "fsmgr_flags", &len); + heap_data copy(value, len); + if (patch_verity(copy)) { modified = true; - fdt_setprop(fdt, node, "fsmgr_flags", copy.data(), new_len); + fdt_setprop(fdt, node, "fsmgr_flags", copy.buf, copy.sz); } if (name == "system"sv) { fprintf(stderr, "Setting [mnt_point] to [/system_root]\n"); diff --git a/native/src/boot/magiskboot.hpp b/native/src/boot/magiskboot.hpp index e401654eb..1150c8a0e 100644 --- a/native/src/boot/magiskboot.hpp +++ b/native/src/boot/magiskboot.hpp @@ -2,6 +2,8 @@ #include +#include + #include "boot-rs.hpp" #define HEADER_FILE "header" @@ -21,6 +23,7 @@ int hexpatch(const char *file, const char *from, const char *to); int cpio_commands(int argc, char *argv[]); int dtb_commands(int argc, char *argv[]); -uint32_t patch_verity(void *buf, uint32_t size); -uint32_t patch_encryption(void *buf, uint32_t size); +bool patch_verity(byte_data &data); +bool patch_encryption(byte_data &data); + bool check_env(const char *name); diff --git a/native/src/boot/pattern.cpp b/native/src/boot/pattern.cpp index bc29398f5..485655aab 100644 --- a/native/src/boot/pattern.cpp +++ b/native/src/boot/pattern.cpp @@ -39,26 +39,28 @@ static int skip_encryption_pattern(const char *s) { return skip; } -static uint32_t remove_pattern(char *src, uint32_t size, int(*pattern_skip)(const char *)) { - int orig_sz = size; +static bool remove_pattern(byte_data &data, int(*pattern_skip)(const char *)) { + char *src = reinterpret_cast(data.buf); + size_t orig_sz = data.sz; int write = 0; - for (int read = 0; read < orig_sz;) { + int read = 0; + while (read < orig_sz) { if (int skip = pattern_skip(src + read); skip > 0) { fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read); - size -= skip; + data.sz -= skip; read += skip; } else { src[write++] = src[read++]; } } memset(src + write, 0, orig_sz - write); - return size; + return data.sz != orig_sz; } -uint32_t patch_verity(void *buf, uint32_t size) { - return remove_pattern(static_cast(buf), size, skip_verity_pattern); +bool patch_verity(byte_data &data) { + return remove_pattern(data, skip_verity_pattern); } -uint32_t patch_encryption(void *buf, uint32_t size) { - return remove_pattern(static_cast(buf), size, skip_encryption_pattern); +bool patch_encryption(byte_data &data) { + return remove_pattern(data, skip_encryption_pattern); } diff --git a/native/src/boot/ramdisk.cpp b/native/src/boot/ramdisk.cpp index 72ac8b327..995eb757e 100644 --- a/native/src/boot/ramdisk.cpp +++ b/native/src/boot/ramdisk.cpp @@ -44,16 +44,14 @@ void magisk_cpio::patch() { if (!keepverity) { if (fstab) { fprintf(stderr, "Found fstab file [%s]\n", cur->first.data()); - cur->second->filesize = patch_verity(cur->second->data, cur->second->filesize); + patch_verity(cur->second->data); } else if (cur->first == "verity_key") { rm(cur); continue; } } - if (!keepforceencrypt) { - if (fstab) { - cur->second->filesize = patch_encryption(cur->second->data, cur->second->filesize); - } + if (!keepforceencrypt && fstab) { + patch_encryption(cur->second->data); } } } @@ -113,7 +111,7 @@ void magisk_cpio::restore() { rm(bk); rm(mg); if (rl != entries.end()) { - for_each_str(file, rl->second->data, rl->second->filesize) { + for_each_str(file, rl->second->data.buf, rl->second->data.sz) { rm(file); } rm(rl); @@ -158,8 +156,7 @@ void magisk_cpio::backup(const char *orig) { do_backup = true; fprintf(stderr, "Backup missing entry: "); } else if (res == 0) { - if (lhs->second->filesize != rhs->second->filesize || - memcmp(lhs->second->data, rhs->second->data, lhs->second->filesize) != 0) { + if (!lhs->second->data.equals(rhs->second->data)) { // Not the same! do_backup = true; fprintf(stderr, "Backup mismatch entry: "); @@ -189,10 +186,8 @@ void magisk_cpio::backup(const char *orig) { } if (!rm_list.empty()) { - auto rm_list_file = new cpio_entry(S_IFREG); - rm_list_file->filesize = rm_list.length(); - rm_list_file->data = malloc(rm_list.length()); - memcpy(rm_list_file->data, rm_list.data(), rm_list.length()); + byte_data rm(rm_list); + auto rm_list_file = new cpio_entry(S_IFREG, rm); backups.emplace(".backup/.rmlist", rm_list_file); }