i#8034: Make native_exec_is_back_from_native check more robust to avoid BOLT induced crashes (#8035)

native_exec_is_back_from_native() bounds its
range check with the hard-coded
MAX_NATIVE_RETSTACK * BACK_FROM_NATIVE_RETSTUB_SIZE
(40 bytes) rather than the actual extent of the retstub region.

Bound the check by
back_from_native_retstubs_end - back_from_native_retstubs instead.
On x86 this is equivalent, the asm emits MAX_NATIVE_RETSTACK
stubs and native_exec_init() already asserts
end == start + MAX_NATIVE_RETSTACK * BACK_FROM_NATIVE_RETSTUB_SIZE.

Fixes #8034
This commit is contained in:
Suyash Mahar
2026-08-14 11:46:06 -07:00
committed by GitHub
parent e2b756de6e
commit 5ba42078a0
3 changed files with 37 additions and 1 deletions
+25
View File
@@ -1,5 +1,6 @@
/* **********************************************************
* Copyright (c) 2012-2025 Google, Inc. All rights reserved.
* Copyright (c) 2026 Meta Platforms, Inc. All rights reserved.
* **********************************************************/
/*
@@ -487,3 +488,27 @@ put_back_native_retaddrs(dcontext_t *dcontext)
}
#endif
}
#ifdef STANDALONE_UNIT_TEST
void
unit_test_native_exec(void)
{
const ptr_uint_t retstubs_sym_start = (ptr_uint_t)back_from_native_retstubs;
const ptr_uint_t retstubs_sym_end = (ptr_uint_t)back_from_native_retstubs_end;
EXPECT(retstubs_sym_end >= retstubs_sym_start, true);
EXPECT(native_exec_is_back_from_native((app_pc)retstubs_sym_start),
(retstubs_sym_end > retstubs_sym_start));
/* If non-zero size label. */
if (retstubs_sym_end > retstubs_sym_start) {
EXPECT(native_exec_is_back_from_native((app_pc)(retstubs_sym_end - 1)), true);
}
/* Boundary conditions: strictly outside the stub. */
EXPECT(native_exec_is_back_from_native((app_pc)(retstubs_sym_start - 1)), false);
EXPECT(native_exec_is_back_from_native((app_pc)(retstubs_sym_end)), false);
}
#endif /* STANDALONE_UNIT_TEST */
+8 -1
View File
@@ -1,5 +1,6 @@
/* **********************************************************
* Copyright (c) 2012-2025 Google, Inc. All rights reserved.
* Copyright (c) 2026 Meta Platforms, Inc. All rights reserved.
* **********************************************************/
/*
@@ -120,8 +121,14 @@ put_back_native_retaddrs(dcontext_t *dcontext);
static inline bool
native_exec_is_back_from_native(app_pc pc)
{
/* Non-x86 platforms can have zero-sized retstub if native_exec is not implemented.
* retstub_region_size is a link-time constant on all platforms, making the check a
* single compare.
*/
ptr_uint_t retstub_region_size =
(ptr_uint_t)back_from_native_retstubs_end - (ptr_uint_t)back_from_native_retstubs;
ptr_uint_t diff = (ptr_uint_t)pc - (ptr_uint_t)back_from_native_retstubs;
return (diff < MAX_NATIVE_RETSTACK * BACK_FROM_NATIVE_RETSTUB_SIZE);
return (diff < retstub_region_size);
}
#ifdef UNIX
+4
View File
@@ -1,5 +1,6 @@
/* **********************************************************
* Copyright (c) 2012-2013 Google, Inc. All rights reserved.
* Copyright (c) 2026 Meta Platforms, Inc. All rights reserved.
* **********************************************************/
/*
@@ -38,6 +39,8 @@
void
unit_test_io(void);
void
unit_test_native_exec(void);
#ifdef UNIX
void
unit_test_string(void);
@@ -75,6 +78,7 @@ main(int argc, char **argv, char **envp)
* might be worth looking into gtest, which already does this.
*/
unit_test_io();
unit_test_native_exec();
#ifdef UNIX
unit_test_string();
unit_test_os();