From: Rich Felker Date: Sat, 16 May 2015 05:15:40 +0000 (-0400) Subject: in i386 __set_thread_area, don't assume %gs register is initially zero X-Git-Tag: v1.1.10~27 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=707d7c30f3379441de9b320536ddfd354f4c2143;p=oweals%2Fmusl.git in i386 __set_thread_area, don't assume %gs register is initially zero commit f630df09b1fd954eda16e2f779da0b5ecc9d80d3 added logic to handle the case where __set_thread_area is called more than once by reusing the GDT slot already in the %gs register, and only setting up a new GDT slot when %gs is zero. this created a hidden assumption that %gs is zero when a new process image starts, which is true in practice on Linux, but does not seem to be documented ABI, and fails to hold under qemu app-level emulation. while it would in theory be possible to zero %gs in the entry point code, this code is shared between static and dynamic binaries, and dynamic binaries must not clobber the value of %gs already setup by the dynamic linker. the alternative solution implemented in this commit simply uses global data to store the GDT index that's selected. __set_thread_area should only be called in the initial thread anyway (subsequent threads get their thread pointer setup by __clone), but even if it were called by another thread, it would simply read and write back the same GDT index that was already assigned to the initial thread, and thus (in the x86 memory model) there is no data race. --- diff --git a/src/thread/i386/__set_thread_area.s b/src/thread/i386/__set_thread_area.s index 1d852689..3a558fb0 100644 --- a/src/thread/i386/__set_thread_area.s +++ b/src/thread/i386/__set_thread_area.s @@ -6,10 +6,10 @@ __set_thread_area: push $0x51 push $0xfffff push 16(%esp) - xor %edx,%edx - mov %gs,%dx - sub $3,%edx - sar $3,%edx + call 1f +1: addl $4f-1b,(%esp) + pop %ecx + mov (%ecx),%edx push %edx mov %esp,%ebx xor %eax,%eax @@ -18,6 +18,7 @@ __set_thread_area: testl %eax,%eax jnz 2f movl (%esp),%edx + movl %edx,(%ecx) leal 3(,%edx,8),%edx 3: movw %dx,%gs 1: @@ -38,3 +39,7 @@ __set_thread_area: mov $7,%dl inc %al jmp 3b + +.data + .align 4 +4: .long -1