From patchwork Tue Aug 26 08:27:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Wielaard X-Patchwork-Id: 2536 Received: (qmail 13179 invoked by alias); 26 Aug 2014 08:27:56 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 13071 invoked by uid 89); 26 Aug 2014 08:27:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, SPF_PASS autolearn=ham version=3.3.2 X-HELO: gnu.wildebeest.org From: Mark Wielaard To: libc-alpha@sourceware.org Cc: Siddhesh Poyarekar , Florian Weimer , Mark Wielaard Subject: [PATCH] i386 TLS_INIT_TP might produce bogus asm changing stack pointer. Date: Tue, 26 Aug 2014 10:27:45 +0200 Message-Id: <1409041665-1558-1-git-send-email-mjw@redhat.com> X-Spam-Score: -2.9 (--) TLS_INIT_TP in sysdeps/i386/nptl/tls.h uses some hand written asm to generate a set_thread_area that might result in exchanging ebx and esp around the syscall causing introspection tools like valgrind to loose track of the user stack. Just use INTERNAL_SYSCALL which makes sure esp isn't changed arbitrarily. Before the patch the code would generate: mov $0xf3,%eax movl $0xfffff,0x8(%esp) movl $0x51,0xc(%esp) xchg %esp,%ebx int $0x80 xchg %esp,%ebx Using INTERNAL_SYSCALL instead will generate: movl $0xfffff,0x8(%esp) movl $0x51,0xc(%esp) xchg %ecx,%ebx mov $0xf3,%eax int $0x80 xchg %ecx,%ebx Thanks to Florian Weimer for analysing why the original code generated the bogus esp usage: _segdescr.desc happens to be at the top of the stack, so its address is in %esp. The asm statement says that %3 is an input, so its value will not change, and GCC can use %esp as the input register for the expression &_segdescr.desc. But the constraints do not fully describe the asm statement because the %3 register is actually modified, albeit only temporarily. https://bugzilla.redhat.com/show_bug.cgi?id=1133134 * sysdeps/i386/nptl/tls.h (TLS_INIT_TP): Use INTERNAL_SYSCALL to call set_thread_area instead of hand written asm. --- ChangeLog | 5 +++++ sysdeps/i386/nptl/tls.h | 8 ++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h index ac9c9a2..052ea64 100644 --- a/sysdeps/i386/nptl/tls.h +++ b/sysdeps/i386/nptl/tls.h @@ -231,12 +231,8 @@ tls_fill_user_desc (union user_desc_init *desc, tls_fill_user_desc (&_segdescr, -1, _thrdescr); \ \ /* Install the TLS. */ \ - asm volatile (TLS_LOAD_EBX \ - "int $0x80\n\t" \ - TLS_LOAD_EBX \ - : "=a" (_result), "=m" (_segdescr.desc.entry_number) \ - : "0" (__NR_set_thread_area), \ - TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \ + INTERNAL_SYSCALL_DECL (err); \ + _result = INTERNAL_SYSCALL (set_thread_area, err, 1, &_segdescr.desc); \ \ if (_result == 0) \ /* We know the index in the GDT, now load the segment register. \