diff options
Diffstat (limited to 'src/lj_mcode.c')
| -rw-r--r-- | src/lj_mcode.c | 255 |
1 files changed, 158 insertions, 97 deletions
diff --git a/src/lj_mcode.c b/src/lj_mcode.c index 2b8ac2df..c3032f4e 100644 --- a/src/lj_mcode.c +++ b/src/lj_mcode.c | |||
| @@ -63,31 +63,46 @@ void lj_mcode_sync(void *start, void *end) | |||
| 63 | 63 | ||
| 64 | #if LJ_HASJIT | 64 | #if LJ_HASJIT |
| 65 | 65 | ||
| 66 | #if LUAJIT_SECURITY_MCODE != 0 | ||
| 67 | /* Protection twiddling failed. Probably due to kernel security. */ | ||
| 68 | static LJ_NORET LJ_NOINLINE void mcode_protfail(jit_State *J) | ||
| 69 | { | ||
| 70 | lua_CFunction panic = J2G(J)->panic; | ||
| 71 | if (panic) { | ||
| 72 | lua_State *L = J->L; | ||
| 73 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITPROT)); | ||
| 74 | panic(L); | ||
| 75 | } | ||
| 76 | exit(EXIT_FAILURE); | ||
| 77 | } | ||
| 78 | #endif | ||
| 79 | |||
| 66 | #if LJ_TARGET_WINDOWS | 80 | #if LJ_TARGET_WINDOWS |
| 67 | 81 | ||
| 68 | #define MCPROT_RW PAGE_READWRITE | 82 | #define MCPROT_RW PAGE_READWRITE |
| 69 | #define MCPROT_RX PAGE_EXECUTE_READ | 83 | #define MCPROT_RX PAGE_EXECUTE_READ |
| 70 | #define MCPROT_RWX PAGE_EXECUTE_READWRITE | 84 | #define MCPROT_RWX PAGE_EXECUTE_READWRITE |
| 71 | 85 | ||
| 72 | static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, DWORD prot) | 86 | static void *mcode_alloc_at(uintptr_t hint, size_t sz, DWORD prot) |
| 73 | { | 87 | { |
| 74 | void *p = LJ_WIN_VALLOC((void *)hint, sz, | 88 | return LJ_WIN_VALLOC((void *)hint, sz, |
| 75 | MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, prot); | 89 | MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, prot); |
| 76 | if (!p && !hint) | ||
| 77 | lj_trace_err(J, LJ_TRERR_MCODEAL); | ||
| 78 | return p; | ||
| 79 | } | 90 | } |
| 80 | 91 | ||
| 81 | static void mcode_free(jit_State *J, void *p, size_t sz) | 92 | static void mcode_free(void *p, size_t sz) |
| 82 | { | 93 | { |
| 83 | UNUSED(J); UNUSED(sz); | 94 | UNUSED(sz); |
| 84 | VirtualFree(p, 0, MEM_RELEASE); | 95 | VirtualFree(p, 0, MEM_RELEASE); |
| 85 | } | 96 | } |
| 86 | 97 | ||
| 87 | static int mcode_setprot(void *p, size_t sz, DWORD prot) | 98 | static void mcode_setprot(jit_State *J, void *p, size_t sz, DWORD prot) |
| 88 | { | 99 | { |
| 100 | #if LUAJIT_SECURITY_MCODE != 0 | ||
| 89 | DWORD oprot; | 101 | DWORD oprot; |
| 90 | return !LJ_WIN_VPROTECT(p, sz, prot, &oprot); | 102 | if (!LJ_WIN_VPROTECT(p, sz, prot, &oprot)) mcode_protfail(J); |
| 103 | #else | ||
| 104 | UNUSED(J); UNUSED(p); UNUSED(sz); UNUSED(prot); | ||
| 105 | #endif | ||
| 91 | } | 106 | } |
| 92 | 107 | ||
| 93 | #elif LJ_TARGET_POSIX | 108 | #elif LJ_TARGET_POSIX |
| @@ -117,33 +132,33 @@ static int mcode_setprot(void *p, size_t sz, DWORD prot) | |||
| 117 | #define MCPROT_CREATE 0 | 132 | #define MCPROT_CREATE 0 |
| 118 | #endif | 133 | #endif |
| 119 | 134 | ||
| 120 | static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot) | 135 | static void *mcode_alloc_at(uintptr_t hint, size_t sz, int prot) |
| 121 | { | 136 | { |
| 122 | void *p = mmap((void *)hint, sz, prot|MCPROT_CREATE, MAP_PRIVATE|MAP_ANONYMOUS|MCMAP_CREATE, -1, 0); | 137 | void *p = mmap((void *)hint, sz, prot|MCPROT_CREATE, MAP_PRIVATE|MAP_ANONYMOUS|MCMAP_CREATE, -1, 0); |
| 123 | if (p == MAP_FAILED) { | 138 | if (p == MAP_FAILED) return NULL; |
| 124 | if (!hint) lj_trace_err(J, LJ_TRERR_MCODEAL); | ||
| 125 | p = NULL; | ||
| 126 | #if MCMAP_CREATE | 139 | #if MCMAP_CREATE |
| 127 | } else { | 140 | pthread_jit_write_protect_np(0); |
| 128 | pthread_jit_write_protect_np(0); | ||
| 129 | #endif | 141 | #endif |
| 130 | } | ||
| 131 | return p; | 142 | return p; |
| 132 | } | 143 | } |
| 133 | 144 | ||
| 134 | static void mcode_free(jit_State *J, void *p, size_t sz) | 145 | static void mcode_free(void *p, size_t sz) |
| 135 | { | 146 | { |
| 136 | UNUSED(J); | ||
| 137 | munmap(p, sz); | 147 | munmap(p, sz); |
| 138 | } | 148 | } |
| 139 | 149 | ||
| 140 | static int mcode_setprot(void *p, size_t sz, int prot) | 150 | static void mcode_setprot(jit_State *J, void *p, size_t sz, int prot) |
| 141 | { | 151 | { |
| 152 | #if LUAJIT_SECURITY_MCODE != 0 | ||
| 142 | #if MCMAP_CREATE | 153 | #if MCMAP_CREATE |
| 154 | UNUSED(J); UNUSED(p); UNUSED(sz); | ||
| 143 | pthread_jit_write_protect_np((prot & PROT_EXEC)); | 155 | pthread_jit_write_protect_np((prot & PROT_EXEC)); |
| 144 | return 0; | 156 | return 0; |
| 145 | #else | 157 | #else |
| 146 | return mprotect(p, sz, prot); | 158 | if (mprotect(p, sz, prot)) mcode_protfail(J); |
| 159 | #endif | ||
| 160 | #else | ||
| 161 | UNUSED(J); UNUSED(p); UNUSED(sz); UNUSED(prot); | ||
| 147 | #endif | 162 | #endif |
| 148 | } | 163 | } |
| 149 | 164 | ||
| @@ -153,6 +168,49 @@ static int mcode_setprot(void *p, size_t sz, int prot) | |||
| 153 | 168 | ||
| 154 | #endif | 169 | #endif |
| 155 | 170 | ||
| 171 | #ifdef LUAJIT_MCODE_TEST | ||
| 172 | /* Test wrapper for mcode allocation. DO NOT ENABLE in production! Try: | ||
| 173 | ** LUAJIT_MCODE_TEST=hhhhhhhhhhhhhhhh luajit -jv main.lua | ||
| 174 | ** LUAJIT_MCODE_TEST=F luajit -jv main.lua | ||
| 175 | */ | ||
| 176 | static void *mcode_alloc_at_TEST(jit_State *J, uintptr_t hint, size_t sz, int prot) | ||
| 177 | { | ||
| 178 | static int test_ofs = 0; | ||
| 179 | static const char *test_str; | ||
| 180 | if (!test_str) { | ||
| 181 | test_str = getenv("LUAJIT_MCODE_TEST"); | ||
| 182 | if (!test_str) test_str = ""; | ||
| 183 | } | ||
| 184 | switch (test_str[test_ofs]) { | ||
| 185 | case 'a': /* OK for one allocation. */ | ||
| 186 | test_ofs++; | ||
| 187 | /* fallthrough */ | ||
| 188 | case '\0': /* EOS: OK for any further allocations. */ | ||
| 189 | break; | ||
| 190 | case 'h': /* Ignore one hint. */ | ||
| 191 | test_ofs++; | ||
| 192 | /* fallthrough */ | ||
| 193 | case 'H': /* Ignore any further hints. */ | ||
| 194 | hint = 0u; | ||
| 195 | break; | ||
| 196 | case 'r': /* Randomize one hint. */ | ||
| 197 | test_ofs++; | ||
| 198 | /* fallthrough */ | ||
| 199 | case 'R': /* Randomize any further hints. */ | ||
| 200 | hint = lj_prng_u64(&J2G(J)->prng) & ~(uintptr_t)0xffffu; | ||
| 201 | hint &= ((uintptr_t)1 << (LJ_64 ? 47 : 31)) - 1; | ||
| 202 | break; | ||
| 203 | case 'f': /* Fail one allocation. */ | ||
| 204 | test_ofs++; | ||
| 205 | /* fallthrough */ | ||
| 206 | default: /* 'F' or unknown: Fail any further allocations. */ | ||
| 207 | return NULL; | ||
| 208 | } | ||
| 209 | return mcode_alloc_at(hint, sz, prot); | ||
| 210 | } | ||
| 211 | #define mcode_alloc_at(hint, sz, prot) mcode_alloc_at_TEST(J, hint, sz, prot) | ||
| 212 | #endif | ||
| 213 | |||
| 156 | /* -- MCode area protection ----------------------------------------------- */ | 214 | /* -- MCode area protection ----------------------------------------------- */ |
| 157 | 215 | ||
| 158 | #if LUAJIT_SECURITY_MCODE == 0 | 216 | #if LUAJIT_SECURITY_MCODE == 0 |
| @@ -174,7 +232,7 @@ static int mcode_setprot(void *p, size_t sz, int prot) | |||
| 174 | 232 | ||
| 175 | static void mcode_protect(jit_State *J, int prot) | 233 | static void mcode_protect(jit_State *J, int prot) |
| 176 | { | 234 | { |
| 177 | UNUSED(J); UNUSED(prot); UNUSED(mcode_setprot); | 235 | UNUSED(J); UNUSED(prot); |
| 178 | } | 236 | } |
| 179 | 237 | ||
| 180 | #else | 238 | #else |
| @@ -190,24 +248,11 @@ static void mcode_protect(jit_State *J, int prot) | |||
| 190 | #define MCPROT_GEN MCPROT_RW | 248 | #define MCPROT_GEN MCPROT_RW |
| 191 | #define MCPROT_RUN MCPROT_RX | 249 | #define MCPROT_RUN MCPROT_RX |
| 192 | 250 | ||
| 193 | /* Protection twiddling failed. Probably due to kernel security. */ | ||
| 194 | static LJ_NORET LJ_NOINLINE void mcode_protfail(jit_State *J) | ||
| 195 | { | ||
| 196 | lua_CFunction panic = J2G(J)->panic; | ||
| 197 | if (panic) { | ||
| 198 | lua_State *L = J->L; | ||
| 199 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITPROT)); | ||
| 200 | panic(L); | ||
| 201 | } | ||
| 202 | exit(EXIT_FAILURE); | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Change protection of MCode area. */ | 251 | /* Change protection of MCode area. */ |
| 206 | static void mcode_protect(jit_State *J, int prot) | 252 | static void mcode_protect(jit_State *J, int prot) |
| 207 | { | 253 | { |
| 208 | if (J->mcprot != prot) { | 254 | if (J->mcprot != prot) { |
| 209 | if (LJ_UNLIKELY(mcode_setprot(J->mcarea, J->szmcarea, prot))) | 255 | mcode_setprot(J, J->mcarea, J->szmcarea, prot); |
| 210 | mcode_protfail(J); | ||
| 211 | J->mcprot = prot; | 256 | J->mcprot = prot; |
| 212 | } | 257 | } |
| 213 | } | 258 | } |
| @@ -216,47 +261,74 @@ static void mcode_protect(jit_State *J, int prot) | |||
| 216 | 261 | ||
| 217 | /* -- MCode area allocation ----------------------------------------------- */ | 262 | /* -- MCode area allocation ----------------------------------------------- */ |
| 218 | 263 | ||
| 219 | #if LJ_64 | ||
| 220 | #define mcode_validptr(p) (p) | ||
| 221 | #else | ||
| 222 | #define mcode_validptr(p) ((p) && (uintptr_t)(p) < 0xffff0000) | ||
| 223 | #endif | ||
| 224 | |||
| 225 | #ifdef LJ_TARGET_JUMPRANGE | 264 | #ifdef LJ_TARGET_JUMPRANGE |
| 226 | 265 | ||
| 227 | /* Get memory within relative jump distance of our code in 64 bit mode. */ | 266 | #define MCODE_RANGE64 ((1u << LJ_TARGET_JUMPRANGE) - 0x10000u) |
| 228 | static void *mcode_alloc(jit_State *J, size_t sz) | 267 | |
| 268 | /* Set a memory range for mcode allocation with addr in the middle. */ | ||
| 269 | static void mcode_setrange(jit_State *J, uintptr_t addr) | ||
| 229 | { | 270 | { |
| 230 | /* Target an address in the static assembler code (64K aligned). | ||
| 231 | ** Try addresses within a distance of target-range/2+1MB..target+range/2-1MB. | ||
| 232 | ** Use half the jump range so every address in the range can reach any other. | ||
| 233 | */ | ||
| 234 | #if LJ_TARGET_MIPS | 271 | #if LJ_TARGET_MIPS |
| 235 | /* Use the middle of the 256MB-aligned region. */ | 272 | /* Use the whole 256MB-aligned region. */ |
| 236 | uintptr_t target = ((uintptr_t)(void *)lj_vm_exit_handler & | 273 | J->mcmin = addr & ~(uintptr_t)((1u << LJ_TARGET_JUMPRANGE) - 1); |
| 237 | ~(uintptr_t)0x0fffffffu) + 0x08000000u; | 274 | J->mcmax = J->mcmin + (1u << LJ_TARGET_JUMPRANGE); |
| 238 | #else | 275 | #else |
| 239 | uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff; | 276 | /* Every address in the 64KB-aligned range should be able to reach |
| 277 | ** any other, so MCODE_RANGE64 is only half the (signed) branch range. | ||
| 278 | */ | ||
| 279 | J->mcmin = (addr - (MCODE_RANGE64 >> 1) + 0xffffu) & ~(uintptr_t)0xffffu; | ||
| 280 | J->mcmax = J->mcmin + MCODE_RANGE64; | ||
| 240 | #endif | 281 | #endif |
| 241 | const uintptr_t range = (1u << (LJ_TARGET_JUMPRANGE-1)) - (1u << 21); | 282 | /* Avoid wrap-around and the 64KB corners. */ |
| 242 | /* First try a contiguous area below the last one. */ | 283 | if (addr < J->mcmin || !J->mcmin) J->mcmin = 0x10000u; |
| 243 | uintptr_t hint = J->mcarea ? (uintptr_t)J->mcarea - sz : 0; | 284 | if (addr > J->mcmax) J->mcmax = ~(uintptr_t)0xffffu; |
| 244 | int i; | 285 | } |
| 245 | /* Limit probing iterations, depending on the available pool size. */ | 286 | |
| 246 | for (i = 0; i < LJ_TARGET_JUMPRANGE; i++) { | 287 | /* Check if an address is in range of the mcode allocation range. */ |
| 247 | if (mcode_validptr(hint)) { | 288 | static LJ_AINLINE int mcode_inrange(jit_State *J, uintptr_t addr, size_t sz) |
| 248 | void *p = mcode_alloc_at(J, hint, sz, MCPROT_GEN); | 289 | { |
| 249 | 290 | /* Take care of unsigned wrap-around of addr + sz, too. */ | |
| 250 | if (mcode_validptr(p) && | 291 | return addr >= J->mcmin && addr + sz >= J->mcmin && addr + sz <= J->mcmax; |
| 251 | ((uintptr_t)p + sz - target < range || target - (uintptr_t)p < range)) | 292 | } |
| 252 | return p; | 293 | |
| 253 | if (p) mcode_free(J, p, sz); /* Free badly placed area. */ | 294 | /* Get memory within a specific jump range in 64 bit mode. */ |
| 254 | } | 295 | static void *mcode_alloc(jit_State *J, size_t sz) |
| 255 | /* Next try probing 64K-aligned pseudo-random addresses. */ | 296 | { |
| 297 | uintptr_t hint; | ||
| 298 | int i = 0, j; | ||
| 299 | if (!J->mcmin) /* Place initial range near the interpreter code. */ | ||
| 300 | mcode_setrange(J, (uintptr_t)(void *)lj_vm_exit_handler); | ||
| 301 | else if (!J->mcmax) /* Switch to a new range (already flushed). */ | ||
| 302 | goto newrange; | ||
| 303 | /* First try a contiguous area below the last one (if in range). */ | ||
| 304 | hint = (uintptr_t)J->mcarea - sz; | ||
| 305 | if (!mcode_inrange(J, hint, sz)) /* Also takes care of NULL J->mcarea. */ | ||
| 306 | goto probe; | ||
| 307 | for (; i < 16; i++) { | ||
| 308 | void *p = mcode_alloc_at(hint, sz, MCPROT_GEN); | ||
| 309 | if (mcode_inrange(J, (uintptr_t)p, sz)) | ||
| 310 | return p; /* Success. */ | ||
| 311 | else if (p) | ||
| 312 | mcode_free(p, sz); /* Free badly placed area. */ | ||
| 313 | probe: | ||
| 314 | /* Next try probing 64KB-aligned pseudo-random addresses. */ | ||
| 315 | j = 0; | ||
| 256 | do { | 316 | do { |
| 257 | hint = lj_prng_u64(&J2G(J)->prng) & ((1u<<LJ_TARGET_JUMPRANGE)-0x10000); | 317 | hint = J->mcmin + (lj_prng_u64(&J2G(J)->prng) & MCODE_RANGE64); |
| 258 | } while (!(hint + sz < range+range)); | 318 | if (++j > 15) goto fail; |
| 259 | hint = target + hint - range; | 319 | } while (!mcode_inrange(J, hint, sz)); |
| 320 | } | ||
| 321 | fail: | ||
| 322 | if (!J->mcarea) { /* Switch to a new range now. */ | ||
| 323 | void *p; | ||
| 324 | newrange: | ||
| 325 | p = mcode_alloc_at(0, sz, MCPROT_GEN); | ||
| 326 | if (p) { | ||
| 327 | mcode_setrange(J, (uintptr_t)p + (sz >> 1)); | ||
| 328 | return p; /* Success. */ | ||
| 329 | } | ||
| 330 | } else { | ||
| 331 | J->mcmax = 0; /* Switch to a new range after the flush. */ | ||
| 260 | } | 332 | } |
| 261 | lj_trace_err(J, LJ_TRERR_MCODEAL); /* Give up. OS probably ignores hints? */ | 333 | lj_trace_err(J, LJ_TRERR_MCODEAL); /* Give up. OS probably ignores hints? */ |
| 262 | return NULL; | 334 | return NULL; |
| @@ -269,15 +341,13 @@ static void *mcode_alloc(jit_State *J, size_t sz) | |||
| 269 | { | 341 | { |
| 270 | #if defined(__OpenBSD__) || defined(__NetBSD__) || LJ_TARGET_UWP | 342 | #if defined(__OpenBSD__) || defined(__NetBSD__) || LJ_TARGET_UWP |
| 271 | /* Allow better executable memory allocation for OpenBSD W^X mode. */ | 343 | /* Allow better executable memory allocation for OpenBSD W^X mode. */ |
| 272 | void *p = mcode_alloc_at(J, 0, sz, MCPROT_RUN); | 344 | void *p = mcode_alloc_at(0, sz, MCPROT_RUN); |
| 273 | if (p && mcode_setprot(p, sz, MCPROT_GEN)) { | 345 | if (p) mcode_setprot(J, p, sz, MCPROT_GEN); |
| 274 | mcode_free(J, p, sz); | ||
| 275 | return NULL; | ||
| 276 | } | ||
| 277 | return p; | ||
| 278 | #else | 346 | #else |
| 279 | return mcode_alloc_at(J, 0, sz, MCPROT_GEN); | 347 | void *p = mcode_alloc_at(0, sz, MCPROT_GEN); |
| 280 | #endif | 348 | #endif |
| 349 | if (!p) lj_trace_err(J, LJ_TRERR_MCODEAL); | ||
| 350 | return p; | ||
| 281 | } | 351 | } |
| 282 | 352 | ||
| 283 | #endif | 353 | #endif |
| @@ -289,7 +359,6 @@ static void mcode_allocarea(jit_State *J) | |||
| 289 | { | 359 | { |
| 290 | MCode *oldarea = J->mcarea; | 360 | MCode *oldarea = J->mcarea; |
| 291 | size_t sz = (size_t)J->param[JIT_P_sizemcode] << 10; | 361 | size_t sz = (size_t)J->param[JIT_P_sizemcode] << 10; |
| 292 | sz = (sz + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1); | ||
| 293 | J->mcarea = (MCode *)mcode_alloc(J, sz); | 362 | J->mcarea = (MCode *)mcode_alloc(J, sz); |
| 294 | J->szmcarea = sz; | 363 | J->szmcarea = sz; |
| 295 | J->mcprot = MCPROT_GEN; | 364 | J->mcprot = MCPROT_GEN; |
| @@ -311,7 +380,7 @@ void lj_mcode_free(jit_State *J) | |||
| 311 | MCode *next = ((MCLink *)mc)->next; | 380 | MCode *next = ((MCLink *)mc)->next; |
| 312 | size_t sz = ((MCLink *)mc)->size; | 381 | size_t sz = ((MCLink *)mc)->size; |
| 313 | lj_err_deregister_mcode(mc, sz, (uint8_t *)mc + sizeof(MCLink)); | 382 | lj_err_deregister_mcode(mc, sz, (uint8_t *)mc + sizeof(MCLink)); |
| 314 | mcode_free(J, mc, sz); | 383 | mcode_free(mc, sz); |
| 315 | mc = next; | 384 | mc = next; |
| 316 | } | 385 | } |
| 317 | } | 386 | } |
| @@ -347,32 +416,25 @@ void lj_mcode_abort(jit_State *J) | |||
| 347 | MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) | 416 | MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) |
| 348 | { | 417 | { |
| 349 | if (finish) { | 418 | if (finish) { |
| 350 | #if LUAJIT_SECURITY_MCODE | ||
| 351 | if (J->mcarea == ptr) | 419 | if (J->mcarea == ptr) |
| 352 | mcode_protect(J, MCPROT_RUN); | 420 | mcode_protect(J, MCPROT_RUN); |
| 353 | else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN))) | 421 | else |
| 354 | mcode_protfail(J); | 422 | mcode_setprot(J, ptr, ((MCLink *)ptr)->size, MCPROT_RUN); |
| 355 | #endif | ||
| 356 | return NULL; | 423 | return NULL; |
| 357 | } else { | 424 | } else { |
| 358 | MCode *mc = J->mcarea; | 425 | uintptr_t base = (uintptr_t)J->mcarea, addr = (uintptr_t)ptr; |
| 359 | /* Try current area first to use the protection cache. */ | 426 | /* Try current area first to use the protection cache. */ |
| 360 | if (ptr >= mc && ptr < (MCode *)((char *)mc + J->szmcarea)) { | 427 | if (addr >= base && addr < base + J->szmcarea) { |
| 361 | #if LUAJIT_SECURITY_MCODE | ||
| 362 | mcode_protect(J, MCPROT_GEN); | 428 | mcode_protect(J, MCPROT_GEN); |
| 363 | #endif | 429 | return (MCode *)base; |
| 364 | return mc; | ||
| 365 | } | 430 | } |
| 366 | /* Otherwise search through the list of MCode areas. */ | 431 | /* Otherwise search through the list of MCode areas. */ |
| 367 | for (;;) { | 432 | for (;;) { |
| 368 | mc = ((MCLink *)mc)->next; | 433 | base = (uintptr_t)(((MCLink *)base)->next); |
| 369 | lj_assertJ(mc != NULL, "broken MCode area chain"); | 434 | lj_assertJ(base != 0, "broken MCode area chain"); |
| 370 | if (ptr >= mc && ptr < (MCode *)((char *)mc + ((MCLink *)mc)->size)) { | 435 | if (addr >= base && addr < base + ((MCLink *)base)->size) { |
| 371 | #if LUAJIT_SECURITY_MCODE | 436 | mcode_setprot(J, (MCode *)base, ((MCLink *)base)->size, MCPROT_GEN); |
| 372 | if (LJ_UNLIKELY(mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN))) | 437 | return (MCode *)base; |
| 373 | mcode_protfail(J); | ||
| 374 | #endif | ||
| 375 | return mc; | ||
| 376 | } | 438 | } |
| 377 | } | 439 | } |
| 378 | } | 440 | } |
| @@ -384,7 +446,6 @@ void lj_mcode_limiterr(jit_State *J, size_t need) | |||
| 384 | size_t sizemcode, maxmcode; | 446 | size_t sizemcode, maxmcode; |
| 385 | lj_mcode_abort(J); | 447 | lj_mcode_abort(J); |
| 386 | sizemcode = (size_t)J->param[JIT_P_sizemcode] << 10; | 448 | sizemcode = (size_t)J->param[JIT_P_sizemcode] << 10; |
| 387 | sizemcode = (sizemcode + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1); | ||
| 388 | maxmcode = (size_t)J->param[JIT_P_maxmcode] << 10; | 449 | maxmcode = (size_t)J->param[JIT_P_maxmcode] << 10; |
| 389 | if (need * sizeof(MCode) > sizemcode) | 450 | if (need * sizeof(MCode) > sizemcode) |
| 390 | lj_trace_err(J, LJ_TRERR_MCODEOV); /* Too long for any area. */ | 451 | lj_trace_err(J, LJ_TRERR_MCODEOV); /* Too long for any area. */ |
