From 3ef07128a8ad8a12688beee244c5e0a2629581de Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 5 Jan 2016 03:30:08 +0200 Subject: [PATCH] wrap munmap to prevent unwanted unmaps --- loader/emu.c | 15 ++++++++++++++- loader/ginge_dyn.symver | 1 + loader/header.h | 1 + loader/override.c | 22 ++++++++++++++++++++++ loader/patches.c | 8 ++++++++ loader/realfuncs.h | 2 ++ 6 files changed, 48 insertions(+), 1 deletion(-) diff --git a/loader/emu.c b/loader/emu.c index 8dc6d51..f14b0fc 100644 --- a/loader/emu.c +++ b/loader/emu.c @@ -1081,7 +1081,7 @@ static void *emu_mmap_dev(unsigned int length, int prot, int flags, unsigned int err("warning: uppermem @ %08x overflows by %d bytes\n", offset, umem + length - umem_end); - dbg("upper mem @ %08x %d\n", offset, length); + dbg("upper mem @ %08x %x = %p\n", offset, length, umem); return umem; } @@ -1101,6 +1101,19 @@ void *emu_do_mmap(unsigned int length, int prot, int flags, int fd, unsigned int return MAP_FAILED; } +int emu_do_munmap(void *addr, unsigned int length) +{ + u8 *p = addr; + + // don't allow to unmap upper mem + if ((u8 *)mmsp2.umem <= p && p < (u8 *)mmsp2.umem + 0x2000000) { + dbg("ignoring munmap: %p %x\n", addr, length); + return 0; + } + + return -EAGAIN; +} + static void emu_sound_open(int fd) { #ifdef PND diff --git a/loader/ginge_dyn.symver b/loader/ginge_dyn.symver index 20d2cd4..93b953b 100644 --- a/loader/ginge_dyn.symver +++ b/loader/ginge_dyn.symver @@ -4,6 +4,7 @@ global: fopen; mmap; mmap2; + munmap; read; ioctl; sigaction; diff --git a/loader/header.h b/loader/header.h index b5241f6..f24457f 100644 --- a/loader/header.h +++ b/loader/header.h @@ -42,6 +42,7 @@ struct op_context; void emu_init(void *map_bottom); void emu_call_handle_op(struct op_context *op_ctx); void *emu_do_mmap(unsigned int length, int prot, int flags, int fd, unsigned int offset); +int emu_do_munmap(void *addr, unsigned int length); int emu_do_ioctl(int fd, int request, void *argp); int emu_read_gpiodev(void *buf, int count); void *emu_do_fopen(const char *path, const char *mode); diff --git a/loader/override.c b/loader/override.c index 8c91644..86de405 100644 --- a/loader/override.c +++ b/loader/override.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "realfuncs.h" #include "header.h" @@ -99,6 +100,18 @@ static void *w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_ } #define w_mmap2 w_mmap +static int w_munmap(void *addr, size_t length) +{ + int ret; + ret = emu_do_munmap(addr, length); + if (ret == -EAGAIN) + ret = munmap(addr, length); + + if (((long)&ret & 0xf0000000) == 0xb0000000) + strace("munmap(%p, %x) = %d\n", addr, length, ret); + return ret; +} + static ssize_t w_read(int fd, void *buf, size_t count) { ssize_t ret; @@ -227,6 +240,7 @@ static int w_chdir(const char *path) #undef open #undef fopen #undef mmap +#undef munmap #undef read #undef ioctl #undef sigaction @@ -256,6 +270,7 @@ static int w_chdir(const char *path) MAKE_WRAP_SYM(open); MAKE_WRAP_SYM(fopen); MAKE_WRAP_SYM(mmap); +MAKE_WRAP_SYM(munmap); MAKE_WRAP_SYM(read); MAKE_WRAP_SYM(ioctl); MAKE_WRAP_SYM(sigaction); @@ -281,6 +296,7 @@ static const struct { REAL_FUNC_NP(open), REAL_FUNC_NP(fopen), REAL_FUNC_NP(mmap), + REAL_FUNC_NP(munmap), REAL_FUNC_NP(read), REAL_FUNC_NP(ioctl), REAL_FUNC_NP(sigaction), @@ -295,6 +311,7 @@ static const struct { #define open p_real_open #define fopen p_real_fopen #define mmap p_real_mmap +#define munmap p_real_munmap #define read p_real_read #define ioctl p_real_ioctl #define sigaction p_real_sigaction @@ -331,6 +348,11 @@ void *real_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t of return mmap(addr, length, prot, flags, fd, offset); } +int real_munmap(void *addr, size_t length) +{ + return munmap(addr, length); +} + int real_read(int fd, void *buf, size_t count) { return read(fd, buf, count); diff --git a/loader/patches.c b/loader/patches.c index 673c3c5..5418c1c 100644 --- a/loader/patches.c +++ b/loader/patches.c @@ -33,6 +33,13 @@ static const unsigned int sig_mmap[] = { }; #define sig_mask_mmap sig_mask_all +static const unsigned int sig_munmap[] = { + 0xef90005b, // svc 0x90005b + 0xe3700a01, // cmn r0, #0x1000 + 0x312fff1e, // bxcc lr +}; +#define sig_mask_munmap sig_mask_all + static const unsigned int sig_mmap2[] = { 0xe52d5004, // push {r5} 0xe59d5008, // ldr r5, [sp, #8] @@ -132,6 +139,7 @@ static const struct { PATCH(open), PATCH(mmap), PATCH(mmap2), // mmap2 syscall + PATCH(munmap), PATCH(read), PATCH(ioctl), PATCH_(hw_ioctl, hw_ioctl, 1), diff --git a/loader/realfuncs.h b/loader/realfuncs.h index 43d2ddf..8a4fb58 100644 --- a/loader/realfuncs.h +++ b/loader/realfuncs.h @@ -13,6 +13,7 @@ int real_open(const char *pathname, int flags, ...); FILE *real_fopen(const char *path, const char *mode); void *real_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); +int real_munmap(void *addr, size_t length); int real_read(int fd, void *buf, size_t count); int real_ioctl(int fd, int request, void *argp); int real_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); @@ -27,6 +28,7 @@ int real_chdir(const char *path); #define open real_open #define fopen real_fopen #define mmap real_mmap +#define munmap real_munmap #define read real_read #define ioctl real_ioctl #define sigaction real_sigaction -- 2.39.5