From patchwork Thu Dec 5 18:34:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 36546 Received: (qmail 60749 invoked by alias); 5 Dec 2019 18:34:50 -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 60575 invoked by uid 89); 5 Dec 2019 18:34:49 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=HX-Received:a67 X-HELO: mail-vs1-f67.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references; bh=DVUxp5bgMUoOw2DPjJDOjO2OGU+DHE/E00Y6OiPYYVg=; b=hDFRUB1sPoNHdqfxljB3/J1/k9B3gvEQCVgJ3E0K4ihDrtVHRnT6CteTFKwI77pmiF AbhIDClL79MHRaaMckelBBPi2P0fdtyfTvIkgE5jH6ZDxfUd7RZ4J1IHT4KzZN2pcI4F dXTQN5dwmDdEfFG0y0Yl8bMggfB21yki2mreCwtd9LqSq1amRI3zJkXQywC1EIXb9QoB p3Kj8jCZ4DtZQD+Pp1z4KiAQhkPPYP06O3LdDOjojluJuo8PxLGJpTTczPjA+ltnY9Xa BM4uZN+ZM1NV2J3LrlsQHWqRnxkDXPSpJjvwq4ULB8F5J+sOduOdXq/I/iyXQO6OD+Wx 02Ew== Return-Path: From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2 3/3] Fix __libc_signal_block_all on sparc64 Date: Thu, 5 Dec 2019 15:34:37 -0300 Message-Id: <20191205183437.22696-3-adhemerval.zanella@linaro.org> In-Reply-To: <20191205183437.22696-1-adhemerval.zanella@linaro.org> References: <20191205183437.22696-1-adhemerval.zanella@linaro.org> The a2e8aa0d9e shows two regressions on sparc64-linux-gnu: nptl/tst-cancel-self-canceltype nptl/tst-cancel5 This is not from the patch itself, but rather from an invalid __NR_rt_sigprocmask issued by the loader: rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0 rt_sigprocmask(0xffd07c60 /* SIG_??? */, ~[], 0x7feffd07d08, 8) = -1 EINVAL (Invalid argument) Tracking the culprit it really seems a wrong code generation in the INTERNAL_SYSCALL due the automatic sigset_t used on __libc_signal_block_all: return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &SIGALL_SET, set, _NSIG / 8); Where SIGALL_SET is defined as: ((__sigset_t) { .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } }) Building the expanded __libc_signal_block_all on sparc64 with recent compiler (gcc 8.3.1 and 9.1.1): #include int _libc_signal_block_all (sigset_t *set) { INTERNAL_SYSCALL_DECL (err); return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &SIGALL_SET, set, _NSIG / 8); } It seems that the first argument (SIG_BLOCK) is not correctly set on 'o0' register: __libc_signal_block_all: save %sp, -304, %sp add %fp, 1919, %o0 mov 128, %o2 sethi %hi(.LC0), %o1 call memcpy, 0 or %o1, %lo(.LC0), %o1 add %fp, 1919, %o1 mov %i0, %o2 mov 8, %o3 mov 103, %g1 ta 0x6d; bcc,pt %xcc, 1f mov 0, %g1 sub %g0, %o0, %o0 mov 1, %g1 1: sra %o0, 0, %i0 return %i7+8 nop Where is I define SIGALL_SET outside INTERNAL_SYSCALL macro, gcc correctly sets the expected kernel argument in correct register: sethi %hi(.LC0), %o1 call memcpy, 0 or %o1, %lo(.LC0), %o1 -> mov 1, %o0 add %fp, 1919, %o1 This patch fixes it by moving both sigset_t that represent all signals sets and the application set to constant data objects. This patch also changes the return value of __libc_signal_block_all, __libc_signal_block_app, and __libc_signal_restore_set to 'void' since the function should not fail if input argument is NULL. Also, for Linux the return value is not fully correct on some platforms due the missing usage of INTERNAL_SYSCALL_ERROR_P / INTERNAL_SYSCALL_ERRNO macros. Checked on x86_64-linux-gnu, i686-linux-gnu, and sparc64-linux-gnu. --- sysdeps/unix/sysv/linux/internal-signals.h | 37 ++++++++++++++-------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h index 01d8bf0a4c..ae2d626ef0 100644 --- a/sysdeps/unix/sysv/linux/internal-signals.h +++ b/sysdeps/unix/sysv/linux/internal-signals.h @@ -53,36 +53,47 @@ __clear_internal_signals (sigset_t *set) __sigdelset (set, SIGSETXID); } -#define SIGALL_SET \ - ((__sigset_t) { .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } }) +static const sigset_t sigall_set = { + .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } +}; + +static const sigset_t sigapp_set = { +#if ULONG_MAX == 0xffffffff + .__val = { [0] = ~0UL & ~(__sigmask (SIGCANCEL)), + [1] = ~0UL & ~(__sigmask (SIGSETXID)), + [2 ... _SIGSET_NWORDS-1] = ~0UL } +#else + .__val = { [0] = ~0UL & ~(__sigmask (SIGCANCEL) + | __sigmask (SIGSETXID)), + [1 ... _SIGSET_NWORDS-1] = ~0UL } +#endif +}; /* Block all signals, including internal glibc ones. */ -static inline int +static inline void __libc_signal_block_all (sigset_t *set) { INTERNAL_SYSCALL_DECL (err); - return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &SIGALL_SET, - set, _NSIG / 8); + INTERNAL_SYSCALL_CALL (rt_sigprocmask, err, SIG_BLOCK, &sigall_set, set, + _NSIG / 8); } /* Block all application signals (excluding internal glibc ones). */ -static inline int +static inline void __libc_signal_block_app (sigset_t *set) { - sigset_t allset = SIGALL_SET; - __clear_internal_signals (&allset); INTERNAL_SYSCALL_DECL (err); - return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &allset, set, - _NSIG / 8); + INTERNAL_SYSCALL_CALL (rt_sigprocmask, err, SIG_BLOCK, &sigapp_set, set, + _NSIG / 8); } /* Restore current process signal mask. */ -static inline int +static inline void __libc_signal_restore_set (const sigset_t *set) { INTERNAL_SYSCALL_DECL (err); - return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, set, NULL, - _NSIG / 8); + INTERNAL_SYSCALL_CALL (rt_sigprocmask, err, SIG_SETMASK, set, NULL, + _NSIG / 8); } /* Used to communicate with signal handler. */