mirror of
				https://github.com/topjohnwu/Magisk.git
				synced 2025-10-31 08:44:07 +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:
		| @@ -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; | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 topjohnwu
					topjohnwu