Besides the obvious clobbering of ax
, what other possible side effects will
this assembly snippet have?
language: asm
mov ax, gs
mov gs, ax
Let's see, shall we? Given a function get_value
that grabs the value at
gs:0x0
and a function set_value
that sets these values (trivial assembly
helpers), plus a function gs_reset
that contains the above code . . .
language: C
#include <stdio.h>
#include <stdint.h>
#include <asm/prctl.h>
#include <sys/prctl.h>
#include <asm/mman.h>
#include <sys/mman.h>
extern uint64_t get_value();
extern void set_value(uint64_t value);
extern void gs_reset();
int main() {
uint64_t old;
void *memory = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
arch_prctl(ARCH_GET_GS, &old);
arch_prctl(ARCH_SET_GS, (uint64_t)memory);
printf("Value: 0x%lx\n", get_value());
set_value(0x42);
printf("Value: 0x%lx\n", get_value());
gs_reset();
printf("Value: 0x%lx\n", get_value());
arch_prctl(ARCH_SET_GS, old);
return 0;
}
When run, we see:
$ ./a.out
Value: 0x0
Value: 0x42
zsh: segmentation fault (core dumped) ./a.out
. . . wait, what?
Explanation
Resetting the gs
selector will also reset the value of the IA32_GS_BASE
MSR
back to zero, the default value. That is to say, setting gs
back to itself
will reset the base offset for the gs
selector.
Note that arch_prctl
works simply by setting this MSR, so the last
get_value()
call ends up simply accessing the memory at address zero.
- ethereal