From patchwork Mon Feb 26 21:03:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 129708 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp4290588edc; Mon, 26 Feb 2018 13:05:03 -0800 (PST) X-Google-Smtp-Source: AH8x227ZJRXRBYAQ+oksraB3hDqobv22HozqDcIOgl01Aporxn8+7/Ns0e9jeYy2WWB9ChTS9fCL X-Received: by 2002:a17:902:968e:: with SMTP id n14-v6mr12002256plp.21.1519679103473; Mon, 26 Feb 2018 13:05:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519679103; cv=none; d=google.com; s=arc-20160816; b=XgMjkIwnhKNd4bSjEbCQrLPFgKvAhOBcqbnU0fzzt9siTR57/OhTIqgCNdVc9qw0u6 29KxzDWKk2Ndc1R0rXKktkNhWIhnzMGQZEWLrQJQrveoMnkJ03xj6NKiegWYzq90+n6h RxymckEzVzFGzPuj50tp5/4htIJ6pu6UErddw7sRMRWtBD/KLB4xwYRkmGGUWg2YbpFS +n/Oiwuhgvuv4UG3LmWe0KC9RhXunCkIwhmSDv7g1GwrGgjLvNR0Ty02LDbMOmwC8fso JtIBqSZCKU8PSoxkq5nTIwSKIbC69TbynOzQG1hLJJuB0+xy1m8MIBozh7ehD9GjEQSW Qszg== 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=aXQVoRcRGXRM63V0IWe+RSmCm6b7Q6tYt2UgkQQodqI=; b=KVuiRFi+nFD7dRs9DoL/iSdPwHL9YORwC0JI7XWq+1YpSeWJr6Kzp5BPReTnmeS4e1 1wlGkXRiz6U2IZvT8e+ugvjWbn+s/pG+2GZvQMhubjL7hmwq4ZTWxlfftU8O4Q3wtJUD 8oJN89vDvbCGPD07UMQzg0hDWctw5tAKLzRss9DqldbU/0upM0EwdXtWn7Y7C/tQk+WQ b8dHfTQYUyXSxLSpKzaNan4t3NkZG55nT3FFvDQCcNDK34uTnU2leCZq1IAg7+De7ziX z5+DstcLo0e6Oj9+aSZwBzb9J3DnOgFXGgnEP44fW6xmYUR/of9Hk6jbMIjAXjsjgwEI i5Xw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=q9k6PXav; spf=pass (google.com: domain of libc-alpha-return-90623-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-90623-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 e3-v6si7337996plb.100.2018.02.26.13.05.03 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Feb 2018 13:05:03 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-return-90623-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=q9k6PXav; spf=pass (google.com: domain of libc-alpha-return-90623-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-90623-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=cm7RmyOAuIeyFfajmX0qToOeH0CoUqA 2gSjM7uw2Jeb/VQmWQvyJozqK33Rj5pBom6ExkMqfpINXXKK0I0v0dEeVPn/cmgE svBm5KbOaXYMooK4X0l4oUOCImmWsT7+iYc2veLHvx+QHkLjRjdmPGFPAB5/xeZy gJqhxAtYntu4= 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=oKZZZXsWDeN2k4ISsoesKq94kj0=; b=q9k6P Xav2HTiv6mVkaHzTqwl/tBvBcGsx6LD40NlZCIpQ1xblhsISPsAxWp3J4kpcDlDk 1XSI7C+6BOamTn86f9hUho97PpFQcniSba5XIyWpjz4mq1cNizGAjWH7f4SjooLG X26Gn7cfFt+d/8RXMJsgOJGJxIpr9ik2rUQcfE= Received: (qmail 75535 invoked by alias); 26 Feb 2018 21:03:58 -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 75412 invoked by uid 89); 26 Feb 2018 21:03:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.0 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-f196.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=aXQVoRcRGXRM63V0IWe+RSmCm6b7Q6tYt2UgkQQodqI=; b=QRaQM4q29fqt7xlLz5tLfKuiTa5qpwSDjKTI8Lq9QQFZ06PtaCO+F5RgatqFjmmk67 DAUS14Zj9Cii+aep/cpyMuj56zpK1qCbTsRLEWnUKnn7W450LdTojobUlziukcew3Dxz D9xetDEX22DGujYLXtMrrhZ6uhUauXrtNyXgAiToJDnmonSfQH+VFLLnnQXuFkeZZXXL /9NF/Y2envn7gMxpHxWYq2RYW8kb5e/uHQ7f0c08g34wuiSlPNhGSA9Li8hO+yq6h4Vd InBqQktPg10wrwMyNLk+KCQNGWQeTLW5dzg8rxgpn1Oy58Ot4cn3RijxcNy8lISXkEqX rL0w== X-Gm-Message-State: APf1xPBeopwEMuVxilfTzboeTPVeUfxedDFVCbYxMCk04dbhaS2wAW9Z BOBy3fawdP6TKMmcnLsvL0dzkm4SOXY= X-Received: by 10.200.9.48 with SMTP id t45mr20324388qth.107.1519679032402; Mon, 26 Feb 2018 13:03:52 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2 06/21] nptl: i386: Fix Race conditions in pthread cancellation (BZ#12683) Date: Mon, 26 Feb 2018 18:03:21 -0300 Message-Id: <1519679016-12241-7-git-send-email-adhemerval.zanella@linaro.org> In-Reply-To: <1519679016-12241-1-git-send-email-adhemerval.zanella@linaro.org> References: <1519679016-12241-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. [BZ #12683] * 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 --- ChangeLog | 10 +++ 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, 132 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 fcda135..ae4de89 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 38fbc25..072bc11 100644 --- a/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -230,7 +230,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 a4ed29a..e7a9f17 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)