Minor code cleanups

This commit is contained in:
topjohnwu 2020-09-02 02:49:32 -07:00
parent 2eee335b5f
commit b73d5753f2
6 changed files with 101 additions and 73 deletions

View File

@ -24,6 +24,61 @@ using namespace std;
constexpr int (*init_applet_main[])(int, char *[]) =
{ magiskpolicy_main, magiskpolicy_main, nullptr };
int data_holder::patch(str_pairs list) {
int count = 0;
for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) {
for (auto [from, to] : list) {
if (memcmp(p, from.data(), from.length() + 1) == 0) {
LOGD("Replace [%s] -> [%s]\n", from.data(), to.data());
memset(p, 0, from.length());
memcpy(p, to.data(), to.length());
++count;
p += from.length();
}
}
}
return count;
}
void data_holder::consume(data_holder &other) {
buf = other.buf;
sz = other.sz;
other.buf = nullptr;
other.sz = 0;
}
template <>
auto_data<MMAP>::~auto_data<MMAP>() {
if (buf) munmap(buf, sz);
}
template <>
auto_data<HEAP>::~auto_data<HEAP>() {
free(buf);
}
auto_data<HEAP> raw_data::read(int fd) {
auto_data<HEAP> data;
fd_full_read(fd, data.buf, data.sz);
return data;
}
auto_data<HEAP> raw_data::read(const char *name) {
auto_data<HEAP> data;
full_read(name, data.buf, data.sz);
return data;
}
auto_data<MMAP> raw_data::mmap_rw(const char *name) {
auto_data<MMAP> data;
::mmap_rw(name, data.buf, data.sz);
return data;
}
// Explicit instantiation
template struct auto_data<HEAP>;
template struct auto_data<MMAP>;
static bool unxz(int fd, const uint8_t *buf, size_t size) {
uint8_t out[8192];
xz_crc32_init();

View File

@ -16,23 +16,32 @@ struct cmdline {
char hardware_plat[32];
};
struct raw_data {
struct data_holder {
uint8_t *buf = nullptr;
size_t sz = 0;
raw_data() = default;
raw_data(const raw_data&) = delete;
raw_data(raw_data &&d) {
buf = d.buf;
sz = d.sz;
d.buf = nullptr;
d.sz = 0;
}
~raw_data() {
free(buf);
}
using str_pairs = std::initializer_list<std::pair<std::string_view, std::string_view>>;
int patch(str_pairs list);
protected:
void consume(data_holder &other);
};
enum data_type { HEAP, MMAP };
template <data_type T>
struct auto_data : public data_holder {
auto_data<T>() = default;
auto_data<T>(const auto_data&) = delete;
auto_data<T>(auto_data<T> &&other) { consume(other); }
~auto_data<T>() {}
auto_data<T>& operator=(auto_data<T> &&other) { consume(other); return *this; }
};
namespace raw_data {
auto_data<HEAP> read(const char *name);
auto_data<HEAP> read(int fd);
auto_data<MMAP> mmap_rw(const char *name);
}
struct fstab_entry {
std::string dev;
std::string mnt_point;
@ -41,7 +50,7 @@ struct fstab_entry {
std::string fsmgr_flags;
fstab_entry() = default;
fstab_entry(const fstab_entry &o) = delete;
fstab_entry(const fstab_entry &) = delete;
fstab_entry(fstab_entry &&o) = default;
void to_file(FILE *fp);
};
@ -53,10 +62,7 @@ void load_kernel_info(cmdline *cmd);
int dump_magisk(const char *path, mode_t mode);
int magisk_proxy_main(int argc, char *argv[]);
void setup_klog();
void setup_tmp(const char *path, const raw_data &self, const raw_data &config);
using str_pairs = std::initializer_list<std::pair<std::string_view, std::string_view>>;
int raw_data_patch(void *addr, size_t sz, str_pairs list);
void setup_tmp(const char *path, const data_holder &self, const data_holder &config);
/***************
* Base classes
@ -85,7 +91,7 @@ public:
class MagiskInit : public BaseInit {
protected:
raw_data self;
auto_data<HEAP> self;
std::string persist_dir;
virtual void early_mount() = 0;
@ -96,7 +102,7 @@ public:
class SARBase : public MagiskInit {
protected:
raw_data config;
auto_data<HEAP> config;
std::vector<raw_file> overlays;
void backup_files();

View File

@ -219,7 +219,7 @@ static void mount_persist(const char *dev_base, const char *mnt_base) {
}
void RootFSInit::early_mount() {
full_read("/init", self.buf, self.sz);
self = raw_data::read("/init");
LOGD("Restoring /init\n");
rename("/.backup/init", "/init");
@ -236,9 +236,9 @@ void SARBase::backup_files() {
if (access("/overlay.d", F_OK) == 0)
backup_folder("/overlay.d", overlays);
full_read("/proc/self/exe", self.buf, self.sz);
self = raw_data::read("/proc/self/exe");
if (access("/.backup/.magisk", R_OK) == 0)
full_read("/.backup/.magisk", config.buf, config.sz);
config = raw_data::read("/.backup/.magisk");
}
void SARBase::mount_system_root() {
@ -304,14 +304,11 @@ void BaseInit::cleanup() {
static void patch_socket_name(const char *path) {
char rstr[16];
gen_rand_str(rstr, sizeof(rstr));
char *buf;
size_t size;
mmap_rw(path, buf, size);
raw_data_patch(buf, size, { make_pair(MAIN_SOCKET, rstr) });
munmap(buf, size);
auto bin = raw_data::mmap_rw(path);
bin.patch({ make_pair(MAIN_SOCKET, rstr) });
}
void setup_tmp(const char *path, const raw_data &self, const raw_data &config) {
void setup_tmp(const char *path, const data_holder &self, const data_holder &config) {
LOGD("Setup Magisk tmp at %s\n", path);
xmount("tmpfs", path, "tmpfs", 0, "mode=755");

View File

@ -81,29 +81,10 @@ static void load_overlay_rc(const char *overlay) {
}
}
int raw_data_patch(void *addr, size_t sz, str_pairs list) {
int count = 0;
for (uint8_t *p = (uint8_t *)addr, *eof = (uint8_t *)addr + sz; p < eof; ++p) {
for (auto &[from, to] : list) {
if (memcmp(p, from.data(), from.length() + 1) == 0) {
LOGD("Replace [%s] -> [%s]\n", from.data(), to.data());
memset(p, 0, from.length());
memcpy(p, to.data(), to.length());
++count;
p += from.length();
}
}
}
return count;
}
void RootFSInit::setup_rootfs() {
if (patch_sepolicy("/sepolicy")) {
char *addr;
size_t size;
mmap_rw("/init", addr, size);
raw_data_patch(addr, size, {make_pair(SPLIT_PLAT_CIL, "xxx")});
munmap(addr, size);
auto init = raw_data::mmap_rw("/init");
init.patch({ make_pair(SPLIT_PLAT_CIL, "xxx") });
}
// Handle overlays
@ -267,10 +248,9 @@ void SARBase::patch_rootdir() {
recreate_sbin(ROOTMIR "/sbin", true);
// Patch init
raw_data init;
int src = xopen("/init", O_RDONLY | O_CLOEXEC);
fd_full_read(src, init.buf, init.sz);
int patch_count = raw_data_patch(init.buf, init.sz, {
auto init = raw_data::read(src);
int patch_count = init.patch({
make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */
make_pair(MONOPOLICY, sepol) /* Redirect /sepolicy to custom path */
});
@ -283,9 +263,8 @@ void SARBase::patch_rootdir() {
if (patch_count != 2 && access(LIBSELINUX, F_OK) == 0) {
// init is dynamically linked, need to patch libselinux
raw_data lib;
full_read(LIBSELINUX, lib.buf, lib.sz);
raw_data_patch(lib.buf, lib.sz, {make_pair(MONOPOLICY, sepol)});
auto lib = raw_data::read(LIBSELINUX);
lib.patch({make_pair(MONOPOLICY, sepol)});
xmkdirs(dirname(ROOTOVL LIBSELINUX), 0755);
dest = xopen(ROOTOVL LIBSELINUX, O_CREAT | O_WRONLY | O_CLOEXEC, 0);
xwrite(dest, lib.buf, lib.sz);
@ -341,11 +320,8 @@ void SARBase::patch_rootdir() {
int magisk_proxy_main(int argc, char *argv[]) {
setup_klog();
raw_data config;
raw_data self;
full_read("/sbin/magisk", self.buf, self.sz);
full_read("/.backup/.magisk", config.buf, config.sz);
auto config = raw_data::read("/sbin/magisk");
auto self = raw_data::read("/.backup/.magisk");
xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr);

View File

@ -108,14 +108,9 @@ void FirstStageInit::prepare() {
sprintf(fstab_file, "fstab.%s", hw);
}
// Patch init to force ignore dt fstab
uint8_t *addr;
size_t sz;
mmap_rw("/init", addr, sz);
raw_data_patch(addr, sz, {
make_pair("android,fstab", "xxx") /* Force IsDtFstabCompatible() to return false */
});
munmap(addr, sz);
// Patch init to force IsDtFstabCompatible() return false
auto init = raw_data::mmap_rw("/init");
init.patch({ make_pair("android,fstab", "xxx") });
}
{
@ -150,9 +145,8 @@ void SARFirstStageInit::prepare() {
int src = xopen("/init", O_RDONLY);
int dest = xopen("/dev/init", O_CREAT | O_WRONLY, 0);
{
raw_data init;
fd_full_read(src, init.buf, init.sz);
raw_data_patch(init.buf, init.sz, { make_pair(INIT_PATH, REDIR_PATH) });
auto init = raw_data::read(dest);
init.patch({ make_pair(INIT_PATH, REDIR_PATH) });
write(dest, init.buf, init.sz);
fclone_attr(src, dest);
close(dest);

View File

@ -143,7 +143,7 @@ sepolicy *sepolicy::compile_split() {
sprintf(path, SYSEXT_POLICY_DIR "mapping/%s.cil", plat_ver);
if (access(path, R_OK) == 0)
load_cil(db, path);
cil_file = SYSEXT_POLICY_DIR "system_ext_sepolicy.cil";
if (access(cil_file, R_OK) == 0)
load_cil(db, cil_file);