Skip to content

Commit 5a93a3a

Browse files
DinoVmeta-codesync[bot]
authored andcommitted
Fix aarch64 JIT crash when cinder_jit region exhausted
Summary: `allocFromCinderJitRegion()` bump-allocates JIT code out of the fixed-size, linker-reserved `__cinder_jit` region but never checked that the requested size fit in the remaining space. Once the region was exhausted, `s_cinder_jit_free -= size` underflowed (it is a `size_t`) and the function returned `s_cinder_jit_cur` pointing past the end of the mapped RWX region instead of returning `nullptr` to fall back to hinted/`mmap` allocation. The caller (`allocPages` -> `ensureSpace`/`ensureSplitSpace` -> `addCode`) then `memcpy`'d the generated code into unmapped memory, crashing with SIGSEGV in `__folly_memcpy_aarch64_sve` on the JIT compile worker thread. This matches the production aarch64 stack trace. The fix adds a bounds check inside `cinder_jit_region_mutex_` that returns `nullptr` when `size > s_cinder_jit_free`, so an exhausting or over-large request cleanly falls back to `mmap`. A rejected request consumes no region space. Reviewed By: alexmalyshev Differential Revision: D109663217 fbshipit-source-id: 2a22a6c0fe76a1dbc713f7457ee1feefec76708a
1 parent 8b6c7ec commit 5a93a3a

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

cinderx/Jit/code_allocator.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ uint8_t* allocFromCinderJitRegion(size_t size) {
148148
}
149149

150150
std::lock_guard lock{cinder_jit_region_mutex_};
151+
if (size > s_cinder_jit_free) {
152+
return nullptr;
153+
}
151154
uint8_t* res = s_cinder_jit_cur;
152155
s_cinder_jit_cur.fetch_add(size, std::memory_order_relaxed);
153156
s_cinder_jit_free -= size;

cinderx/RuntimeTests/hinted_code_allocation_test.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <array>
1919
#include <cstdint>
2020
#include <memory>
21+
#include <vector>
2122

2223
using namespace cinderx::jit;
2324

@@ -92,4 +93,47 @@ TEST_F(HintedCodeAllocationTest, AllocatesWithinCinderJitRegion) {
9293
#endif
9394
}
9495

96+
// A request the linker-reserved region can't satisfy must fall back to mmap
97+
// rather than handing back a pointer past the end of the region.
98+
TEST_F(HintedCodeAllocationTest, FallsBackWhenRequestExceedsRegion) {
99+
#if defined(__linux__)
100+
char* region_start = __cinder_jit_start;
101+
char* region_end = __cinder_jit_end;
102+
103+
if (region_start == nullptr) {
104+
GTEST_SKIP() << "binary not linked with the .cinder_jit linker script";
105+
}
106+
ASSERT_NE(region_end, nullptr)
107+
<< "binary not linked with the .cinder_jit linker script";
108+
ASSERT_LT(region_start, region_end);
109+
110+
// Build a code blob larger than the whole region so the bump allocator can
111+
// never satisfy it, forcing the mmap fallback. 0x90 is a nop on x86-64; the
112+
// exact bytes don't matter, only that they're really copied into the
113+
// allocation (exercising the memcpy that crashed in production).
114+
size_t region_size = static_cast<size_t>(region_end - region_start);
115+
std::vector<uint8_t> blob(region_size + 4096, 0x90);
116+
blob.back() = 0xc3; // ret
117+
118+
asmjit::CodeHolder code;
119+
code.init(code_allocator_->asmJitEnvironment());
120+
121+
cinderx::jit::codegen::arch::Builder as(&code);
122+
ASSERT_EQ(as.section(code.textSection()), asmjit::kErrorOk);
123+
ASSERT_EQ(as.embed(blob.data(), blob.size()), asmjit::kErrorOk);
124+
ASSERT_EQ(as.finalize(), asmjit::kErrorOk);
125+
126+
AllocateResult result = code_allocator_->addCode(&code);
127+
ASSERT_EQ(result.error, asmjit::kErrorOk);
128+
ASSERT_NE(result.addr, nullptr);
129+
130+
// The allocation must have come from the mmap fallback, outside the region.
131+
char* addr = static_cast<char*>(result.addr);
132+
EXPECT_TRUE(addr < region_start || addr >= region_end)
133+
<< "oversized request was satisfied from inside the reserved region";
134+
#else
135+
GTEST_SKIP() << "cinder_jit region allocation is only supported on Linux";
136+
#endif
137+
}
138+
95139
} // namespace

0 commit comments

Comments
 (0)