The Vmalloc package, on which the Smalloc allocator is built, is thread-safe, so extending our design to multi-threaded programs is straightforward. If sensitive local variables are transformed into heap-allocated structures, no changes to our system are necessary. Performance is a concern, however, since the many calls to smalloc in each thread will contend for the lock that guards the heap.
Alternatively, using the shadow stack approach to hold the sensitive local variables requires each thread to have its own shadow stack, just as each has its own traditional stack. The shadow stack pointer, which in single-threaded programs is simply a global variable, must therefore be stored into thread-local storage. Each thread has a pointer to its own shadow stack. The stack space for the thread is allocated during the first use of the shadow stack and freed when the thread terminates.
Since the same function may be called in different threads, each function with sensitive local variables retrieves the shadow stack pointer for the current thread upon entry to the function. When the pointer is updated, it must be stored into thread-local storage. For programs using POSIX threads, we add the following to the beginning of each function body:
void * stackPointer = pthread_getspecific(scrash_stack_key); stackPointer += sizeof(struct function_shadow); pthread_setspecific(scrash_stack_key, stackPointer);
and before each return statement, we add:
stackPointer -= sizeof(struct function_shadow); pthread_setspecific(scrash_stack_key, stackPointer);
Note that the structure function_shadow holds the contents of all sensitive local variables for that function.
The first part of the structure's name identifies the function in which it is used.
An alternative to thread-local storage would be to add an extra parameter to every function that holds the address of the current thread's shadow stack. Unfortunately, it is often not possible to change the signature of every function, since functions such as event handlers and signal handlers are called by underlying systems.