I am currently in a situation where I need to relocate the TCB (Thread Control Block). From what I understood, the following scheme is in place in processes execution when calling the VDSO (according to this article)
My problem is that I need to override some of my process memory with other things, and most of the time, it erases the section at the address (GDT[%gs]+0x10).
What I would like to do is to relocate the contents of the TCB (from GDT[%gs] to GDT[%gs]+0x..) in a free location in my process' AS, but that would mean altering the GDT contents, what I think I cannot do from the user mode. In other words, I'd like to change the association of %GS in my GDT.
Thanks in advance for any answer, /iansus
Ok, I found the solution :
int relocateTCB()
{
#ifndef TCB_LDT_INDEX
#define TCB_LDT_INDEX 6
#endif
struct user_desc* u_info = (struct user_desc*) malloc(sizeof(struct user_desc));
int r,j;
int mstart, map;
int PS = sysconf(_SC_PAGESIZE);
if(u_info == NULL)
{
errno = EFAULT;
return -1;
}
u_info->entry_number = TCB_LDT_INDEX;
r = syscall(SYS_get_thread_area, u_info);
if(r==-1) return -1;
mstart = (u_info->base_addr) & ~(PS-1);
map = (int) mmap(NULL, PS, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, (off_t)0);
if(!map)
{
errno = EFAULT;
return -1;
}
for(j=mstart; j<mstart+PS; j+=sizeof(int))
{
* ((int*) (map+j-mstart)) = * ((int*) j);
}
u_info->base_addr = map + u_info->base_addr - mstart;
r = syscall(SYS_set_thread_area, u_info);
if(r==-1)
{
errno = EINVAL;
return -1;
}
for(j=mstart; j<mstart+PS; j+=sizeof(int))
*((int*) j) = 0;
// Keep *%gs = %gs
*((int*) u_info->base_addr) = u_info->base_addr;
return 0;
}