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;
}
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)

View File

@ -43,15 +43,23 @@ struct mount_info {
std::string fs_option;
};
struct heap_data;
struct byte_data {
using str_pairs = std::initializer_list<std::pair<std::string_view, std::string_view>>;
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<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(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; }
};

View File

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

View File

@ -6,18 +6,19 @@
#include <map>
#include <string_view>
#include <base.hpp>
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 {

View File

@ -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");

View File

@ -2,6 +2,8 @@
#include <sys/types.h>
#include <base.hpp>
#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);

View File

@ -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<char *>(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<char *>(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<char *>(buf), size, skip_encryption_pattern);
bool patch_encryption(byte_data &data) {
return remove_pattern(data, skip_encryption_pattern);
}

View File

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