From a19293cb7586223541d5f80ae58cbe29df03f87f Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sun, 8 Dec 2013 18:07:41 +0100 Subject: [PATCH] Move OS-dependent mprotect for module loading to grub-core/osdep/*/dl.c and implement windows variant. --- ChangeLog | 5 +++ grub-core/Makefile.core.def | 3 ++ grub-core/kern/dl.c | 20 +++++------- grub-core/osdep/dl.c | 5 +++ grub-core/osdep/unix/dl.c | 61 ++++++++++++++++++++++++++++++++++++ grub-core/osdep/windows/dl.c | 59 ++++++++++++++++++++++++++++++++++ include/grub/dl.h | 7 +++++ 7 files changed, 147 insertions(+), 13 deletions(-) create mode 100644 grub-core/osdep/dl.c create mode 100644 grub-core/osdep/unix/dl.c create mode 100644 grub-core/osdep/windows/dl.c diff --git a/ChangeLog b/ChangeLog index 07f8dfb96..6f90aada0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-12-08 Vladimir Serbinenko + + Move OS-dependent mprotect for module loading to grub-core/osdep/*/dl.c + and implement windows variant. + 2013-12-08 Vladimir Serbinenko Fix mips-emu compilation. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 57abb4910..0a4eba56b 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -282,6 +282,9 @@ kernel = { emu = osdep/emuconsole.c; extra_dist = osdep/unix/emuconsole.c; extra_dist = osdep/windows/emuconsole.c; + emu = osdep/dl.c; + extra_dist = osdep/unix/dl.c; + extra_dist = osdep/windows/dl.c; emu = osdep/sleep.c; emu = osdep/init.c; emu = osdep/emunet.c; diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index f01fcfd4f..90589f75b 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -38,10 +38,6 @@ #define GRUB_MODULES_MACHINE_READONLY #endif -#ifdef GRUB_MACHINE_EMU -#include -#endif - #pragma GCC diagnostic ignored "-Wcast-align" @@ -258,21 +254,15 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) #endif #ifdef GRUB_MACHINE_EMU - if (talign < 8192 * 16) - talign = 8192 * 16; - tsize = ALIGN_UP (tsize, 8192 * 16); -#endif - + mod->base = grub_osdep_dl_memalign (talign, tsize); +#else mod->base = grub_memalign (talign, tsize); +#endif if (!mod->base) return grub_errno; mod->sz = tsize; ptr = mod->base; -#ifdef GRUB_MACHINE_EMU - mprotect (mod->base, tsize, PROT_READ | PROT_WRITE | PROT_EXEC); -#endif - for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); i < e->e_shnum; i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) @@ -782,7 +772,11 @@ grub_dl_unload (grub_dl_t mod) grub_free (dep); } +#ifdef GRUB_MACHINE_EMU + grub_dl_osdep_dl_free (mod->base); +#else grub_free (mod->base); +#endif grub_free (mod->name); #ifdef GRUB_MODULES_MACHINE_READONLY grub_free (mod->symtab); diff --git a/grub-core/osdep/dl.c b/grub-core/osdep/dl.c new file mode 100644 index 000000000..c51174763 --- /dev/null +++ b/grub-core/osdep/dl.c @@ -0,0 +1,5 @@ +#if defined (__MINGW32__) || defined (__CYGWIN__) +#include "windows/dl.c" +#else +#include "unix/dl.c" +#endif diff --git a/grub-core/osdep/unix/dl.c b/grub-core/osdep/unix/dl.c new file mode 100644 index 000000000..562b101a2 --- /dev/null +++ b/grub-core/osdep/unix/dl.c @@ -0,0 +1,61 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +void * +grub_osdep_dl_memalign (grub_size_t align, grub_size_t size) +{ + void *ret; + if (align < 8192 * 16) + align = 8192 * 16; + size = ALIGN_UP (size, 8192 * 16); + +#if defined(HAVE_POSIX_MEMALIGN) + if (posix_memalign (&ret, align, size) != 0) + ret = 0; +#elif defined(HAVE_MEMALIGN) + ret = memalign (align, size); +#else +#error "Complete this" +#endif + + if (!ret) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + return NULL; + } + + mprotect (ret, size, PROT_READ | PROT_WRITE | PROT_EXEC); + return ret; +} + +void +grub_dl_osdep_dl_free (void *ptr) +{ + if (ptr) + free (ptr); +} diff --git a/grub-core/osdep/windows/dl.c b/grub-core/osdep/windows/dl.c new file mode 100644 index 000000000..b18a4a009 --- /dev/null +++ b/grub-core/osdep/windows/dl.c @@ -0,0 +1,59 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +void * +grub_osdep_dl_memalign (grub_size_t align, grub_size_t size) +{ + void *ret; + if (align > 4096) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("too large alignment")); + return NULL; + } + + size = ALIGN_UP (size, 4096); + + ret = VirtualAlloc (NULL, size, MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + + if (!ret) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + return NULL; + } + + return ret; +} + +void +grub_dl_osdep_dl_free (void *ptr) +{ + if (!ptr) + return; + VirtualFree (ptr, 0, MEM_RELEASE); +} diff --git a/include/grub/dl.h b/include/grub/dl.h index 6c758c01a..58b636f16 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -210,6 +210,13 @@ extern grub_dl_t EXPORT_VAR(grub_dl_head); #define FOR_DL_MODULES(var) FOR_LIST_ELEMENTS ((var), (grub_dl_head)) +#ifdef GRUB_MACHINE_EMU +void * +grub_osdep_dl_memalign (grub_size_t align, grub_size_t size); +void +grub_dl_osdep_dl_free (void *ptr); +#endif + static inline void grub_dl_init (grub_dl_t mod) {