diff --git a/src/Makefile.dep b/src/Makefile.dep index 5b35ddf5..97f8125a 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -138,8 +138,8 @@ lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \ lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ - lj_gc.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h lj_dispatch.h lj_bc.h \ - lj_traceerr.h lj_vm.h + lj_gc.h lj_err.h lj_errmsg.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h \ + lj_dispatch.h lj_bc.h lj_traceerr.h lj_vm.h lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \ lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h index e62dc237..8f01fdc7 100644 --- a/src/lj_errmsg.h +++ b/src/lj_errmsg.h @@ -100,6 +100,7 @@ ERRDEF(STRFMT, "invalid option " LUA_QS " to " LUA_QL("format")) ERRDEF(STRGSRV, "invalid replacement value (a %s)") ERRDEF(BADMODN, "name conflict for module " LUA_QS) #if LJ_HASJIT +ERRDEF(JITPROT, "runtime code generation failed, restricted kernel?") #if LJ_TARGET_X86ORX64 ERRDEF(NOJIT, "JIT compiler disabled, CPU does not support SSE2") #else diff --git a/src/lj_mcode.c b/src/lj_mcode.c index cb79e8cd..d464802b 100644 --- a/src/lj_mcode.c +++ b/src/lj_mcode.c @@ -9,6 +9,7 @@ #include "lj_obj.h" #if LJ_HASJIT #include "lj_gc.h" +#include "lj_err.h" #include "lj_jit.h" #include "lj_mcode.h" #include "lj_trace.h" @@ -78,10 +79,10 @@ static void mcode_free(jit_State *J, void *p, size_t sz) VirtualFree(p, 0, MEM_RELEASE); } -static void mcode_setprot(void *p, size_t sz, DWORD prot) +static int mcode_setprot(void *p, size_t sz, DWORD prot) { DWORD oprot; - VirtualProtect(p, sz, prot, &oprot); + return !VirtualProtect(p, sz, prot, &oprot); } #elif LJ_TARGET_POSIX @@ -112,9 +113,9 @@ static void mcode_free(jit_State *J, void *p, size_t sz) munmap(p, sz); } -static void mcode_setprot(void *p, size_t sz, int prot) +static int mcode_setprot(void *p, size_t sz, int prot) { - mprotect(p, sz, prot); + return mprotect(p, sz, prot); } #elif LJ_64 @@ -140,8 +141,6 @@ static void mcode_free(jit_State *J, void *p, size_t sz) lj_mem_free(J2G(J), p, sz); } -#define mcode_setprot(p, sz, prot) UNUSED(p) - #endif /* -- MCode area protection ----------------------------------------------- */ @@ -180,11 +179,23 @@ static void mcode_protect(jit_State *J, int prot) #define MCPROT_GEN MCPROT_RW #define MCPROT_RUN MCPROT_RX +/* Protection twiddling failed. Probably due to kernel security. */ +static LJ_NOINLINE void mcode_protfail(jit_State *J) +{ + lua_CFunction panic = J2G(J)->panic; + if (panic) { + lua_State *L = J->L; + setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITPROT)); + panic(L); + } +} + /* Change protection of MCode area. */ static void mcode_protect(jit_State *J, int prot) { if (J->mcprot != prot) { - mcode_setprot(J->mcarea, J->szmcarea, prot); + if (LJ_UNLIKELY(mcode_setprot(J->mcarea, J->szmcarea, prot))) + mcode_protfail(J); J->mcprot = prot; } } @@ -305,7 +316,8 @@ void lj_mcode_commit(jit_State *J, MCode *top) /* Abort the reservation. */ void lj_mcode_abort(jit_State *J) { - mcode_protect(J, MCPROT_RUN); + if (J->mcarea) + mcode_protect(J, MCPROT_RUN); } /* Set/reset protection to allow patching of MCode areas. */ @@ -318,8 +330,8 @@ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) if (finish) { if (J->mcarea == ptr) mcode_protect(J, MCPROT_RUN); - else - mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN); + else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN))) + mcode_protfail(J); return NULL; } else { MCode *mc = J->mcarea; @@ -333,7 +345,8 @@ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) mc = ((MCLink *)mc)->next; lua_assert(mc != NULL); if (ptr >= mc && ptr < (MCode *)((char *)mc + ((MCLink *)mc)->size)) { - mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN); + if (LJ_UNLIKELY(mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN))) + mcode_protfail(J); return mc; } }