Skip to content
Snippets Groups Projects
Commit affce2d2 authored by Basile Desloges's avatar Basile Desloges
Browse files

[eacsl] Add shadow layout support for the linux VDSO segment

parent e2be093e
No related branches found
No related tags found
No related merge requests found
...@@ -1137,6 +1137,8 @@ void print_shadow_layout() { ...@@ -1137,6 +1137,8 @@ void print_shadow_layout() {
print_memory_partition(&mem_layout.global); print_memory_partition(&mem_layout.global);
DLOG(">>> TLS ----------------------\n"); DLOG(">>> TLS ----------------------\n");
print_memory_partition(&mem_layout.tls); print_memory_partition(&mem_layout.tls);
DLOG(">>> VDSO ---------------------\n");
print_memory_partition(&mem_layout.vdso);
# elif E_ACSL_OS_IS_WINDOWS # elif E_ACSL_OS_IS_WINDOWS
DLOG(">>> TEXT ---------------------\n"); DLOG(">>> TEXT ---------------------\n");
print_memory_partition(&mem_layout.text); print_memory_partition(&mem_layout.text);
......
...@@ -30,7 +30,13 @@ ...@@ -30,7 +30,13 @@
#if E_ACSL_OS_IS_LINUX #if E_ACSL_OS_IS_LINUX
# include <fcntl.h>
# include <inttypes.h>
# include <stdio.h>
# include <string.h>
# include <sys/auxv.h>
# include <sys/resource.h> # include <sys/resource.h>
# include <unistd.h>
/** Program stack information {{{ */ /** Program stack information {{{ */
...@@ -229,6 +235,93 @@ static void init_shadow_layout_tls() { ...@@ -229,6 +235,93 @@ static void init_shadow_layout_tls() {
# endif # endif
} }
static void init_shadow_layout_vdso() {
// Retrieve the start address of the VDSO segment
uintptr_t vdso = getauxval(AT_SYSINFO_EHDR);
private_assert(
vdso != 0,
"Start address of VDSO segment not found in auxiliary vector.\n");
// Use /proc/self/maps to retrieve the end address of the VDSO segment
// (using open() instead of fopen() to avoid a dynamic allocation)
int maps_fd = open("/proc/self/maps", O_RDONLY);
private_assert(maps_fd >= 0, "Unable to open /proc/self/maps: %s\n",
strerror(errno));
int result;
uintptr_t start, end;
ssize_t count;
off_t offset;
char *newline;
// Buffer to read /proc/self/maps. 255 should be enough to read one line.
char buffer[255];
while (1) {
count = read(maps_fd, buffer, sizeof(buffer) - 1);
if (count == 0) {
// If the VDSO segment has not been found, use 0 as start and end
// addresses
DVABORT("VDSO segment not found at address %a in /proc/self/maps\n",
vdso);
start = 0;
end = 0;
break;
} else if (count < 0) {
DVABORT("Reading /proc/self/maps failed: %s\n", strerror(errno));
break;
} else {
// Scan the start and end addresses of the segment
buffer[count] = '\0';
result = sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR, &start, &end);
DVASSERT(result == 2,
"Scanning for addresses in /proc/self/maps failed, expected 2 "
"addresses, found: %d, error: %s\n",
result, strerror(errno));
if (start <= vdso && vdso < end) {
break;
}
// Set the file offset to the next line
do {
// Look for a newline character
buffer[count] = '\0';
newline = strchr(buffer, '\n');
if (newline != NULL) {
// Newline character found, set the file offset to the character
// after the newline
offset = count - (newline - buffer + 1);
offset = lseek(maps_fd, -offset, SEEK_CUR);
DVASSERT(offset != -1,
"Unable to move file offset of /proc/self/maps: %s\n",
strerror(errno));
break;
} else {
// No newline found on the current buffer, continue reading the file
count = read(maps_fd, buffer, sizeof(buffer) - 1);
}
} while (count > 0);
}
}
result = close(maps_fd);
DVASSERT(result == 0, "Unable to close /proc/self/maps: %s\n",
strerror(errno));
// Initialize the memory partition
memory_partition *pvdso = &mem_layout.vdso;
set_application_segment(&pvdso->application, start, end - start, "vdso",
NULL);
set_shadow_segment(&pvdso->primary, &pvdso->application, 1, "vdso_primary");
set_shadow_segment(&pvdso->secondary, &pvdso->application, 1,
"vdso_secondary");
# ifdef E_ACSL_TEMPORAL
set_shadow_segment(&pvdso->temporal_primary, &pvdso->application, 1,
"temporal_vdso_primary");
set_shadow_segment(&pvdso->temporal_secondary, &pvdso->application, 1,
"temporal_vdso_secondary");
# endif
}
static void init_shadow_layout_stack(int *argc_ref, char ***argv_ref) { static void init_shadow_layout_stack(int *argc_ref, char ***argv_ref) {
memory_partition *pstack = &mem_layout.stack; memory_partition *pstack = &mem_layout.stack;
set_application_segment(&pstack->application, set_application_segment(&pstack->application,
...@@ -489,6 +582,7 @@ void init_shadow_layout_pre_main() { ...@@ -489,6 +582,7 @@ void init_shadow_layout_pre_main() {
#if E_ACSL_OS_IS_LINUX #if E_ACSL_OS_IS_LINUX
init_shadow_layout_global(); init_shadow_layout_global();
init_shadow_layout_vdso();
init_shadow_layout_tls(); init_shadow_layout_tls();
#elif E_ACSL_OS_IS_WINDOWS #elif E_ACSL_OS_IS_WINDOWS
HANDLE module = GetModuleHandle(NULL); HANDLE module = GetModuleHandle(NULL);
......
...@@ -70,9 +70,11 @@ ...@@ -70,9 +70,11 @@
Standard streams stdin, stdout and stderr are put here. Standard streams stdin, stdout and stderr are put here.
Some libraries such as libxml use it quite a lot: Some libraries such as libxml use it quite a lot:
it may occur that the given size is not enough, it may occur that the given size is not enough,
in which case it MUST be increased. */ in which case it MUST be increased.
However since the TLS is next to the VDSO segment in the program layout, the
default size is small enough so that both segments do not overlap. */
#ifndef PGM_TLS_SIZE #ifndef PGM_TLS_SIZE
# define PGM_TLS_SIZE (64 * MB) # define PGM_TLS_SIZE (2 * MB)
#endif #endif
/*! \brief Mspace padding used by shadow segments. This is to make sure that /*! \brief Mspace padding used by shadow segments. This is to make sure that
...@@ -191,6 +193,8 @@ struct memory_layout { ...@@ -191,6 +193,8 @@ struct memory_layout {
memory_partition global; memory_partition global;
// The TLS is in a specific section and identifiable // The TLS is in a specific section and identifiable
memory_partition tls; memory_partition tls;
// The VDSO is a small shared library used for some kernel functions
memory_partition vdso;
#elif E_ACSL_OS_IS_WINDOWS #elif E_ACSL_OS_IS_WINDOWS
// On windows // On windows
// The text, bss and data segments are not necessarily contiguous so each one // The text, bss and data segments are not necessarily contiguous so each one
...@@ -214,11 +218,9 @@ struct memory_layout mem_layout = { ...@@ -214,11 +218,9 @@ struct memory_layout mem_layout = {
/*! \brief Array of used partitions */ /*! \brief Array of used partitions */
memory_partition *mem_partitions[] = { memory_partition *mem_partitions[] = {
&mem_layout.heap, &mem_layout.heap, &mem_layout.stack,
&mem_layout.stack,
#if E_ACSL_OS_IS_LINUX #if E_ACSL_OS_IS_LINUX
&mem_layout.global, &mem_layout.global, &mem_layout.tls, &mem_layout.vdso,
&mem_layout.tls,
#elif E_ACSL_OS_IS_WINDOWS #elif E_ACSL_OS_IS_WINDOWS
&mem_layout.text, &mem_layout.bss, &mem_layout.data, &mem_layout.text, &mem_layout.bss, &mem_layout.data,
&mem_layout.idata, &mem_layout.rdata, &mem_layout.idata, &mem_layout.rdata,
...@@ -291,6 +293,8 @@ void clean_shadow_layout(); ...@@ -291,6 +293,8 @@ void clean_shadow_layout();
# define global_secondary_offset mem_layout.global.secondary.shadow_offset # define global_secondary_offset mem_layout.global.secondary.shadow_offset
# define tls_primary_offset mem_layout.tls.primary.shadow_offset # define tls_primary_offset mem_layout.tls.primary.shadow_offset
# define tls_secondary_offset mem_layout.tls.secondary.shadow_offset # define tls_secondary_offset mem_layout.tls.secondary.shadow_offset
# define vdso_primary_offset mem_layout.vdso.primary.shadow_offset
# define vdso_secondary_offset mem_layout.vdso.secondary.shadow_offset
#elif E_ACSL_OS_IS_WINDOWS #elif E_ACSL_OS_IS_WINDOWS
# define text_primary_offset mem_layout.text.primary.shadow_offset # define text_primary_offset mem_layout.text.primary.shadow_offset
# define text_secondary_offset mem_layout.text.secondary.shadow_offset # define text_secondary_offset mem_layout.text.secondary.shadow_offset
...@@ -351,6 +355,14 @@ void clean_shadow_layout(); ...@@ -351,6 +355,14 @@ void clean_shadow_layout();
/*! \brief Convert a TLS address into its secondary shadow counterpart */ /*! \brief Convert a TLS address into its secondary shadow counterpart */
# define SECONDARY_TLS_SHADOW(_addr) SHADOW_ACCESS(_addr, tls_secondary_offset) # define SECONDARY_TLS_SHADOW(_addr) SHADOW_ACCESS(_addr, tls_secondary_offset)
/*! \brief Convert a VDSO address into its primary shadow counterpart */
# define PRIMARY_VDSO_SHADOW(_addr) SHADOW_ACCESS(_addr, vdso_primary_offset)
/*! \brief Convert a VDSO address into its secondary shadow counterpart */
# define SECONDARY_VDSO_SHADOW(_addr) \
SHADOW_ACCESS(_addr, vdso_secondary_offset)
#elif E_ACSL_OS_IS_WINDOWS #elif E_ACSL_OS_IS_WINDOWS
/*! \brief Convert a text address into its primary shadow counterpart */ /*! \brief Convert a text address into its primary shadow counterpart */
# define PRIMARY_TEXT_SHADOW(_addr) SHADOW_ACCESS(_addr, text_primary_offset) # define PRIMARY_TEXT_SHADOW(_addr) SHADOW_ACCESS(_addr, text_primary_offset)
...@@ -418,6 +430,7 @@ void clean_shadow_layout(); ...@@ -418,6 +430,7 @@ void clean_shadow_layout();
(IS_ON_STACK(_addr) ? _region##_STACK_SHADOW(_addr) \ (IS_ON_STACK(_addr) ? _region##_STACK_SHADOW(_addr) \
: IS_ON_GLOBAL(_addr) ? _region##_GLOBAL_SHADOW(_addr) \ : IS_ON_GLOBAL(_addr) ? _region##_GLOBAL_SHADOW(_addr) \
: IS_ON_TLS(_addr) ? _region##_TLS_SHADOW(_addr) \ : IS_ON_TLS(_addr) ? _region##_TLS_SHADOW(_addr) \
: IS_ON_VDSO(_addr) ? _region##_VDSO_SHADOW(_addr) \
: (intptr_t)0) : (intptr_t)0)
// clang-format on // clang-format on
#elif E_ACSL_OS_IS_WINDOWS #elif E_ACSL_OS_IS_WINDOWS
...@@ -462,10 +475,14 @@ void clean_shadow_layout(); ...@@ -462,10 +475,14 @@ void clean_shadow_layout();
/*! \brief Evaluate to true if _addr is a TLS address */ /*! \brief Evaluate to true if _addr is a TLS address */
# define IS_ON_TLS(_addr) IS_ON(_addr, mem_layout.tls.application) # define IS_ON_TLS(_addr) IS_ON(_addr, mem_layout.tls.application)
/*! \brief Evaluate to true if _addr is a VDSO address */
# define IS_ON_VDSO(_addr) IS_ON(_addr, mem_layout.vdso.application)
/*! \brief Shortcut for evaluating an address via ::IS_ON_STACK, /*! \brief Shortcut for evaluating an address via ::IS_ON_STACK,
* ::IS_ON_GLOBAL or ::IS_ON_TLS */ * ::IS_ON_GLOBAL or ::IS_ON_TLS */
# define IS_ON_STATIC(_addr) \ # define IS_ON_STATIC(_addr) \
(IS_ON_STACK(_addr) || IS_ON_GLOBAL(_addr) || IS_ON_TLS(_addr)) (IS_ON_STACK(_addr) || IS_ON_GLOBAL(_addr) || IS_ON_TLS(_addr) \
|| IS_ON_VDSO(_addr))
#elif E_ACSL_OS_IS_WINDOWS #elif E_ACSL_OS_IS_WINDOWS
/*! \brief Evaluate to true if `_addr` is a text address */ /*! \brief Evaluate to true if `_addr` is a text address */
# define IS_ON_TEXT(_addr) IS_ON(_addr, mem_layout.text.application) # define IS_ON_TEXT(_addr) IS_ON(_addr, mem_layout.text.application)
...@@ -529,6 +546,15 @@ void clean_shadow_layout(); ...@@ -529,6 +546,15 @@ void clean_shadow_layout();
/*! \brief Convert a TLS address into its secondary temporal shadow counterpart */ /*! \brief Convert a TLS address into its secondary temporal shadow counterpart */
# define TEMPORAL_SECONDARY_TLS_SHADOW(_addr) \ # define TEMPORAL_SECONDARY_TLS_SHADOW(_addr) \
SHADOW_ACCESS(_addr, mem_layout.tls.temporal_secondary.shadow_offset) SHADOW_ACCESS(_addr, mem_layout.tls.temporal_secondary.shadow_offset)
/*! \brief Convert a VDSO address into its primary temporal shadow counterpart */
# define TEMPORAL_PRIMARY_VDSO_SHADOW(_addr) \
SHADOW_ACCESS(_addr, mem_layout.vdso.temporal_primary.shadow_offset)
/*! \brief Convert a VDSO address into its secondary temporal shadow counterpart */
# define TEMPORAL_SECONDARY_VDSO_SHADOW(_addr) \
SHADOW_ACCESS(_addr, mem_layout.vdso.temporal_secondary.shadow_offset)
# elif E_ACSL_OS_IS_WINDOWS # elif E_ACSL_OS_IS_WINDOWS
/*! \brief Convert a text address into its primary temporal shadow counterpart */ /*! \brief Convert a text address into its primary temporal shadow counterpart */
# define TEMPORAL_PRIMARY_TEXT_SHADOW(_addr) \ # define TEMPORAL_PRIMARY_TEXT_SHADOW(_addr) \
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment