Cleanup cpio codebase

This commit is contained in:
topjohnwu 2023-06-03 00:31:20 -07:00
parent feb44f875e
commit 57afae3425
8 changed files with 74 additions and 57 deletions

View File

@ -463,11 +463,21 @@ bool byte_data::contains(string_view pattern, bool log) const {
return false; 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) { void byte_data::swap(byte_data &o) {
std::swap(buf, o.buf); std::swap(buf, o.buf);
std::swap(sz, o.sz); 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) { mmap_data::mmap_data(const char *name, bool rw) {
int fd = xopen(name, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC); int fd = xopen(name, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC);
if (fd < 0) if (fd < 0)

View File

@ -43,15 +43,23 @@ struct mount_info {
std::string fs_option; std::string fs_option;
}; };
struct heap_data;
struct byte_data { struct byte_data {
using str_pairs = std::initializer_list<std::pair<std::string_view, std::string_view>>; using str_pairs = std::initializer_list<std::pair<std::string_view, std::string_view>>;
uint8_t *buf = nullptr; uint8_t *buf;
size_t sz = 0; size_t sz;
byte_data() : buf(nullptr), sz(0) {}
byte_data(void *buf, size_t sz) : buf(static_cast<uint8_t *>(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(str_pairs list) { return patch(true, list); }
int patch(bool log, str_pairs list); int patch(bool log, str_pairs list);
bool contains(std::string_view pattern, bool log = true) const; bool contains(std::string_view pattern, bool log = true) const;
bool equals(const byte_data &o) const;
heap_data clone() const;
protected: protected:
void swap(byte_data &o); void swap(byte_data &o);
}; };
@ -65,7 +73,8 @@ clazz& operator=(clazz &&o) { swap(o); return *this; }
struct heap_data : public byte_data { struct heap_data : public byte_data {
MOVE_ONLY(heap_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; } ~heap_data() { delete[] buf; }
}; };

View File

@ -43,11 +43,13 @@ static uint32_t x8u(const char *hex) {
return val; 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) : 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) { void cpio::dump(const char *file) {
fprintf(stderr, "Dump cpio: [%s]\n", 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); xmkdir(file, e.second->mode & 0777);
} else if (S_ISREG(e.second->mode)) { } else if (S_ISREG(e.second->mode)) {
int fd = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, e.second->mode & 0777); 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); fchown(fd, e.second->uid, e.second->gid);
close(fd); 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]; char target[4096];
memcpy(target, e.second->data, e.second->filesize); memcpy(target, e.second->data.buf, e.second->data.sz);
target[e.second->filesize] = '\0'; target[e.second->data.sz] = '\0';
symlink(target, file); symlink(target, file);
} }
} }
@ -132,7 +134,7 @@ void cpio::dump(FILE *out) {
e.second->gid, e.second->gid,
1, // e->nlink 1, // e->nlink
0, // e->mtime 0, // e->mtime
e.second->filesize, (uint32_t) e.second->data.sz,
0, // e->devmajor 0, // e->devmajor
0, // e->devminor 0, // e->devminor
0, // e->rdevmajor 0, // e->rdevmajor
@ -143,8 +145,8 @@ void cpio::dump(FILE *out) {
do_out(header, 110); do_out(header, 110);
do_out(e.first.data(), e.first.size() + 1); do_out(e.first.data(), e.first.size() + 1);
out_align(); out_align();
if (e.second->filesize) { if (e.second->data.sz) {
do_out(e.second->data, e.second->filesize); do_out(e.second->data.buf, e.second->data.sz);
out_align(); 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) { void cpio::add(mode_t mode, const char *name, const char *file) {
auto m = mmap_data(file); mmap_data m(file);
auto e = new cpio_entry(S_IFREG | mode); auto e = new cpio_entry(S_IFREG | mode, m);
e->filesize = m.sz;
e->data = malloc(m.sz);
memcpy(e->data, m.buf, m.sz);
insert(name, e); insert(name, e);
fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode); 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) { void cpio::ln(const char *target, const char *name) {
auto e = new cpio_entry(S_IFLNK); byte_data link(target);
e->filesize = strlen(target); auto e = new cpio_entry(S_IFLNK, link);
e->data = strdup(target);
insert(name, e); insert(name, e);
fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target); fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target);
} }
@ -236,9 +234,8 @@ void cpio::load_cpio(const char *buf, size_t sz) {
continue; continue;
} }
auto entry = new cpio_entry(hdr); auto entry = new cpio_entry(hdr);
entry->data = malloc(entry->filesize); memcpy(entry->data.buf, buf + pos, entry->data.sz);
memcpy(entry->data, buf + pos, entry->filesize); pos += entry->data.sz;
pos += entry->filesize;
insert(name, entry); insert(name, entry);
pos_align(pos); pos_align(pos);
} }

View File

