int main() { unsigned int currentGS = TLS_GET_GS_REG(); unsigned int currentFS = TLS_GET_FS_REG(); if ((currentGS == 0) || ((currentGS & 0x4) == 0x4)) { unsigned int ldtEntry = currentGS >> 3; unsigned int ldtNextEntry = ldtEntry+1; UserDesc tableEntry; memset(&tableEntry, 0, sizeof(UserDesc)); tableEntry.entry_number = ldtNextEntry; tableEntry.base_addr = reinterpret_cast<unsigned int>(new unsigned int(0xabcd)); tableEntry.limit = 0x4000; int res = syscall(SYS_modify_ldt, LDT_SET, &tableEntry, sizeof(UserDesc)); if (res < 0) { printf("LDT_SET for entry %d failed, code %d, %s\n", ldtNextEntry, errno, strerror(errno) ); return 0; } unsigned int newSegVal = (ldtNextEntry << 3) + 7; unsigned int GSRes = 0x1; unsigned int FSRes = 0x2; FarPointer farPtrGS(GSRes, newSegVal); FarPointer farPtrFS(FSRes, newSegVal); if ((SetGs(&farPtrGS) != GSRes) || (SetFs(&farPtrFS) != FSRes)) { TLS_SET_GS_REG(currentGS); TLS_SET_FS_REG(currentFS); printf("LFS or LGS failed\n"); return 0; } if ((TLS_GET_GS_REG() != newSegVal) || (TLS_GET_FS_REG() != newSegVal)) { TLS_SET_GS_REG(currentGS); TLS_SET_FS_REG(currentFS); printf("GS or FS wrong value\n"); return 0; } if ((GetGsBase() != 0xabcd) || (GetFsBase() != 0xabcd)) { TLS_SET_GS_REG(currentGS); TLS_SET_FS_REG(currentFS); printf("GS or FS wrong base address\n"); return 0; } TLS_SET_GS_REG(currentGS); TLS_SET_FS_REG(currentFS); printf("LFS and LGS passed successfully\n"); printf("Base address of GS and FS was synchronuized successfully;\n"); }
ADDRINT GetTlsBaseAddress() { ADDRINT baseAddress = 0; #ifdef TARGET_IA32 unsigned int gsVal = TLS_GET_GS_REG(); UserDesc td; td.entry_number = gsVal >> 3; if (gsVal == 0) return 0; int res = syscall(SYS_get_thread_area, &td); if (res != 0) { printf("SYS_get_thread_area failed with error: %s\n", strerror(errno)); return 0; } baseAddress = td.base_addr; #else int res = syscall(SYS_arch_prctl, ARCH_GET_FS, &baseAddress); if (res != 0) { printf("SYS_arch_prctl failed with error: %s\n", strerror(errno)); return 0; } #endif return baseAddress; }
void * thread_func (void *arg) { unsigned long thread_no = (unsigned long)arg+1; unsigned int gs_value = TLS_GET_GS_REG(); sprintf(buf[thread_no-1],"gs value for thread %ld is 0x%x\n", thread_no, gs_value ); unsigned int gdtEntryMin = GdtFirstEntry(); unsigned int gdtEntryMax = gdtEntryMin + GDT_NUM_OF_ENTRIES - 1; for (unsigned int i=gdtEntryMin; i<=gdtEntryMax+1; i++) { UserDesc thrDescr; thrDescr._entry_number = i; int res = syscall(SYS_get_thread_area, &thrDescr); if (res == 0) { if (thrDescr._base_addr != mainThreadAddress[i]) sprintf(buf[thread_no-1],"%s thread %d: base addr for entry %d has been changed by clone()\n", buf[thread_no-1], thread_no, i); else sprintf(buf[thread_no-1],"%s thread %d: base addr for entry %d is equal to the same entry in main thread\n", buf[thread_no-1], thread_no, i); } else { sprintf(buf[thread_no-1],"%s thread %d: SYS_get_thread_area failed for entry %d with error: %s\n", buf[thread_no-1], thread_no, i, strerror(errno)); } } return 0; }
int main (int argc, char *argv[]) { unsigned long gs_val = TLS_GET_GS_REG(); while (1) { loop1 = true; loop2 = true; pthread_t h[NTHREADS]; pthread_create (&h[0], 0, thread_dlopen_func, 0); for (unsigned long i = 1; i < NTHREADS; i++) { pthread_create (&h[i], 0, thread_func, 0); } sleep(1); loop1 = false; loop2 = false; for (unsigned long i = 0; i < NTHREADS; i++) { pthread_join (h[i], 0); } } return 0; }