public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/azanella/pthread-multiple-fixes] nptl: ia64: Fix Race conditions in pthread cancellation [BZ#12683]
@ 2021-06-08 20:49 Adhemerval Zanella
  0 siblings, 0 replies; only message in thread
From: Adhemerval Zanella @ 2021-06-08 20:49 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=e9239873c8f775cd7aee0d5ccf0681c570467bb8

commit e9239873c8f775cd7aee0d5ccf0681c570467bb8
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Mon Jan 16 17:01:44 2017 -0200

    nptl: ia64: Fix Race conditions in pthread cancellation [BZ#12683]
    
    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.
    
    Checked on ia64-linux-gnu.

Diff:
---
 sysdeps/ia64/nptl/tcb-offsets.sym                  |  3 +
 .../unix/sysv/linux/ia64/cancellation-pc-check.h   | 48 +++++++++++++
 sysdeps/unix/sysv/linux/ia64/syscall_cancel.S      | 81 ++++++++++++++++++++++
 3 files changed, 132 insertions(+)

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
+   <http://www.gnu.org/licenses/>.  */
+
+#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/syscall_cancel.S b/sysdeps/unix/sysv/linux/ia64/syscall_cancel.S
new file mode 100644
index 0000000000..ebe8514993
--- /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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#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 = __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)


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-06-08 20:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-08 20:49 [glibc/azanella/pthread-multiple-fixes] nptl: ia64: Fix Race conditions in pthread cancellation [BZ#12683] Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).