From a44f53acf53603e7d9b88352de035b1804be4e88 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 15 Jun 2020 12:21:05 +0200 Subject: [PATCH] Use a securely seeded global PRNG for the VM. It's not 2005 anymore. --- src/Makefile | 4 +- src/Makefile.dep | 50 ++++++----- src/lib_aux.c | 8 +- src/lib_math.c | 53 +++-------- src/lj_alloc.c | 85 ++++++++---------- src/lj_alloc.h | 3 +- src/lj_arch.h | 15 ++++ src/lj_def.h | 5 ++ src/lj_ffrecord.c | 2 +- src/lj_ir.c | 2 +- src/lj_ircall.h | 2 +- src/lj_jit.h | 13 +-- src/lj_lib.h | 5 -- src/lj_mcode.c | 41 +++------ src/lj_obj.h | 1 + src/lj_prng.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++ src/lj_prng.h | 24 +++++ src/lj_record.c | 3 +- src/lj_state.c | 38 ++++++-- src/lj_state.h | 2 + src/lj_trace.c | 3 +- src/ljamalg.c | 1 + 22 files changed, 411 insertions(+), 174 deletions(-) create mode 100644 src/lj_prng.c create mode 100644 src/lj_prng.h diff --git a/src/Makefile b/src/Makefile index 667fff56..6a9de5db 100644 --- a/src/Makefile +++ b/src/Makefile @@ -485,8 +485,8 @@ LJLIB_C= $(LJLIB_O:.o=.c) LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ - lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \ - lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ + lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \ + lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ diff --git a/src/Makefile.dep b/src/Makefile.dep index 03dba96b..3f26599e 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,6 +1,6 @@ lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ - lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lj_alloc.h + lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \ @@ -28,7 +28,7 @@ lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \ lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ - lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h + lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_prng.h lj_libdef.h lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.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_lib.h \ lj_libdef.h @@ -41,7 +41,8 @@ lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.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_tab.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h -lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h +lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h \ + lj_prng.h lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ @@ -126,7 +127,7 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ - lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h + lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h lj_lex.o: lj_lex.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_ctype.h lj_cdata.h \ lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ @@ -140,7 +141,7 @@ lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.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_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_dispatch.h lj_bc.h lj_traceerr.h lj_prng.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 @@ -172,11 +173,12 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h +lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \ lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ - lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h + lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ @@ -184,7 +186,8 @@ lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_state.o: lj_state.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_func.h \ lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h \ - lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_alloc.h luajit.h + lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \ + lj_alloc.h luajit.h lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_err.h lj_errmsg.h lj_str.h lj_char.h lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ @@ -199,7 +202,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_frame.h lj_bc.h \ lj_state.h lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h \ lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \ - lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h + lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_udata.h lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ @@ -214,21 +217,22 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \ lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \ - lj_state.c lj_lex.h lj_alloc.h luajit.h lj_dispatch.c lj_ccallback.h \ - lj_profile.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c \ - lj_strfmt.c lj_strfmt_num.c lj_api.c lj_profile.c lj_lex.c lualib.h \ - lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c \ - lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h \ - lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h lj_carith.c \ - lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c \ - lj_ircall.h lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h \ - lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c \ - lj_opt_sink.c lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h \ - lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \ - lj_emit_*.h lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c \ - lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c \ - lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c \ - lib_ffi.c lib_init.c + lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \ + lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \ + lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \ + lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \ + lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \ + lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \ + lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \ + lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \ + lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ + lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ + lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ + lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ + lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ + lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ + lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ + lib_init.c luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ diff --git a/src/lib_aux.c b/src/lib_aux.c index 8f10e23c..35866f8d 100644 --- a/src/lib_aux.c +++ b/src/lib_aux.c @@ -345,17 +345,13 @@ LUALIB_API lua_State *luaL_newstate(void) #else -#include "lj_alloc.h" - LUALIB_API lua_State *luaL_newstate(void) { lua_State *L; - void *ud = lj_alloc_create(); - if (ud == NULL) return NULL; #if LJ_64 && !LJ_GC64 - L = lj_state_newstate(lj_alloc_f, ud); + L = lj_state_newstate(LJ_ALLOCF_INTERNAL, NULL); #else - L = lua_newstate(lj_alloc_f, ud); + L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL); #endif if (L) G(L)->panic = panic; return L; diff --git a/src/lib_math.c b/src/lib_math.c index 4cc2ba6e..95b7d460 100644 --- a/src/lib_math.c +++ b/src/lib_math.c @@ -15,6 +15,7 @@ #include "lj_obj.h" #include "lj_lib.h" #include "lj_vm.h" +#include "lj_prng.h" /* ------------------------------------------------------------------------ */ @@ -105,34 +106,11 @@ LJLIB_PUSH(1e310) LJLIB_SET(huge) ** Full-period ME-CF generator with L=64, J=4, k=223, N1=49. */ -/* PRNG state. */ -struct RandomState { - uint64_t gen[4]; /* State of the 4 LFSR generators. */ - int valid; /* State is valid. */ -}; - /* Union needed for bit-pattern conversion between uint64_t and double. */ typedef union { uint64_t u64; double d; } U64double; -/* Update generator i and compute a running xor of all states. */ -#define TW223_GEN(i, k, q, s) \ - z = rs->gen[i]; \ - z = (((z<> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<gen[i] = z; - -/* PRNG step function. Returns a double in the range 1.0 <= d < 2.0. */ -LJ_NOINLINE uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs) -{ - uint64_t z, r = 0; - TW223_GEN(0, 63, 31, 18) - TW223_GEN(1, 58, 19, 28) - TW223_GEN(2, 55, 24, 7) - TW223_GEN(3, 47, 21, 8) - return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000); -} - -/* PRNG initialization function. */ -static void random_init(RandomState *rs, double d) +/* PRNG seeding function. */ +static void random_seed(PRNGState *rs, double d) { uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */ int i; @@ -141,24 +119,22 @@ static void random_init(RandomState *rs, double d) uint32_t m = 1u << (r&255); r >>= 8; u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354; - if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of gen[i] are non-zero. */ - rs->gen[i] = u.u64; + if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of u[i] are non-zero. */ + rs->u[i] = u.u64; } - rs->valid = 1; for (i = 0; i < 10; i++) - lj_math_random_step(rs); + (void)lj_prng_u64(rs); } /* PRNG extract function. */ -LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */ +LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */ LJLIB_CF(math_random) LJLIB_REC(.) { int n = (int)(L->top - L->base); - RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); + PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); U64double u; double d; - if (LJ_UNLIKELY(!rs->valid)) random_init(rs, 0.0); - u.u64 = lj_math_random_step(rs); + u.u64 = lj_prng_u64d(rs); d = u.d - 1.0; if (n > 0) { #if LJ_DUALNUM @@ -203,11 +179,11 @@ LJLIB_CF(math_random) LJLIB_REC(.) } /* PRNG seed function. */ -LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */ +LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */ LJLIB_CF(math_randomseed) { - RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); - random_init(rs, lj_lib_checknum(L, 1)); + PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); + random_seed(rs, lj_lib_checknum(L, 1)); return 0; } @@ -217,9 +193,8 @@ LJLIB_CF(math_randomseed) LUALIB_API int luaopen_math(lua_State *L) { - RandomState *rs; - rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState)); - rs->valid = 0; /* Use lazy initialization to save some time on startup. */ + PRNGState *rs = (PRNGState *)lua_newuserdata(L, sizeof(PRNGState)); + lj_prng_seed_fixed(rs); LJ_LIB_REG(L, LUA_MATHLIBNAME, math); return 1; } diff --git a/src/lj_alloc.c b/src/lj_alloc.c index 70ca1e3b..bf2ae847 100644 --- a/src/lj_alloc.c +++ b/src/lj_alloc.c @@ -31,6 +31,7 @@ #include "lj_def.h" #include "lj_arch.h" #include "lj_alloc.h" +#include "lj_prng.h" #ifndef LUAJIT_USE_SYSMALLOC @@ -140,7 +141,7 @@ static void init_mmap(void) #define INIT_MMAP() init_mmap() /* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ -static void *CALL_MMAP(size_t size) +static void *mmap_plain(size_t size) { DWORD olderr = GetLastError(); void *ptr = NULL; @@ -164,7 +165,7 @@ static void *direct_mmap(size_t size) #else /* Win32 MMAP via VirtualAlloc */ -static void *CALL_MMAP(size_t size) +static void *mmap_plain(size_t size) { DWORD olderr = GetLastError(); void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); @@ -184,7 +185,8 @@ static void *direct_mmap(size_t size) #endif -#define DIRECT_MMAP(size) direct_mmap(size) +#define CALL_MMAP(prng, size) mmap_plain(size) +#define DIRECT_MMAP(prng, size) direct_mmap(size) /* This function supports releasing coalesed segments */ static int CALL_MUNMAP(void *ptr, size_t size) @@ -228,30 +230,10 @@ static int CALL_MUNMAP(void *ptr, size_t size) #define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000) -/* No point in a giant ifdef mess. Just try to open /dev/urandom. -** It doesn't really matter if this fails, since we get some ASLR bits from -** every unsuitable allocation, too. And we prefer linear allocation, anyway. -*/ -#include -#include - -static uintptr_t mmap_probe_seed(void) -{ - uintptr_t val; - int fd = open("/dev/urandom", O_RDONLY); - if (fd != -1) { - int ok = ((size_t)read(fd, &val, sizeof(val)) == sizeof(val)); - (void)close(fd); - if (ok) return val; - } - return 1; /* Punt. */ -} - -static void *mmap_probe(size_t size) +static void *mmap_probe(PRNGState *rs, size_t size) { /* Hint for next allocation. Doesn't need to be thread-safe. */ static uintptr_t hint_addr = 0; - static uintptr_t hint_prng = 0; int olderr = errno; int retry; for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) { @@ -283,15 +265,8 @@ static void *mmap_probe(size_t size) } } /* Finally, try pseudo-random probing. */ - if (LJ_UNLIKELY(hint_prng == 0)) { - hint_prng = mmap_probe_seed(); - } - /* The unsuitable address we got has some ASLR PRNG bits. */ - hint_addr ^= addr & ~((uintptr_t)(LJ_PAGESIZE-1)); - do { /* The PRNG itself is very weak, but see above. */ - hint_prng = hint_prng * 1103515245 + 12345; - hint_addr ^= hint_prng * (uintptr_t)LJ_PAGESIZE; - hint_addr &= (((uintptr_t)1 << LJ_ALLOC_MBITS)-1); + do { + hint_addr = lj_prng_u64(rs) & (((uintptr_t)1< nb)) { /* Check for wrap around 0 */ - char *mm = (char *)(DIRECT_MMAP(mmsize)); + char *mm = (char *)(DIRECT_MMAP(m->prng, mmsize)); if (mm != CMFAIL) { size_t offset = align_offset(chunk2mem(mm)); size_t psize = mmsize - offset - DIRECT_FOOT_PAD; @@ -853,6 +838,7 @@ static void *direct_alloc(size_t nb) return chunk2mem(p); } } + UNUSED(m); return NULL; } @@ -1001,7 +987,7 @@ static void *alloc_sys(mstate m, size_t nb) /* Directly map large chunks */ if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) { - void *mem = direct_alloc(nb); + void *mem = direct_alloc(m, nb); if (mem != 0) return mem; } @@ -1010,7 +996,7 @@ static void *alloc_sys(mstate m, size_t nb) size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; size_t rsize = granularity_align(req); if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */ - char *mp = (char *)(CALL_MMAP(rsize)); + char *mp = (char *)(CALL_MMAP(m->prng, rsize)); if (mp != CMFAIL) { tbase = mp; tsize = rsize; @@ -1237,12 +1223,13 @@ static void *tmalloc_small(mstate m, size_t nb) /* ----------------------------------------------------------------------- */ -void *lj_alloc_create(void) +void *lj_alloc_create(PRNGState *rs) { size_t tsize = DEFAULT_GRANULARITY; char *tbase; INIT_MMAP(); - tbase = (char *)(CALL_MMAP(tsize)); + UNUSED(rs); + tbase = (char *)(CALL_MMAP(rs, tsize)); if (tbase != CMFAIL) { size_t msize = pad_request(sizeof(struct malloc_state)); mchunkptr mn; @@ -1261,6 +1248,12 @@ void *lj_alloc_create(void) return NULL; } +void lj_alloc_setprng(void *msp, PRNGState *rs) +{ + mstate ms = (mstate)msp; + ms->prng = rs; +} + void lj_alloc_destroy(void *msp) { mstate ms = (mstate)msp; diff --git a/src/lj_alloc.h b/src/lj_alloc.h index f87a7cf3..669f50b7 100644 --- a/src/lj_alloc.h +++ b/src/lj_alloc.h @@ -9,7 +9,8 @@ #include "lj_def.h" #ifndef LUAJIT_USE_SYSMALLOC -LJ_FUNC void *lj_alloc_create(void); +LJ_FUNC void *lj_alloc_create(PRNGState *rs); +LJ_FUNC void lj_alloc_setprng(void *msp, PRNGState *rs); LJ_FUNC void lj_alloc_destroy(void *msp); LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize); #endif diff --git a/src/lj_arch.h b/src/lj_arch.h index 3e3581c2..626f6c13 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h @@ -633,4 +633,19 @@ extern void *LJ_WIN_LOADLIBA(const char *path); #define LJ_52 0 #endif +/* -- VM security --------------------------------------------------------- */ + +/* Don't make any changes here. Instead build with: +** make "XCFLAGS=-DLUAJIT_SECURITY_flag=value" +*/ + +/* Security defaults. */ +#ifndef LUAJIT_SECURITY_PRNG +#define LUAJIT_SECURITY_PRNG 1 +#endif + +#ifndef LUAJIT_SECURITY_MCODE +#define LUAJIT_SECURITY_MCODE 1 +#endif + #endif diff --git a/src/lj_def.h b/src/lj_def.h index af0687c4..e458c89f 100644 --- a/src/lj_def.h +++ b/src/lj_def.h @@ -372,4 +372,9 @@ static LJ_AINLINE uint32_t lj_getu32(const void *v) extern void LJ_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) #endif +/* PRNG state. Need this here, details in lj_prng.h. */ +typedef struct PRNGState { + uint64_t u[4]; +} PRNGState; + #endif diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index d34340ce..19da15a2 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c @@ -616,7 +616,7 @@ static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd) GCudata *ud = udataV(&J->fn->c.upvalue[0]); TRef tr, one; lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */ - tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud))); + tr = lj_ir_call(J, IRCALL_lj_prng_u64d, lj_ir_kptr(J, uddata(ud))); one = lj_ir_knum_one(J); tr = emitir(IRTN(IR_SUB), tr, one); if (J->base[0]) { diff --git a/src/lj_ir.c b/src/lj_ir.c index 600e432c..b5e94eb8 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c @@ -31,7 +31,7 @@ #include "lj_vm.h" #include "lj_strscan.h" #include "lj_strfmt.h" -#include "lj_lib.h" +#include "lj_prng.h" /* Some local macros to save typing. Undef'd at the end. */ #define IR(ref) (&J->cur.ir[(ref)]) diff --git a/src/lj_ircall.h b/src/lj_ircall.h index dbc8c0db..58cebc5d 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h @@ -172,7 +172,7 @@ typedef struct CCallInfo { _(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \ _(ANY, lj_gc_barrieruv, 2, FS, NIL, 0) \ _(ANY, lj_mem_newgco, 2, FS, PGC, CCI_L) \ - _(ANY, lj_math_random_step, 1, FS, NUM, CCI_CASTU64) \ + _(ANY, lj_prng_u64d, 1, FS, NUM, CCI_CASTU64) \ _(ANY, lj_vm_modi, 2, FN, INT, 0) \ _(ANY, log10, 1, N, NUM, XA_FP) \ _(ANY, exp, 1, N, NUM, XA_FP) \ diff --git a/src/lj_jit.h b/src/lj_jit.h index fa754b64..b0d90fcd 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h @@ -438,9 +438,9 @@ typedef struct jit_State { int32_t framedepth; /* Current frame depth. */ int32_t retdepth; /* Return frame depth (count of RETF). */ + uint32_t k32[LJ_K32__MAX]; /* Common 4 byte constants used by backends. */ TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */ - TValue k64[LJ_K64__MAX]; /* Common 8 byte constants used by backends. */ - uint32_t k32[LJ_K32__MAX]; /* Ditto for 4 byte constants. */ + TValue k64[LJ_K64__MAX]; /* Common 8 byte constants. */ IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */ IRRef irtoplim; /* Upper limit of instuction buffer (biased). */ @@ -472,7 +472,6 @@ typedef struct jit_State { HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */ uint32_t penaltyslot; /* Round-robin index into penalty slots. */ - uint32_t prngstate; /* PRNG state. */ #ifdef LUAJIT_ENABLE_TABLE_BUMP RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */ @@ -516,12 +515,4 @@ jit_State; #define lj_assertJ(c, ...) ((void)J) #endif -/* Trivial PRNG e.g. used for penalty randomization. */ -static LJ_AINLINE uint32_t LJ_PRNG_BITS(jit_State *J, int bits) -{ - /* Yes, this LCG is very weak, but that doesn't matter for our use case. */ - J->prngstate = J->prngstate * 1103515245 + 12345; - return J->prngstate >> (32-bits); -} - #endif diff --git a/src/lj_lib.h b/src/lj_lib.h index 83778b83..496bdb2a 100644 --- a/src/lj_lib.h +++ b/src/lj_lib.h @@ -107,9 +107,4 @@ LJ_FUNC int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, #define LIBINIT_FFID 0xfe #define LIBINIT_END 0xff -/* Exported library functions. */ - -typedef struct RandomState RandomState; -LJ_FUNC uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs); - #endif diff --git a/src/lj_mcode.c b/src/lj_mcode.c index e64c5878..b2d12118 100644 --- a/src/lj_mcode.c +++ b/src/lj_mcode.c @@ -14,6 +14,7 @@ #include "lj_mcode.h" #include "lj_trace.h" #include "lj_dispatch.h" +#include "lj_prng.h" #endif #if LJ_HASJIT || LJ_HASFFI #include "lj_vm.h" @@ -118,52 +119,34 @@ static int mcode_setprot(void *p, size_t sz, int prot) return mprotect(p, sz, prot); } -#elif LJ_64 - -#error "Missing OS support for explicit placement of executable memory" - #else -/* Fallback allocator. This will fail if memory is not executable by default. */ -#define LUAJIT_UNPROTECT_MCODE -#define MCPROT_RW 0 -#define MCPROT_RX 0 -#define MCPROT_RWX 0 - -static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot) -{ - UNUSED(hint); UNUSED(prot); - return lj_mem_new(J->L, sz); -} - -static void mcode_free(jit_State *J, void *p, size_t sz) -{ - lj_mem_free(J2G(J), p, sz); -} +#error "Missing OS support for explicit placement of executable memory" #endif /* -- MCode area protection ----------------------------------------------- */ -/* Define this ONLY if page protection twiddling becomes a bottleneck. */ -#ifdef LUAJIT_UNPROTECT_MCODE +#if LUAJIT_SECURITY_MCODE == 0 -/* It's generally considered to be a potential security risk to have +/* Define this ONLY if page protection twiddling becomes a bottleneck. +** +** It's generally considered to be a potential security risk to have ** pages with simultaneous write *and* execute access in a process. ** ** Do not even think about using this mode for server processes or -** apps handling untrusted external data (such as a browser). +** apps handling untrusted external data. ** ** The security risk is not in LuaJIT itself -- but if an adversary finds -** any *other* flaw in your C application logic, then any RWX memory page -** simplifies writing an exploit considerably. +** any *other* flaw in your C application logic, then any RWX memory pages +** simplify writing an exploit considerably. */ #define MCPROT_GEN MCPROT_RWX #define MCPROT_RUN MCPROT_RWX static void mcode_protect(jit_State *J, int prot) { - UNUSED(J); UNUSED(prot); + UNUSED(J); UNUSED(prot); UNUSED(mcode_setprot); } #else @@ -242,7 +225,7 @@ static void *mcode_alloc(jit_State *J, size_t sz) } /* Next try probing 64K-aligned pseudo-random addresses. */ do { - hint = LJ_PRNG_BITS(J, LJ_TARGET_JUMPRANGE-16) << 16; + hint = lj_prng_u64(&J2G(J)->prng) & ((1u<base or NULL. */ MRef ctype_state; /* Pointer to C type state. */ + PRNGState prng; /* Global PRNG state. */ GCRef gcroot[GCROOT_MAX]; /* GC roots. */ } global_State; diff --git a/src/lj_prng.c b/src/lj_prng.c new file mode 100644 index 00000000..62a6bbb7 --- /dev/null +++ b/src/lj_prng.c @@ -0,0 +1,225 @@ +/* +** Pseudo-random number generation. +** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h +*/ + +#define lj_prng_c +#define LUA_CORE + +/* To get the syscall prototype. */ +#if defined(__linux__) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif + +#include "lj_def.h" +#include "lj_arch.h" +#include "lj_prng.h" + +/* -- PRNG step function -------------------------------------------------- */ + +/* This implements a Tausworthe PRNG with period 2^223. Based on: +** Tables of maximally-equidistributed combined LFSR generators, +** Pierre L'Ecuyer, 1991, table 3, 1st entry. +** Full-period ME-CF generator with L=64, J=4, k=223, N1=49. +** +** Important note: This PRNG is NOT suitable for cryptographic use! +** +** But it works fine for math.random(), which has an API that's not +** suitable for cryptography, anyway. +** +** When used as a securely seeded global PRNG, it substantially raises +** the difficulty for various attacks on the VM. +*/ + +/* Update generator i and compute a running xor of all states. */ +#define TW223_GEN(rs, z, r, i, k, q, s) \ + z = rs->u[i]; \ + z = (((z<> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<u[i] = z; + +#define TW223_STEP(rs, z, r) \ + TW223_GEN(rs, z, r, 0, 63, 31, 18) \ + TW223_GEN(rs, z, r, 1, 58, 19, 28) \ + TW223_GEN(rs, z, r, 2, 55, 24, 7) \ + TW223_GEN(rs, z, r, 3, 47, 21, 8) + +/* PRNG step function with uint64_t result. */ +LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs) +{ + uint64_t z, r = 0; + TW223_STEP(rs, z, r) + return r; +} + +/* PRNG step function with double in uint64_t result. */ +LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs) +{ + uint64_t z, r = 0; + TW223_STEP(rs, z, r) + /* Returns a double bit pattern in the range 1.0 <= d < 2.0. */ + return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000); +} + +/* Condition seed: ensure k[i] MSB of u[i] are non-zero. */ +static LJ_AINLINE void lj_prng_condition(PRNGState *rs) +{ + if (rs->u[0] < (1u << 1)) rs->u[0] += (1u << 1); + if (rs->u[1] < (1u << 6)) rs->u[1] += (1u << 6); + if (rs->u[2] < (1u << 9)) rs->u[2] += (1u << 9); + if (rs->u[3] < (1u << 17)) rs->u[3] += (1u << 17); +} + +/* -- PRNG seeding from OS ------------------------------------------------ */ + +#if LUAJIT_SECURITY_PRNG == 0 + +/* Nothing to define. */ + +#elif LJ_TARGET_XBOX360 + +extern int XNetRandom(void *buf, unsigned int len); + +#elif LJ_TARGET_PS3 + +extern int sys_get_random_number(void *buf, uint64_t len); + +#elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA + +extern int sceRandomGetRandomNumber(void *buf, size_t len); + +#elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOXONE + +#define WIN32_LEAN_AND_MEAN +#include + +#if LJ_TARGET_UWP || LJ_TARGET_XBOXONE +/* Must use BCryptGenRandom. */ +#include +#pragma comment(lib, "bcrypt.lib") +#else +/* If you wonder about this mess, then search online for RtlGenRandom. */ +typedef BOOLEAN (WINAPI *PRGR)(void *buf, ULONG len); +static PRGR libfunc_rgr; +#endif + +#elif LJ_TARGET_POSIX + +#if LJ_TARGET_LINUX +/* Avoid a dependency on glibc 2.25+ and use the getrandom syscall instead. */ +#include +#elif LJ_TARGET_OSX || LJ_TARGET_BSD || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN +extern int getentropy(void *buf, size_t len); +#ifdef __ELF__ + __attribute__((weak)) +#endif +; +#endif + +/* For the /dev/urandom fallback. */ +#include +#include + +#endif + +#if LUAJIT_SECURITY_PRNG == 0 + +/* If you really don't care about security, then define +** LUAJIT_SECURITY_PRNG=0. This yields a predictable seed +** and provides NO SECURITY against various attacks on the VM. +** +** BTW: This is NOT the way to get predictable table iteration, +** predictable trace generation, predictable bytecode generation, etc. +*/ +int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs) +{ + lj_prng_seed_fixed(rs); /* The fixed seed is already conditioned. */ + return 1; +} + +#else + +/* Securely seed PRNG from system entropy. Returns 0 on failure. */ +int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs) +{ +#if LJ_TARGET_XBOX360 + + if (XNetRandom(rs->u, (unsigned int)sizeof(rs->u)) == 0) + goto ok; + +#elif LJ_TARGET_PS3 + + if (sys_get_random_number(rs->u, sizeof(rs->u)) == 0) + goto ok; + +#elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA + + if (sceRandomGetRandomNumber(rs->u, sizeof(rs->u) == 0) + goto ok; + +#elif LJ_TARGET_UWP || LJ_TARGET_XBOXONE + + if (BCryptGenRandom(NULL, (PUCHAR)(rs->u), (ULONG)sizeof(rs->u), + BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0) + goto ok; + +#elif LJ_TARGET_WINDOWS + + /* Keep the library loaded in case multiple VMs are started. */ + if (!libfunc_rgr) { + HMODULE lib = LJ_WIN_LOADLIBA("advapi32.dll"); + if (!lib) return 0; + libfunc_rgr = (PRGR)GetProcAddress(lib, "SystemFunction036"); + if (!libfunc_rgr) return 0; + } + if (libfunc_rgr(rs->u, (ULONG)sizeof(rs->u))) + goto ok; + +#elif LJ_TARGET_POSIX + +#if LJ_TARGET_LINUX && defined(SYS_getrandom) + + if (syscall(SYS_getrandom, rs->u, sizeof(rs->u), 0) == (long)sizeof(rs->u)) + goto ok; + +#elif LJ_TARGET_OSX || LJ_TARGET_BSD || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN + + if ((!__ELF__ || getentropy) && getentropy(rs->u, sizeof(rs->u)) == 0) + goto ok; + +#endif + + /* Fallback to /dev/urandom. This may fail if the device is not + ** existent or accessible in a chroot or container, or if the process + ** or the OS ran out of file descriptors. + */ + { + int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); + if (fd != -1) { + ssize_t n = read(fd, rs->u, sizeof(rs->u)); + (void)close(fd); + if (n == (ssize_t)sizeof(rs->u)) + goto ok; + } + } + +#else + + /* Add an elif above for your OS with a secure PRNG seed. + ** Note that fiddling around with rand(), getpid(), time() or coercing + ** ASLR to yield a few bits of randomness is not helpful. + ** If you don't want any security, then don't pretend you have any + ** and simply define LUAJIT_SECURITY_PRNG=0 for the build. + */ +#error "Missing secure PRNG seed for this OS" + +#endif + return 0; /* Fail. */ + +ok: + lj_prng_condition(rs); + (void)lj_prng_u64(rs); + return 1; /* Success. */ +} + +#endif + diff --git a/src/lj_prng.h b/src/lj_prng.h new file mode 100644 index 00000000..40c34a71 --- /dev/null +++ b/src/lj_prng.h @@ -0,0 +1,24 @@ +/* +** Pseudo-random number generation. +** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h +*/ + +#ifndef _LJ_PRNG_H +#define _LJ_PRNG_H + +#include "lj_def.h" + +LJ_FUNC int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs); +LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs); +LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs); + +/* This is just the precomputed result of lib_math.c:random_seed(rs, 0.0). */ +static LJ_AINLINE void lj_prng_seed_fixed(PRNGState *rs) +{ + rs->u[0] = U64x(a0d27757,0a345b8c); + rs->u[1] = U64x(764a296c,5d4aa64f); + rs->u[2] = U64x(51220704,070adeaa); + rs->u[3] = U64x(2a2717b5,a7b7b927); +} + +#endif diff --git a/src/lj_record.c b/src/lj_record.c index cfa48ecf..df428818 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -33,6 +33,7 @@ #include "lj_snap.h" #include "lj_dispatch.h" #include "lj_vm.h" +#include "lj_prng.h" /* Some local macros to save typing. Undef'd at the end. */ #define IR(ref) (&J->cur.ir[(ref)]) @@ -1696,7 +1697,7 @@ static void check_call_unroll(jit_State *J, TraceNo lnk) if (lnk) { /* Possible tail- or up-recursion. */ lj_trace_flush(J, lnk); /* Flush trace that only returns. */ /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ - hotcount_set(J2GG(J), J->pc+1, LJ_PRNG_BITS(J, 4)); + hotcount_set(J2GG(J), J->pc+1, lj_prng_u64(&J2G(J)->prng) & 15u); } lj_trace_err(J, LJ_TRERR_CUNROLL); } diff --git a/src/lj_state.c b/src/lj_state.c index 7081a474..a4d072be 100644 --- a/src/lj_state.c +++ b/src/lj_state.c @@ -25,6 +25,7 @@ #include "lj_trace.h" #include "lj_dispatch.h" #include "lj_vm.h" +#include "lj_prng.h" #include "lj_lex.h" #include "lj_alloc.h" #include "luajit.h" @@ -185,16 +186,33 @@ static void close_state(lua_State *L) } #if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC)) -lua_State *lj_state_newstate(lua_Alloc f, void *ud) +lua_State *lj_state_newstate(lua_Alloc allocf, void *allocd) #else -LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) +LUA_API lua_State *lua_newstate(lua_Alloc allocf, void *allocd) #endif { - GG_State *GG = (GG_State *)f(ud, NULL, 0, sizeof(GG_State)); - lua_State *L = &GG->L; - global_State *g = &GG->g; + PRNGState prng; + GG_State *GG; + lua_State *L; + global_State *g; + /* We need the PRNG for the memory allocator, so initialize this first. */ + if (!lj_prng_seed_secure(&prng)) { + lj_assertX(0, "secure PRNG seeding failed"); + /* Can only return NULL here, so this errors with "not enough memory". */ + return NULL; + } +#ifndef LUAJIT_USE_SYSMALLOC + if (allocf == LJ_ALLOCF_INTERNAL) { + allocd = lj_alloc_create(&prng); + if (!allocd) return NULL; + allocf = lj_alloc_f; + } +#endif + GG = (GG_State *)allocf(allocd, NULL, 0, sizeof(GG_State)); if (GG == NULL || !checkptrGC(GG)) return NULL; memset(GG, 0, sizeof(GG_State)); + L = &GG->L; + g = &GG->g; L->gct = ~LJ_TTHREAD; L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */ L->dummy_ffid = FF_C; @@ -202,8 +220,14 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED; g->strempty.marked = LJ_GC_WHITE0; g->strempty.gct = ~LJ_TSTR; - g->allocf = f; - g->allocd = ud; + g->allocf = allocf; + g->allocd = allocd; + g->prng = prng; +#ifndef LUAJIT_USE_SYSMALLOC + if (allocf == lj_alloc_f) { + lj_alloc_setprng(allocd, &g->prng); + } +#endif setgcref(g->mainthref, obj2gco(L)); setgcref(g->uvhead.prev, obj2gco(&g->uvhead)); setgcref(g->uvhead.next, obj2gco(&g->uvhead)); diff --git a/src/lj_state.h b/src/lj_state.h index 9a8c7d93..50fe9000 100644 --- a/src/lj_state.h +++ b/src/lj_state.h @@ -32,4 +32,6 @@ LJ_FUNC void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L); LJ_FUNC lua_State *lj_state_newstate(lua_Alloc f, void *ud); #endif +#define LJ_ALLOCF_INTERNAL ((lua_Alloc)(void *)(uintptr_t)(1237<<4)) + #endif diff --git a/src/lj_trace.c b/src/lj_trace.c index c4e728c6..77e9d05b 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c @@ -30,6 +30,7 @@ #include "lj_vm.h" #include "lj_vmevent.h" #include "lj_target.h" +#include "lj_prng.h" /* -- Error handling ------------------------------------------------------ */ @@ -384,7 +385,7 @@ static void penalty_pc(jit_State *J, GCproto *pt, BCIns *pc, TraceError e) if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */ /* First try to bump its hotcount several times. */ val = ((uint32_t)J->penalty[i].val << 1) + - LJ_PRNG_BITS(J, PENALTY_RNDBITS); + (lj_prng_u64(&J2G(J)->prng) & ((1u< PENALTY_MAX) { blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */ return; diff --git a/src/ljamalg.c b/src/ljamalg.c index 19980241..56585e6d 100644 --- a/src/ljamalg.c +++ b/src/ljamalg.c @@ -31,6 +31,7 @@ #include "lj_udata.c" #include "lj_meta.c" #include "lj_debug.c" +#include "lj_prng.c" #include "lj_state.c" #include "lj_dispatch.c" #include "lj_vmevent.c"