@ -6,18 +6,19 @@
#include <map> #include <map>
#include <string_view> #include <string_view>
#include <base.hpp>
struct cpio_newc_header; struct cpio_newc_header;
struct cpio_entry { struct cpio_entry {
uint32_t mode; uint32_t mode;
uint32_t uid; uint32_t uid;
uint32_t gid; uint32_t gid;
uint32_t filesize; heap_data data;
void *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); explicit cpio_entry(const cpio_newc_header *h);
~cpio_entry() { free(data); }
}; };
class cpio { class cpio {

View File

@ -150,7 +150,8 @@ static bool dtb_patch(const char *file) {
fdt_for_each_subnode(node, fdt, fstab) { fdt_for_each_subnode(node, fdt, fstab) {
int len; int len;
char *value = (char *) fdt_getprop(fdt, node, "fsmgr_flags", &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); const char *name = fdt_get_name(fdt, node, nullptr);
// Force remove AVB for 2SI since it may bootloop some devices // Force remove AVB for 2SI since it may bootloop some devices
int len; int len;
auto value = (const char *) fdt_getprop(fdt, node, "fsmgr_flags", &len); const void *value = fdt_getprop(fdt, node, "fsmgr_flags", &len);
string copy(value, len); heap_data copy(value, len);
uint32_t new_len = patch_verity(copy.data(), len); if (patch_verity(copy)) {
if (new_len != len) {
modified = true; 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) { if (name == "system"sv) {
fprintf(stderr, "Setting [mnt_point] to [/system_root]\n"); fprintf(stderr, "Setting [mnt_point] to [/system_root]\n");

View File

@ -2,6 +2,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <base.hpp>
#include "boot-rs.hpp" #include "boot-rs.hpp"
#define HEADER_FILE "header" #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 cpio_commands(int argc, char *argv[]);
int dtb_commands(int argc, char *argv[]); int dtb_commands(int argc, char *argv[]);
uint32_t patch_verity(void *buf, uint32_t size); bool patch_verity(byte_data &data);
uint32_t patch_encryption(void *buf, uint32_t size); bool patch_encryption(byte_data &data);
bool check_env(const char *name); bool check_env(const char *name);

View File

@ -39,26 +39,28 @@ static int skip_encryption_pattern(const char *s) {
return skip; return skip;
} }
static uint32_t remove_pattern(char *src, uint32_t size, int(*pattern_skip)(const char *)) { static bool remove_pattern(byte_data &data, int(*pattern_skip)(const char *)) {
int orig_sz = size; char *src = reinterpret_cast<char *>(data.buf);
size_t orig_sz = data.sz;
int write = 0; 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) { if (int skip = pattern_skip(src + read); skip > 0) {
fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read); fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read);
size -= skip; data.sz -= skip;
read += skip; read += skip;
} else { } else {
src[write++] = src[read++]; src[write++] = src[read++];
} }
} }
memset(src + write, 0, orig_sz - write); memset(src + write, 0, orig_sz - write);
return size; return data.sz != orig_sz;
} }
uint32_t patch_verity(void *buf, uint32_t size) { bool patch_verity(byte_data &data) {
return remove_pattern(static_cast<char *>(buf), size, skip_verity_pattern); return remove_pattern(data, skip_verity_pattern);
} }
uint32_t patch_encryption(void *buf, uint32_t size) { bool patch_encryption(byte_data &data) {
return remove_pattern(static_cast<char *>(buf), size, skip_encryption_pattern); return remove_pattern(data, skip_encryption_pattern);
} }

View File

@ -44,16 +44,14 @@ void magisk_cpio::patch() {
if (!keepverity) { if (!keepverity) {
if (fstab) { if (fstab) {
fprintf(stderr, "Found fstab file [%s]\n", cur->first.data()); 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") { } else if (cur->first == "verity_key") {
rm(cur); rm(cur);
continue; continue;
} }
} }
if (!keepforceencrypt) { if (!keepforceencrypt && fstab) {
if (fstab) { patch_encryption(cur->second->data);
cur->second->filesize = patch_encryption(cur->second->data, cur->second->filesize);
}
} }
} }
} }
@ -113,7 +111,7 @@ void magisk_cpio::restore() {
rm(bk); rm(bk);
rm(mg); rm(mg);
if (rl != entries.end()) { 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(file);
} }
rm(rl); rm(rl);
@ -158,8 +156,7 @@ void magisk_cpio::backup(const char *orig) {
do_backup = true; do_backup = true;
fprintf(stderr, "Backup missing entry: "); fprintf(stderr, "Backup missing entry: ");
} else if (res == 0) { } else if (res == 0) {
if (lhs->second->filesize != rhs->second->filesize || if (!lhs->second->data.equals(rhs->second->data)) {
memcmp(lhs->second->data, rhs->second->data, lhs->second->filesize) != 0) {
// Not the same! // Not the same!
do_backup = true; do_backup = true;
fprintf(stderr, "Backup mismatch entry: "); fprintf(stderr, "Backup mismatch entry: ");
@ -189,10 +186,8 @@ void magisk_cpio::backup(const char *orig) {
} }
if (!rm_list.empty()) { if (!rm_list.empty()) {
auto rm_list_file = new cpio_entry(S_IFREG); byte_data rm(rm_list);
rm_list_file->filesize = rm_list.length(); auto rm_list_file = new cpio_entry(S_IFREG, rm);
rm_list_file->data = malloc(rm_list.length());
memcpy(rm_list_file->data, rm_list.data(), rm_list.length());
backups.emplace(".backup/.rmlist", rm_list_file); backups.emplace(".backup/.rmlist", rm_list_file);
} }