From patchwork Mon Dec 11 19:06:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 121441 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp3167814qgn; Mon, 11 Dec 2017 11:08:30 -0800 (PST) X-Google-Smtp-Source: ACJfBovW3A6afSwVJXR9T13Nq+jVB3aaBaStM7v6dVCcjdctvir+03nBPEuAmn3+aI+qnm0NScSN X-Received: by 10.84.142.1 with SMTP id 1mr1290501plw.254.1513019310014; Mon, 11 Dec 2017 11:08:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513019310; cv=none; d=google.com; s=arc-20160816; b=PyBFZYIdR5FEfRTEFagiQ7jIH1HGZAGKlcdEH1qIXor3YwW1fokUzMTMiZ+PF/7uUv 50a/O4a42JA+c354HGBjsAsoMIMcQrxDwVcwjpOeNiCSJYzofoBruJRezauFt0Wv4BAr +PS3M70zIlhlpjZiis2wt/Ii+UXO5OuUUPVih1TFp4oBui0ZPFRsptzt0h1B9ONuTVyx gzoEwt1iko9DwHfG1PfSS8nlWvl29cqflpB62i8LMSqZwCGmW5UMb8mkXPHzc/kAMHGb VVFUQRmjT6Az+AicG+7IA6a3cqY9Ae5LVxkokp5NgWfGt3jqmaYeXazq+MzD0+ferGWJ nqHw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:to:from:delivered-to :sender:list-help:list-post:list-archive:list-subscribe :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature:arc-authentication-results; bh=x3JY/2B4XC8sA2krs9r9KkAjCapMtsOzy4sXmyZG3os=; b=nKVQDoxpfYY89/DEOmDMEXapmwapiSCdN3QyPMfqqJQjWl8H18yIzctrhYFOR+ylA3 xHjnFEK5+cIMkJ9QMjajWRvOgqZ1dbWl2WuSB7xLGl1SzN/mpJMPBkJU/AK7J/LWLVww 0aW36myQJ6ssZzD5O4/drPJEHG2uhj6v4r782ZFpZ3BNan+4uv4Jr56IXK/ovyAdO+yj d3jOJS4uyE4m1PDxqW+nNjH1PxGmmA1uOL1Hs6VJiiqd3NrNiwu2dc0O72Z7DnVRI+tu TIELtSqX8cerViiM34Pmno9/hTkud7b1wWFOhH9AENqHOf0x0YmvwRNy5FgYLwpWh3x/ gx/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=hMNZMgNE; spf=pass (google.com: domain of libc-alpha-return-88018-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-88018-patch=linaro.org@sourceware.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id i195si10250111pgc.351.2017.12.11.11.08.29 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 11:08:30 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-return-88018-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=hMNZMgNE; spf=pass (google.com: domain of libc-alpha-return-88018-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-88018-patch=linaro.org@sourceware.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=Ht54dwzHxzqVjTva5UGu9OkyIFLJT9B 9Mw7f3acH4jCNxlsWsI4+8hf/EBaj3kYoD0GXNXK4CY6sjwkPQIXZCFlPho6puQ5 GSGFwrxN3Kl2lgS8SGw3aABK1h/piMMRAom5iY76Is+r80cCExFjQ2QacvDvUVdi s31bJ6FkqpxA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:in-reply-to :references; s=default; bh=LYKpF561FniPe8VBMHCufW1hKWQ=; b=hMNZM gNEZO6Z/hRx7l+EdpLZUbFF+6WbKBMCNgNGSDBtWR++z9kjYcnCzER3GTHYZw5c7 211FxtE4EFnFtAehz26lIsW/hRMg4Za/os9yWMd86rxGlX19EEVQaPlDMJxGT9Yk u/ZMQTVMEgr3EJgfie0kgKCzfVnxrpZE0s+/F4= Received: (qmail 41126 invoked by alias); 11 Dec 2017 19:07:22 -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 41098 invoked by uid 89); 11 Dec 2017 19:07:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-qt0-f194.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=x3JY/2B4XC8sA2krs9r9KkAjCapMtsOzy4sXmyZG3os=; b=UFhlm8mraWt6PsGUDhavk+UZCy23VKzc/KC95PKjI/ayb1OUSuNkXVPPpetlOdzfGo lSsFcI4Zveed4Mw4KNnqrAGKW5nlMP1Se2Q3/sH/nBvwXP1Ko+OwQNPslgeLAOVafi4l 31vCaliy+z6tczmHIn9gSIWmx2jvC4vS7TYD03E1utlPdvouaUtKzv76NnoWkpBH9OWl HRzgHFxNsTyghRMriyqj0RcYKEHTpC87cGq6kmf719xM9ekFJ2Kcpw9zv5HG9k9DUkf+ 8X1as4oTMi2OqSjjTPujBKqvGD/ACR01xIakwiSLxhgxIHVcVDXLs4rm4uKXACPhB/Gq 0yFQ== X-Gm-Message-State: AKGB3mKA1pIh7MeOJkMcXgyahgz+MnQaRvVKG9iAS1XmOv718gyH84ra QrAtWMPQPjjIduosmdWb7SypA7cRRz8= X-Received: by 10.237.50.130 with SMTP id z2mr1879772qtd.243.1513019238003; Mon, 11 Dec 2017 11:07:18 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 05/19] nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683) Date: Mon, 11 Dec 2017 17:06:49 -0200 Message-Id: <1513019223-7603-6-git-send-email-adhemerval.zanella@linaro.org> In-Reply-To: <1513019223-7603-1-git-send-email-adhemerval.zanella@linaro.org> References: <1513019223-7603-1-git-send-email-adhemerval.zanella@linaro.org> This patch adds the i386 modifications required for the BZ#12683. It basically provides the required ucontext_get_pc symbol, add the cancelable syscall wrapper and fix a thread atomic update macro. On i386 an arch-specific cancellation implementation is required because depending of the glibc configuration and underlying kernel the syscall may be done using a vDSO symbol (__kernel_vsyscall). By using the vDSO symbol the resulting PC value for an interrupted syscall points to an adress outside the expected markers in __syscall_cancel_arch. It has been discussed in LKML [1] on how kernel could help userland to accomplish it, but afaik discussion was stalled. Also, since glibc supports i486, the old 'int 0x80' should be used in the syscall wrapper. One option could make minimum default chip to pentium II (which implements sysenter) or add a runtime check on syscall_cancel.S to use 'int 0x80' or sysenter. Similar to x86_64, it also remove bogus arch-specific THREAD_ATOMIC_BIT_SET where it always reference to current thread instead of the one referenced by input 'descr' argument. Checked on i686-linux-gnu. * sysdeps/i386/nptl/tls.h (THREAD_ATOMIC_CMPXCHG_VAL, THREAD_ATOMIC_BIT_SET): Remove macro. * sysdeps/unix/sysv/linux/i386/Makefile [$(subdir) = elf] (sysdep-rtld_routines): Add libc-do-syscall object. * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_wait_tid): Use cancellable futex syscall macro. * sysdeps/unix/sysv/linux/i386/syscall_cancel.S: New file. * sysdeps/unix/sysv/linux/i386/sigcontextinfo.h (ucontext_get_pc): New function. [1] https://lkml.org/lkml/2016/3/8/1105 Signed-off-by: Adhemerval Zanella --- ChangeLog | 9 +++ sysdeps/i386/nptl/tls.h | 11 --- sysdeps/unix/sysv/linux/i386/Makefile | 2 +- sysdeps/unix/sysv/linux/i386/lowlevellock.h | 2 +- sysdeps/unix/sysv/linux/i386/sigcontextinfo.h | 13 ++++ sysdeps/unix/sysv/linux/i386/syscall_cancel.S | 107 ++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/i386/syscall_cancel.S -- 2.7.4 diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h index f9a6b11..afc2f88 100644 --- a/sysdeps/i386/nptl/tls.h +++ b/sysdeps/i386/nptl/tls.h @@ -383,17 +383,6 @@ tls_fill_user_desc (union user_desc_init *desc, abort (); }) -/* Atomic set bit. */ -#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ - (void) ({ if (sizeof ((descr)->member) == 4) \ - asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0" \ - :: "i" (offsetof (struct pthread, member)), \ - "ir" (1 << (bit))); \ - else \ - /* Not necessary for other sizes in the moment. */ \ - abort (); }) - - /* Set the stack guard field in TCB head. */ #define THREAD_SET_STACK_GUARD(value) \ THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile index 4080b8c..bae2e4b 100644 --- a/sysdeps/unix/sysv/linux/i386/Makefile +++ b/sysdeps/unix/sysv/linux/i386/Makefile @@ -6,7 +6,7 @@ sysdep_routines += ioperm iopl vm86 endif ifeq ($(subdir),elf) -sysdep-dl-routines += libc-do-syscall +sysdep-rtld_routines += libc-do-syscall sysdep-others += lddlibc4 install-bin += lddlibc4 endif diff --git a/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/sysdeps/unix/sysv/linux/i386/lowlevellock.h index 197bb1f..e54d1ea 100644 --- a/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -223,7 +223,7 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count, do { \ __typeof (tid) __tid; \ while ((__tid = (tid)) != 0) \ - lll_futex_wait (&(tid), __tid, LLL_SHARED);\ + lll_futex_wait_cancel (&(tid), __tid, LLL_SHARED);\ } while (0) extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) diff --git a/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h b/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h index 7e2764e..8547d9e 100644 --- a/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h +++ b/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h @@ -16,6 +16,11 @@ License along with the GNU C Library; if not, see . */ +#ifndef _SIGCONTEXTINFO_H +#define _SIGCONTEXTINFO_H + +#include + #define SIGCONTEXT struct sigcontext #define SIGCONTEXT_EXTRA_ARGS #define GET_PC(ctx) ((void *) ctx.eip) @@ -48,3 +53,11 @@ do { \ "i" (sizeof (struct sigcontext) / 4) \ : "cc", "edi"); \ } while (0) + +static inline uintptr_t +ucontext_get_pc (const ucontext_t *uc) +{ + return uc->uc_mcontext.gregs[REG_EIP]; +} + +#endif /* _SIGCONTEXTINFO_H */ diff --git a/sysdeps/unix/sysv/linux/i386/syscall_cancel.S b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S new file mode 100644 index 0000000..5596b3e --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/syscall_cancel.S @@ -0,0 +1,107 @@ +/* Cancellable syscall wrapper. Linux/i686 version. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +/* long int [eax] __syscall_cancel_arch (int *cancelhandling [SP], + long int nr [SP+4], + long int arg1 [SP+8], + long int arg2 [SP+12], + long int arg3 [SP+16], + long int arg4 [SP+20], + long int arg5 [SP+24], + long int arg6 [SP+28]) */ + +ENTRY (__syscall_cancel_arch) + pushl %ebp + cfi_def_cfa_offset (8) + cfi_offset (ebp, -8) + pushl %edi + cfi_def_cfa_offset (12) + cfi_offset (edi, -12) + pushl %esi + cfi_def_cfa_offset (16) + cfi_offset (esi, -16) + pushl %ebx + cfi_def_cfa_offset (20) + cfi_offset (ebx, -20) + + .global __syscall_cancel_arch_start + .type __syscall_cancel_arch_start, @function +__syscall_cancel_arch_start: + + /* if (*cancelhandling & CANCELED_BITMASK) + __syscall_do_cancel() */ + testb $4, (%eax) + jne 1f + + /* Issue a 6 argument syscall, the nr [%eax] being the syscall + number. */ + movl 24(%esp), %eax + movl 28(%esp), %ebx + movl 32(%esp), %ecx + movl 36(%esp), %edx + movl 40(%esp), %esi + movl 44(%esp), %edi + movl 48(%esp), %ebp + + /* We can not use the vDSO helper for syscall (__kernel_vsyscall) + because the returned PC from kernel will indicate whether the + interrupted syscall have any side-effects that need to be reported + back to program. And the signal handler (sigcancel_handler at + nptl-init.c) checks the PC agains the __syscall_cancel_arch_* + marks. */ + int $128 + + .global __syscall_cancel_arch_end + .type __syscall_cancel_arch_end, @function +__syscall_cancel_arch_end: + + popl %ebx + cfi_restore (ebx) + cfi_def_cfa_offset (16) + popl %esi + cfi_restore (esi) + cfi_def_cfa_offset (12) + popl %edi + cfi_restore (edi) + cfi_def_cfa_offset (8) + popl %ebp + cfi_restore (ebp) + cfi_def_cfa_offset (4) + ret + +1: + /* Although the __syscall_do_cancel do not return, we need to stack + being set correctly for unwind. */ + popl %ebx + cfi_restore (ebx) + cfi_def_cfa_offset (16) + popl %esi + cfi_restore (esi) + cfi_def_cfa_offset (12) + popl %edi + cfi_restore (edi) + cfi_def_cfa_offset (8) + popl %ebp + cfi_restore (ebp) + cfi_def_cfa_offset (4) + jmp __syscall_do_cancel + +END (__syscall_cancel_arch) +libc_hidden_def (__syscall_cancel_arch)