From patchwork Thu Sep 17 20:04:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 53847 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f69.google.com (mail-la0-f69.google.com [209.85.215.69]) by patches.linaro.org (Postfix) with ESMTPS id 17F9122E57 for ; Thu, 17 Sep 2015 20:05:17 +0000 (UTC) Received: by lamf6 with SMTP id f6sf11415856lam.1 for ; Thu, 17 Sep 2015 13:05:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:mailing-list:precedence:list-id :list-unsubscribe:list-subscribe:list-archive:list-post:list-help :sender:delivered-to:from:subject:to:message-id:date:user-agent :mime-version:content-type:content-transfer-encoding :x-original-sender:x-original-authentication-results; bh=9q37zbR8OxYxS2LeMLf1X1rfWRGCMt8SOqWRpgxrKFU=; b=fziahXMlCSOlPTHg+eELsqJVw9/FVAKaLdcwwvf0ivFd9epxMlXFyovQQNJExnK30D 1y28KIlSt2x5q5qIAEm1U4eugYiOV1ANl4InFy7zg/gN0XWp83J7vtGeWqvTwuRiHPJ0 C+AEcVkaGrZ8WA5CMV92jey6JMhklCS1+eQEPuM+KAcRrzBirNlFtnwhyFmmUNYaS14k wfv9Oi00WJiAqoD63q/KZua4KY8hj25v/R6QQJI51vX0R0LQ+lT3ppi18L8MSz13f7LP ZoJeLwkIh//ACZm2XBXsyvsp376MhmxAQIb+W8WcDV7p8FYvplj9etJAT07J04xa6AJF 4G3Q== X-Gm-Message-State: ALoCoQknwtGgAoyGleCBA1D5EOZyUKGMdE0oFWRJAWheepVhUM+0KbyHgjCF4G78OmB8Af3KBKiz X-Received: by 10.112.198.33 with SMTP id iz1mr178287lbc.8.1442520316033; Thu, 17 Sep 2015 13:05:16 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.1.136 with SMTP id 8ls46398lam.61.gmail; Thu, 17 Sep 2015 13:05:15 -0700 (PDT) X-Received: by 10.152.23.42 with SMTP id j10mr1250155laf.2.1442520315868; Thu, 17 Sep 2015 13:05:15 -0700 (PDT) Received: from mail-lb0-x234.google.com (mail-lb0-x234.google.com. [2a00:1450:4010:c04::234]) by mx.google.com with ESMTPS id 8si3462597lax.120.2015.09.17.13.05.15 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2015 13:05:15 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c04::234 as permitted sender) client-ip=2a00:1450:4010:c04::234; Received: by lbbmp1 with SMTP id mp1so15167779lbb.1 for ; Thu, 17 Sep 2015 13:05:15 -0700 (PDT) X-Received: by 10.112.64.72 with SMTP id m8mr1165156lbs.41.1442520315695; Thu, 17 Sep 2015 13:05:15 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp3265135lbq; Thu, 17 Sep 2015 13:05:14 -0700 (PDT) X-Received: by 10.69.12.33 with SMTP id en1mr1807391pbd.97.1442520314382; Thu, 17 Sep 2015 13:05:14 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id k3si7601061pbq.107.2015.09.17.13.05.13 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2015 13:05:14 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-63264-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 108409 invoked by alias); 17 Sep 2015 20:04:39 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list 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 107947 invoked by uid 89); 17 Sep 2015 20:04:35 -0000 X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-yk0-f177.google.com X-Received: by 10.170.52.7 with SMTP id 7mr1178020yku.74.1442520262915; Thu, 17 Sep 2015 13:04:22 -0700 (PDT) From: Adhemerval Zanella Subject: [PATCH 08/10] nptl: arm: Fix Race conditions in pthread cancellation (BZ#12683) To: GNU C Library Message-ID: <55FB1CC6.3070102@linaro.org> Date: Thu, 17 Sep 2015 17:04:22 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 X-Original-Sender: adhemerval.zanella@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c04::234 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@sourceware.org X-Google-Group-Id: 836684582541 This patch adds the ARM modifications required for the BZ#12683 fix. It basically removes the enable_asynccancel/disable_asynccancel function usage on code, provide a arch-specific symbol that contains global markers to be used in SIGCANCEL handler. --- * sysdeps/unix/sysv/linux/arm/syscall_cancel.S: New file. * sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO): Redefine to call __syscall_cancel function for cancellable syscalls. * sysdeps/unix/sysv/linux/arm/sysdep.h (SYSCALL_CANCEL_ERROR): Add definition. (SYSCALL_CANCEL_ERRNO): Likewise. -- diff --git a/sysdeps/unix/sysv/linux/arm/syscall_cancel.S b/sysdeps/unix/sysv/linux/arm/syscall_cancel.S new file mode 100644 index 0000000..da4b454 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/syscall_cancel.S @@ -0,0 +1,72 @@ +/* Cancellable syscall wrapper - arm version. + Copyright (C) 2015 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 [r0] __syscall_cancel_arch (int *cancelhandling [r0], + long int nr [r1], + long int arg1 [r2], + long int arg2 [r3], + long int arg3 [SP], + long int arg4 [SP+4], + long int arg5 [SP+8], + long int arg6 [SP+12]) */ + +#ifdef __thumb2__ + .thumb +#endif + .syntax unified + +ENTRY (__syscall_cancel_arch) + .fnstart + mov ip,sp + stmfd sp!,{r4,r5,r6,lr} + .save {r4,r5,r6,lr} + + cfi_adjust_cfa_offset (20) + cfi_rel_offset (lr, 16) + + .globl __syscall_cancel_arch_start +__syscall_cancel_arch_start: + + /* if (*cancelhandling & CANCELED_BITMASK) + __syscall_do_cancel() */ + ldr r0,[r0] + tst r0, #4 + bne 1f + + /* Issue a 6 argument syscall, the nr [r1] being the syscall + number. */ + mov r7,r1 + mov r0,r2 + mov r1,r3 + ldmfd ip,{r2,r3,r4,r5,r6} + svc 0x0 + + .globl __syscall_cancel_arch_end +__syscall_cancel_arch_end: + ldmfd sp!,{r4,r5,r6,lr} + cfi_adjust_cfa_offset (-16); + bx lr + +1: + mov lr, pc + b __syscall_do_cancel + .fnend +END (__syscall_cancel_arch) +libc_hidden_def (__syscall_cancel_arch) diff --git a/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h index bdefa80..afbf07d 100644 --- a/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h +++ b/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -19,10 +19,17 @@ #include #ifndef __ASSEMBLER__ # include +# include #endif #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) +# if IS_IN (libc) +# define JMP_SYSCALL_CANCEL HIDDEN_JUMPTARGET(__syscall_cancel) +# else +# define JMP_SYSCALL_CANCEL __syscall_cancel(PLT) +# endif + /* NOTE: We do mark syscalls with unwind annotations, for the benefit of cancellation; but they're really only accurate at the point of the syscall. The ARM unwind directives are not rich enough without adding @@ -31,16 +38,10 @@ # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .text; \ - ENTRY (__##syscall_name##_nocancel); \ - CFI_SECTIONS; \ - DO_CALL (syscall_name, args); \ - cmn r0, $4096; \ - PSEUDO_RET; \ - END (__##syscall_name##_nocancel); \ ENTRY (name); \ SINGLE_THREAD_P; \ - DOARGS_##args; \ bne .Lpseudo_cancel; \ + DOARGS_##args; \ cfi_remember_state; \ ldr r7, =SYS_ify (syscall_name); \ swi 0x0; \ @@ -50,150 +51,36 @@ cfi_restore_state; \ .Lpseudo_cancel: \ .fnstart; /* matched by the .fnend in UNDOARGS below. */ \ - DOCARGS_##args; /* save syscall args etc. around CENABLE. */ \ - CENABLE; \ - mov ip, r0; /* put mask in safe place. */ \ - UNDOCARGS_##args; /* restore syscall args. */ \ - ldr r7, =SYS_ify (syscall_name); \ - swi 0x0; /* do the call. */ \ - mov r7, r0; /* save syscall return value. */ \ - mov r0, ip; /* get mask back. */ \ - CDISABLE; \ - mov r0, r7; /* retrieve return value. */ \ - RESTORE_LR_##args; \ - UNDOARGS_##args; \ + push {r4, r5, lr}; \ + .save {r4, r5, lr}; \ + PSEUDO_CANCEL_BEFORE; \ + ldr r0, =SYS_ify (syscall_name); \ + PSEUDO_CANCEL_AFTER; \ + pop {r4, r5, lr}; \ + .fnend; \ cmn r0, $4096 -/* DOARGS pushes eight bytes on the stack for five arguments, twelve bytes for - six arguments, and four bytes for fewer. In order to preserve doubleword - alignment, sometimes we must save an extra register. */ - -# define RESTART_UNWIND \ - .fnend; \ - .fnstart; \ - .save {r7}; \ - .save {lr} - -# define DOCARGS_0 \ - .save {r7}; \ - push {lr}; \ - cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (lr, 0); \ - .save {lr} -# define UNDOCARGS_0 -# define RESTORE_LR_0 \ - pop {lr}; \ - cfi_adjust_cfa_offset (-4); \ - cfi_restore (lr) - -# define DOCARGS_1 \ - .save {r7}; \ - push {r0, r1, lr}; \ - cfi_adjust_cfa_offset (12); \ - cfi_rel_offset (lr, 8); \ - .save {lr}; \ - .pad #8 -# define UNDOCARGS_1 \ - ldr r0, [sp], #8; \ - cfi_adjust_cfa_offset (-8); \ - RESTART_UNWIND -# define RESTORE_LR_1 \ - RESTORE_LR_0 - -# define DOCARGS_2 \ - .save {r7}; \ - push {r0, r1, lr}; \ - cfi_adjust_cfa_offset (12); \ - cfi_rel_offset (lr, 8); \ - .save {lr}; \ - .pad #8 -# define UNDOCARGS_2 \ - pop {r0, r1}; \ - cfi_adjust_cfa_offset (-8); \ - RESTART_UNWIND -# define RESTORE_LR_2 \ - RESTORE_LR_0 - -# define DOCARGS_3 \ - .save {r7}; \ - push {r0, r1, r2, r3, lr}; \ - cfi_adjust_cfa_offset (20); \ - cfi_rel_offset (lr, 16); \ - .save {lr}; \ - .pad #16 -# define UNDOCARGS_3 \ - pop {r0, r1, r2, r3}; \ - cfi_adjust_cfa_offset (-16); \ - RESTART_UNWIND -# define RESTORE_LR_3 \ - RESTORE_LR_0 - -# define DOCARGS_4 \ - .save {r7}; \ - push {r0, r1, r2, r3, lr}; \ - cfi_adjust_cfa_offset (20); \ - cfi_rel_offset (lr, 16); \ - .save {lr}; \ - .pad #16 -# define UNDOCARGS_4 \ - pop {r0, r1, r2, r3}; \ - cfi_adjust_cfa_offset (-16); \ - RESTART_UNWIND -# define RESTORE_LR_4 \ - RESTORE_LR_0 - -/* r4 is only stmfd'ed for correct stack alignment. */ -# define DOCARGS_5 \ - .save {r4, r7}; \ - push {r0, r1, r2, r3, r4, lr}; \ - cfi_adjust_cfa_offset (24); \ - cfi_rel_offset (lr, 20); \ - .save {lr}; \ - .pad #20 -# define UNDOCARGS_5 \ - pop {r0, r1, r2, r3}; \ - cfi_adjust_cfa_offset (-16); \ - .fnend; \ - .fnstart; \ - .save {r4, r7}; \ - .save {lr}; \ - .pad #4 -# define RESTORE_LR_5 \ - pop {r4, lr}; \ - cfi_adjust_cfa_offset (-8); \ - /* r4 will be marked as restored later. */ \ - cfi_restore (lr) - -# define DOCARGS_6 \ - .save {r4, r5, r7}; \ - push {r0, r1, r2, r3, lr}; \ - cfi_adjust_cfa_offset (20); \ - cfi_rel_offset (lr, 16); \ - .save {lr}; \ - .pad #16 -# define UNDOCARGS_6 \ - pop {r0, r1, r2, r3}; \ - cfi_adjust_cfa_offset (-16); \ - .fnend; \ - .fnstart; \ - .save {r4, r5, r7}; \ - .save {lr}; -# define RESTORE_LR_6 \ - RESTORE_LR_0 +# define PSEUDO_CANCEL_BEFORE \ + .pad #20; \ + sub sp, sp, #20; \ + ldr r5, [sp, #32]; \ + ldr r4, [sp, #36]; \ + str r3, [sp]; \ + mov r3, r2; \ + str r5, [sp, #4]; \ + mov r2, r1; \ + str r4, [sp, #8]; \ + mov r1, r0 + +# define PSEUDO_CANCEL_AFTER \ + bl JMP_SYSCALL_CANCEL; \ + add sp, sp, #20 + # if IS_IN (libpthread) -# define CENABLE bl PLTJMP(__pthread_enable_asynccancel) -# define CDISABLE bl PLTJMP(__pthread_disable_asynccancel) # define __local_multiple_threads __pthread_multiple_threads # elif IS_IN (libc) -# define CENABLE bl PLTJMP(__libc_enable_asynccancel) -# define CDISABLE bl PLTJMP(__libc_disable_asynccancel) # define __local_multiple_threads __libc_multiple_threads -# elif IS_IN (librt) -# define CENABLE bl PLTJMP(__librt_enable_asynccancel) -# define CDISABLE bl PLTJMP(__librt_disable_asynccancel) -# else -# error Unsupported library # endif # if IS_IN (libpthread) || IS_IN (libc) @@ -238,4 +125,10 @@ extern int __local_multiple_threads attribute_hidden; # define RTLD_SINGLE_THREAD_P \ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ header.multiple_threads) == 0, 1) + +static inline +long int __pthread_get_ip (const struct ucontext *uc) +{ + return uc->uc_mcontext.arm_pc; +} #endif diff --git a/sysdeps/unix/sysv/linux/arm/sysdep.h b/sysdeps/unix/sysv/linux/arm/sysdep.h index 200f77a..6b18e34 100644 --- a/sysdeps/unix/sysv/linux/arm/sysdep.h +++ b/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -387,6 +387,14 @@ __local_syscall_error: \ #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) +#undef SYSCALL_CANCEL_ERROR +#define SYSCALL_CANCEL_ERROR(__val) \ + ((unsigned int) (__val) >= 0xfffff001u) + +#undef SYSCALL_CANCEL_ERRNO +#define SYSCALL_CANCEL_ERRNO(__val) \ + (-(__val)) + /* List of system calls which are supported as vsyscalls. */ #define HAVE_CLOCK_GETTIME_VSYSCALL 1 #define HAVE_GETTIMEOFDAY_VSYSCALL 1