Update mmap implementation

Always map memory as writable, but private when read-only
This commit is contained in:
topjohnwu 2021-01-12 22:50:55 -08:00
parent 9a28dd4f6e
commit f2cb3c38fe
9 changed files with 58 additions and 73 deletions

View File

@ -213,6 +213,6 @@ bool check_two_stage() {
if (access("/system/bin/init", F_OK) == 0)
return true;
// If we still have no indication, parse the original init and see what's up
auto init = raw_data::mmap_ro("/.backup/init");
auto init = mmap_data::ro("/.backup/init");
return init.contains("selinux_setup");
}

View File

@ -54,8 +54,8 @@ public:
class MagiskInit : public BaseInit {
protected:
auto_data<HEAP> self;
auto_data<HEAP> config;
mmap_data self;
mmap_data config;
std::string custom_rules_dir;
void mount_with_dt();

View File

@ -289,7 +289,7 @@ success:
}
void RootFSInit::early_mount() {
self = raw_data::read("/init");
self = mmap_data::ro("/init");
LOGD("Restoring /init\n");
rename("/.backup/init", "/init");
@ -301,9 +301,9 @@ void SARBase::backup_files() {
if (access("/overlay.d", F_OK) == 0)
backup_folder("/overlay.d", overlays);
self = raw_data::read("/proc/self/exe");
self = mmap_data::ro("/proc/self/exe");
if (access("/.backup/.magisk", R_OK) == 0)
config = raw_data::read("/.backup/.magisk");
config = mmap_data::ro("/.backup/.magisk");
}
void SARBase::mount_system_root() {
@ -346,7 +346,7 @@ void SARInit::early_mount() {
switch_root("/system_root");
{
auto init = raw_data::mmap_ro("/init");
auto init = mmap_data::ro("/init");
is_two_stage = init.contains("selinux_setup");
}
LOGD("is_two_stage: [%d]\n", is_two_stage);
@ -383,7 +383,7 @@ void BaseInit::exec_init() {
static void patch_socket_name(const char *path) {
char rstr[16];
gen_rand_str(rstr, sizeof(rstr));
auto bin = raw_data::mmap_rw(path);
auto bin = mmap_data::rw(path);
bin.patch({ make_pair(MAIN_SOCKET, rstr) });
}

View File

@ -2,7 +2,7 @@
using namespace std;
int data_holder::patch(str_pairs list) {
int mmap_data::patch(str_pairs list) {
if (buf == nullptr)
return 0;
int count = 0;
@ -20,7 +20,7 @@ int data_holder::patch(str_pairs list) {
return count;
}
bool data_holder::contains(string_view pattern) {
bool mmap_data::contains(string_view pattern) {
if (buf == nullptr)
return false;
for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) {
@ -32,33 +32,21 @@ bool data_holder::contains(string_view pattern) {
return false;
}
void data_holder::consume(data_holder &other) {
void mmap_data::consume(mmap_data &other) {
buf = other.buf;
sz = other.sz;
other.buf = nullptr;
other.sz = 0;
}
auto_data<HEAP> raw_data::read(int fd) {
auto_data<HEAP> data;
fd_full_read(fd, data.buf, data.sz);
mmap_data mmap_data::rw(const char *name) {
mmap_data data;
mmap_rw(name, 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;
}
auto_data<MMAP> raw_data::mmap_ro(const char *name) {
auto_data<MMAP> data;
::mmap_ro(name, data.buf, data.sz);
mmap_data mmap_data::ro(const char *name) {
mmap_data data;
mmap_ro(name, data.buf, data.sz);
return data;
}

View File

@ -2,31 +2,23 @@
#include <utils.hpp>
struct data_holder {
struct mmap_data {
uint8_t *buf = nullptr;
size_t sz = 0;
mmap_data() = default;
mmap_data(const mmap_data&) = delete;
mmap_data(mmap_data &&other) { consume(other); }
~mmap_data() { if (buf) munmap(buf, sz); }
mmap_data& operator=(mmap_data &&other) { consume(other); return *this; }
using str_pairs = std::initializer_list<std::pair<std::string_view, std::string_view>>;
int patch(str_pairs list);
bool contains(std::string_view pattern);
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; }
};
template <> inline auto_data<MMAP>::~auto_data<MMAP>() { if (buf) munmap(buf, sz); }
template <> inline auto_data<HEAP>::~auto_data<HEAP>() { free(buf); }
static mmap_data rw(const char *name);
static mmap_data ro(const char *name);
namespace raw_data {
auto_data<HEAP> read(const char *name);
auto_data<HEAP> read(int fd);
auto_data<MMAP> mmap_rw(const char *name);
auto_data<MMAP> mmap_ro(const char *name);
}
private:
void consume(mmap_data &other);
};

View File

@ -218,7 +218,7 @@ void SARBase::patch_rootdir() {
int patch_count;
{
int src = xopen("/init", O_RDONLY | O_CLOEXEC);
auto init = raw_data::read(src);
auto init = mmap_data::ro("/init");
patch_count = init.patch({
make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */
make_pair(MONOPOLICY, sepol) /* Redirect /sepolicy to custom path */
@ -233,7 +233,7 @@ void SARBase::patch_rootdir() {
if (patch_count != 2 && access(LIBSELINUX, F_OK) == 0) {
// init is dynamically linked, need to patch libselinux
auto lib = raw_data::read(LIBSELINUX);
auto lib = mmap_data::ro(LIBSELINUX);
lib.patch({make_pair(MONOPOLICY, sepol)});
xmkdirs(dirname(ROOTOVL LIBSELINUX), 0755);
int dest = xopen(ROOTOVL LIBSELINUX, O_CREAT | O_WRONLY | O_CLOEXEC, 0);
@ -301,7 +301,7 @@ void RootFSInit::patch_rootfs() {
}
if (patch_sepolicy("/sepolicy")) {
auto init = raw_data::mmap_rw("/init");
auto init = mmap_data::rw("/init");
init.patch({ make_pair(SPLIT_PLAT_CIL, "xxx") });
}
@ -331,8 +331,8 @@ void MagiskProxy::start() {
xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr);
// Backup stuffs before removing them
self = raw_data::read("/sbin/magisk");
config = raw_data::read("/.backup/.magisk");
self = mmap_data::ro("/sbin/magisk");
config = mmap_data::ro("/.backup/.magisk");
char custom_rules_dir[64];
custom_rules_dir[0] = '\0';
xreadlink(TMP_RULESDIR, custom_rules_dir, sizeof(custom_rules_dir));

View File

@ -114,7 +114,7 @@ void FirstStageInit::prepare() {
}
// Patch init to force IsDtFstabCompatible() return false
auto init = raw_data::mmap_rw("/init");
auto init = mmap_data::rw("/init");
init.patch({ make_pair("android,fstab", "xxx") });
}
@ -150,7 +150,7 @@ void SARInit::first_stage_prep() {
int src = xopen("/init", O_RDONLY);
int dest = xopen("/dev/init", O_CREAT | O_WRONLY, 0);
{
auto init = raw_data::read(src);
auto init = mmap_data::ro("/init");
init.patch({ make_pair(INIT_PATH, REDIR_PATH) });
write(dest, init.buf, init.sz);
fclone_attr(src, dest);

View File

@ -279,7 +279,6 @@ void *__mmap(const char *filename, size_t *size, bool rw) {
return nullptr;
}
struct stat st;
void *buf;
if (fstat(fd, &st)) {
*size = 0;
return nullptr;
@ -288,7 +287,9 @@ void *__mmap(const char *filename, size_t *size, bool rw) {
ioctl(fd, BLKGETSIZE64, size);
else
*size = st.st_size;
buf = *size > 0 ? xmmap(nullptr, *size, PROT_READ | (rw ? PROT_WRITE : 0), MAP_SHARED, fd, 0) : nullptr;
void *buf = *size > 0 ?
xmmap(nullptr, *size, PROT_READ | PROT_WRITE, rw ? MAP_SHARED : MAP_PRIVATE, fd, 0) :
nullptr;
close(fd);
return buf;
}
@ -437,3 +438,16 @@ sDIR make_dir(DIR *dp) {
sFILE make_file(FILE *fp) {
return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; });
}
raw_file::raw_file(raw_file &&o) {
path.swap(o.path);
attr = o.attr;
buf = o.buf;
sz = o.sz;
o.buf = nullptr;
o.sz = 0;
}
raw_file::~raw_file() {
free(buf);
}

View File

@ -21,22 +21,13 @@ struct file_attr {
struct raw_file {
std::string path;
file_attr attr;
uint8_t *buf = nullptr;
size_t sz = 0;
uint8_t *buf;
size_t sz;
raw_file() = default;
raw_file() : attr({}), buf(nullptr), sz(0) {}
raw_file(const raw_file&) = delete;
raw_file(raw_file &&d) {
path = std::move(d.path);
attr = d.attr;
buf = d.buf;
sz = d.sz;
d.buf = nullptr;
d.sz = 0;
}
~raw_file() {
free(buf);
}
raw_file(raw_file &&o);
~raw_file();
};
ssize_t fd_path(int fd, char *path, size_t size);