mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-25 16:07:24 +00:00
Improve memory map tricks
- In `unmap_all`, replace readable pages atomically with mmap + mremap - Create new function `remap_all` to replace pages with equivalent anonymous copies to prevent simple maps name scanning
This commit is contained in:
parent
da38f59e62
commit
12647dcf30
@ -106,6 +106,7 @@ static void first_stage_entry() {
|
|||||||
// Load second stage
|
// Load second stage
|
||||||
setenv(INJECT_ENV_2, "1", 1);
|
setenv(INJECT_ENV_2, "1", 1);
|
||||||
void *handle = dlopen(path, RTLD_LAZY);
|
void *handle = dlopen(path, RTLD_LAZY);
|
||||||
|
remap_all(path);
|
||||||
|
|
||||||
// Revert path to 1st stage lib
|
// Revert path to 1st stage lib
|
||||||
*(strrchr(path, '.') - 1) = '1';
|
*(strrchr(path, '.') - 1) = '1';
|
||||||
|
@ -16,6 +16,9 @@ enum : int {
|
|||||||
// Unmap all pages matching the name
|
// Unmap all pages matching the name
|
||||||
void unmap_all(const char *name);
|
void unmap_all(const char *name);
|
||||||
|
|
||||||
|
// Remap all matching pages with anonymous pages
|
||||||
|
void remap_all(const char *name);
|
||||||
|
|
||||||
// Get library name + offset (from start of ELF), given function address
|
// Get library name + offset (from start of ELF), given function address
|
||||||
uintptr_t get_function_off(int pid, uintptr_t addr, char *lib);
|
uintptr_t get_function_off(int pid, uintptr_t addr, char *lib);
|
||||||
|
|
||||||
|
@ -12,15 +12,9 @@ struct map_info {
|
|||||||
uintptr_t end;
|
uintptr_t end;
|
||||||
uintptr_t off;
|
uintptr_t off;
|
||||||
int perms;
|
int perms;
|
||||||
char *path;
|
const char *path;
|
||||||
|
|
||||||
map_info() : start(0), end(0), off(0), perms(0), path(nullptr) {}
|
map_info() : start(0), end(0), off(0), perms(0), path(nullptr) {}
|
||||||
|
|
||||||
enum {
|
|
||||||
EXEC = (1 << 0),
|
|
||||||
WRITE = (1 << 1),
|
|
||||||
READ = (1 << 2),
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -43,11 +37,11 @@ static void parse_maps(int pid, Func fn) {
|
|||||||
|
|
||||||
// Parse permissions
|
// Parse permissions
|
||||||
if (perm[0] != '-')
|
if (perm[0] != '-')
|
||||||
info.perms |= map_info::READ;
|
info.perms |= PROT_READ;
|
||||||
if (perm[1] != '-')
|
if (perm[1] != '-')
|
||||||
info.perms |= map_info::WRITE;
|
info.perms |= PROT_WRITE;
|
||||||
if (perm[2] != '-')
|
if (perm[2] != '-')
|
||||||
info.perms |= map_info::EXEC;
|
info.perms |= PROT_EXEC;
|
||||||
|
|
||||||
info.path = line + path_off;
|
info.path = line + path_off;
|
||||||
|
|
||||||
@ -55,24 +49,46 @@ static void parse_maps(int pid, Func fn) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmap_all(const char *name) {
|
static vector<map_info> find_maps(const char *name) {
|
||||||
vector<map_info> unmaps;
|
vector<map_info> maps;
|
||||||
parse_maps(getpid(), [=, &unmaps](map_info &info) -> bool {
|
parse_maps(getpid(), [=, &maps](map_info &info) -> bool {
|
||||||
if (strcmp(info.path, name) == 0)
|
if (strcmp(info.path, name) == 0)
|
||||||
unmaps.emplace_back(info);
|
maps.emplace_back(info);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
for (map_info &info : unmaps) {
|
return maps;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unmap_all(const char *name) {
|
||||||
|
vector<map_info> maps = find_maps(name);
|
||||||
|
for (map_info &info : maps) {
|
||||||
void *addr = reinterpret_cast<void *>(info.start);
|
void *addr = reinterpret_cast<void *>(info.start);
|
||||||
size_t size = info.end - info.start;
|
size_t size = info.end - info.start;
|
||||||
munmap(addr, size);
|
if (info.perms & PROT_READ) {
|
||||||
if (info.perms & map_info::READ) {
|
|
||||||
// Make sure readable pages are still readable
|
// Make sure readable pages are still readable
|
||||||
xmmap(addr, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
|
void *dummy = xmmap(nullptr, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||||
|
mremap(dummy, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, addr);
|
||||||
|
} else {
|
||||||
|
munmap(addr, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remap_all(const char *name) {
|
||||||
|
vector<map_info> maps = find_maps(name);
|
||||||
|
for (map_info &info : maps) {
|
||||||
|
void *addr = reinterpret_cast<void *>(info.start);
|
||||||
|
size_t size = info.end - info.start;
|
||||||
|
void *copy = xmmap(nullptr, size, PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||||
|
if ((info.perms & PROT_READ) == 0) {
|
||||||
|
mprotect(addr, size, PROT_READ);
|
||||||
|
}
|
||||||
|
memcpy(copy, addr, size);
|
||||||
|
mremap(copy, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, addr);
|
||||||
|
mprotect(addr, size, info.perms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t get_function_off(int pid, uintptr_t addr, char *lib) {
|
uintptr_t get_function_off(int pid, uintptr_t addr, char *lib) {
|
||||||
uintptr_t off = 0;
|
uintptr_t off = 0;
|
||||||
parse_maps(pid, [=, &off](map_info &info) -> bool {
|
parse_maps(pid, [=, &off](map_info &info) -> bool {
|
||||||
@ -90,7 +106,7 @@ uintptr_t get_function_off(int pid, uintptr_t addr, char *lib) {
|
|||||||
uintptr_t get_function_addr(int pid, const char *lib, uintptr_t off) {
|
uintptr_t get_function_addr(int pid, const char *lib, uintptr_t off) {
|
||||||
uintptr_t addr = 0;
|
uintptr_t addr = 0;
|
||||||
parse_maps(pid, [=, &addr](map_info &info) -> bool {
|
parse_maps(pid, [=, &addr](map_info &info) -> bool {
|
||||||
if (strcmp(info.path, lib) == 0 && (info.perms & map_info::EXEC)) {
|
if (strcmp(info.path, lib) == 0 && (info.perms & PROT_EXEC)) {
|
||||||
addr = info.start - info.off + off;
|
addr = info.start - info.off + off;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user