From patchwork Fri Apr 3 20:31:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 38730 Return-Path: X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x743.google.com (mail-qk1-x743.google.com [IPv6:2607:f8b0:4864:20::743]) by sourceware.org (Postfix) with ESMTPS id 1245E388A02A for ; Fri, 3 Apr 2020 20:32:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 1245E388A02A Received: by mail-qk1-x743.google.com with SMTP id k13so9564154qki.2 for ; Fri, 03 Apr 2020 13:32:18 -0700 (PDT) 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=e5M1B+1L1ZiJSANPTjq8HkikMEBvffzpqhHLDu0tx7w=; b=ndvyOMMwhXHUjCbrjFAvMl4/fJQsPbZdn7ClZ2ILOr1nZiXp1tlRNCHkQC4AJjA8h3 RXEN7bm3PqillB1eXIkF47ni/fFHeupuAHUIJzDEQaMpuNjinOTV/CsLFyVxhiqU0wSQ 3140drqLWKJMVhdRYmr5LNzVPNS4utQIZvRLT0ysLJPo+TPXZbaWQbW+uRMTI5oGUi/y OEBc48yyY+H5uHCLWxBz2mhzYB4nEcFzNhqG6wuY2VGUiFsZ102xBvX56d8zgTaZD/2m LLxykN+ejXGsMVUpvwt4+aIsRTKmmoD3IjUE2//RP5ZIb2Kp2n/2UxdAeVrzRYxt6mzF PAog== X-Gm-Message-State: AGi0PuZzitffTJ+ONlAwkqGdRU6Rd9aUrgHZOVzU8hLSg9cQqRk4KoHp SJAutY3RMf8Qh3OImpsyTCfbp+ZRL5w= X-Google-Smtp-Source: APiQypJvHBEtdJcjDv17yXVFd2Mzcquty23CJ2Y9u56WUdOv/MTyAjtchjnRSuWUuN7l/u15PAuGRw== X-Received: by 2002:a37:bc87:: with SMTP id m129mr11052336qkf.143.1585945937257; Fri, 03 Apr 2020 13:32:17 -0700 (PDT) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id d141sm7063535qke.68.2020.04.03.13.32.16 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2020 13:32:16 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v4 06/21] nptl: ia64: Fix Race conditions in pthread cancellation [BZ#12683] Date: Fri, 3 Apr 2020 17:31:46 -0300 Message-Id: <20200403203201.7494-7-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200403203201.7494-1-adhemerval.zanella@linaro.org> References: <20200403203201.7494-1-adhemerval.zanella@linaro.org> X-Spam-Status: No, score=-26.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Apr 2020 20:32:19 -0000 This patch adds the ia64 modifications required for the BZ#12683 fix. The syscall bridge uses the old brk 0x10000 instruction because by using the vDSO gate the resulting PC value for an interrupted syscall points to an address outside the expected markers in __syscall_cancel_arch. This is similar to i686 issue. Also the __syscall_cancel_arch issues the 'break 0x100000' on its own bundle, and __syscall_cancel_arch_end points to end of the previous one. It requires an arch-specific ucontext_check_pc_boundary to check for the ri value (embedded in the sc_ip by the kernel) to check if the syscall had any side-effects. Also, ia64 issues a sigcontext as third argument for sigaction handler with SA_SIGINFO which requires an arch-specific ucontext_add_cancel. Checked on ia64-linux-gnu. --- sysdeps/ia64/nptl/tcb-offsets.sym | 3 + .../sysv/linux/ia64/cancellation-pc-check.h | 48 +++++++++++ .../sysv/linux/ia64/cancellation-sigmask.h | 33 ++++++++ sysdeps/unix/sysv/linux/ia64/syscall_cancel.S | 81 +++++++++++++++++++ 4 files changed, 165 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/ia64/cancellation-pc-check.h create mode 100644 sysdeps/unix/sysv/linux/ia64/cancellation-sigmask.h create mode 100644 sysdeps/unix/sysv/linux/ia64/syscall_cancel.S diff --git a/sysdeps/ia64/nptl/tcb-offsets.sym b/sysdeps/ia64/nptl/tcb-offsets.sym index b01f712be2..202046cd5b 100644 --- a/sysdeps/ia64/nptl/tcb-offsets.sym +++ b/sysdeps/ia64/nptl/tcb-offsets.sym @@ -4,3 +4,6 @@ TID offsetof (struct pthread, tid) - TLS_PRE_TCB_SIZE MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads) - TLS_PRE_TCB_SIZE SYSINFO_OFFSET offsetof (tcbhead_t, __private) + +-- Not strictly offsets, used on syscall_cancel.S +TCB_CANCELED_BIT CANCELED_BIT diff --git a/sysdeps/unix/sysv/linux/ia64/cancellation-pc-check.h b/sysdeps/unix/sysv/linux/ia64/cancellation-pc-check.h new file mode 100644 index 0000000000..cadb4ac055 --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/cancellation-pc-check.h @@ -0,0 +1,48 @@ +/* Architecture specific bits for cancellation handling. + Copyright (C) 2020 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 + . */ + +#ifndef _NPTL_CANCELLATION_PC_CHECK +#define _NPTL_CANCELLATION_PC_CHECK 1 + +/* Check if the program counter (PC) from ucontext CTX is within the start and + then end boundary from the __syscall_cancel_arch bridge. Return TRUE if + the PC is within the boundary, meaning the syscall does not have any side + effects; or FALSE otherwise. */ +static bool +cancellation_pc_check (void *ctx) +{ + /* Both are defined in syscall_cancel.S for each architecture. */ + extern const char __syscall_cancel_arch_start[1]; + extern const char __syscall_cancel_arch_end[1]; + + uintptr_t sc_ip = ((struct sigcontext *) (ctx))->sc_ip; + uintptr_t cr_iip = sc_ip & ~0x3ull; + uintptr_t ri = sc_ip & 0x3ull; + + /* IA64 __syscall_cancel_arch issues the 'break 0x100000' on its own bundle, + and __syscall_cancel_arch_end points to end of the previous bundle. + To check if the syscall had any side-effects we need to check the slot + number. */ + if (cr_iip == (uintptr_t) __syscall_cancel_arch_end) + return ri == 0; + + return cr_iip >= (uintptr_t) __syscall_cancel_arch_start + && cr_iip < (uintptr_t) __syscall_cancel_arch_end; +} + +#endif diff --git a/sysdeps/unix/sysv/linux/ia64/cancellation-sigmask.h b/sysdeps/unix/sysv/linux/ia64/cancellation-sigmask.h new file mode 100644 index 0000000000..05c3f90ab9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/cancellation-sigmask.h @@ -0,0 +1,33 @@ +/* Architecture specific bits for cancellation handling. + Copyright (C) 2020 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 + . */ + +#ifndef _NPTL_CANCELLATION_SIGMASK_H +#define _NPTL_CANCELLATION_SIGMASK_H 1 + +/* Add the SIGCANCEL signal on sigmask set at the ucontext CTX obtained from + the sigaction handler. */ +static void +ucontext_block_sigcancel (void *ctx) +{ + /* IA64 issues a sigcontext as third argument for sigaction handler (instead + of usual ucontext_t). */ + struct sigcontext *sctx = (struct sigcontext *) (ctx); + __sigaddset ((sigset_t *) &sctx->sc_mask, SIGCANCEL); +} + +#endif diff --git a/sysdeps/unix/sysv/linux/ia64/syscall_cancel.S b/sysdeps/unix/sysv/linux/ia64/syscall_cancel.S new file mode 100644 index 0000000000..92f358ab2e --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/syscall_cancel.S @@ -0,0 +1,81 @@ +/* Cancellable syscall wrapper. Linux/IA64 version. + Copyright (C) 2020 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 +#undef ret + +/* long int __syscall_cancel_arch (int *cancelhandling, long int nr, + long int arg1, long int arg2, long int arg3, + long int arg4, long int arg5, long int arg6) +*/ + +ENTRY (__syscall_cancel_arch) + .prologue ASM_UNW_PRLG_RP | ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE (8) + .mmi + .save ar.pfs, r41 + alloc r41=ar.pfs,8,3,8,0 + mov r15=r33 + .save rp, r40 + mov r40=b0 + .body + .mmi + mov r43=r34 + mov r44=r35 + mov r45=r36 + ;; + .mmi + mov r46=r37 + mov r47=r38 + mov r48=r39 + ;; + + .global __syscall_cancel_arch_start +__syscall_cancel_arch_start: + ;; + .mmi + nop 0 + ld4.acq r14=[r32] + nop 0 + ;; + .mib + nop 0 + tbit.z p6, p7=r14, TCB_CANCELED_BIT + .pred.safe_across_calls p1-p63 +(p7) br.call.dpnt.many b0 = __syscall_do_cancel# + .pred.safe_across_calls p1-p5,p16-p63 + ;; + + /* Due instruction bundle ia64 has the end marker before the syscall + instruction. Check IA64 ucontext_check_pc_boundary on how the PC + is checked. */ + .global __syscall_cancel_arch_end +__syscall_cancel_arch_end: + break 0x100000 + ;; + .mmi + cmp.ne p6, p7=-1, r10 + nop 0 + mov b0=r40 + ;; + .mib +(p7) sub r8=r0, r8 + mov ar.pfs=r41 + br.ret.sptk.many b0 + +END (__syscall_cancel_arch) +libc_hidden_def (__syscall_cancel_arch)