From 566e10aa7292bacd74d229ca6f2cd9e8c8ba8748 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Thu, 12 Mar 2020 09:50:19 -0300 Subject: signal: Only handle on NSIG signals on signal functions (BZ #25657) The upper bits of the sigset_t s not fully initialized in the signal mask calls that return information from kernel (sigprocmask, sigpending, and pthread_sigmask), since the exported sigset_t size (1024 bits) is larger than Linux support one (64 or 128 bits). It might make sigisemptyset/sigorset/sigandset fail if the mask is filled prior the call. This patch changes the internal signal function to handle up to supported Linux signal number (_NSIG), the remaining bits are untouched. Checked on x86_64-linux-gnu and i686-linux-gnu. --- sysdeps/unix/sysv/linux/sigpending.c | 6 +- sysdeps/unix/sysv/linux/sigsetops.h | 155 +++++++++++++++++------------------ 2 files changed, 78 insertions(+), 83 deletions(-) (limited to 'sysdeps/unix/sysv/linux') diff --git a/sysdeps/unix/sysv/linux/sigpending.c b/sysdeps/unix/sysv/linux/sigpending.c index f6bedb5..458a3cf 100644 --- a/sysdeps/unix/sysv/linux/sigpending.c +++ b/sysdeps/unix/sysv/linux/sigpending.c @@ -15,13 +15,9 @@ License along with the GNU C Library; if not, see . */ -#include #include -#include - #include -#include - +#include /* Change the set of blocked signals to SET, wait until a signal arrives, and restore the set of blocked signals. */ diff --git a/sysdeps/unix/sysv/linux/sigsetops.h b/sysdeps/unix/sysv/linux/sigsetops.h index cb97c98..db8f378 100644 --- a/sysdeps/unix/sysv/linux/sigsetops.h +++ b/sysdeps/unix/sysv/linux/sigsetops.h @@ -26,83 +26,82 @@ (((unsigned long int) 1) << (((sig) - 1) % (8 * sizeof (unsigned long int)))) /* Return the word index for SIG. */ -# define __sigword(sig) (((sig) - 1) / (8 * sizeof (unsigned long int))) - -# define __sigemptyset(set) \ - (__extension__ ({ \ - int __cnt = _SIGSET_NWORDS; \ - sigset_t *__set = (set); \ - while (--__cnt >= 0) \ - __set->__val[__cnt] = 0; \ - (void)0; \ - })) - -# define __sigfillset(set) \ - (__extension__ ({ \ - int __cnt = _SIGSET_NWORDS; \ - sigset_t *__set = (set); \ - while (--__cnt >= 0) \ - __set->__val[__cnt] = ~0UL; \ - (void)0; \ - })) - -# define __sigisemptyset(set) \ - (__extension__ ({ \ - int __cnt = _SIGSET_NWORDS; \ - const sigset_t *__set = (set); \ - int __ret = __set->__val[--__cnt]; \ - while (!__ret && --__cnt >= 0) \ - __ret = __set->__val[__cnt]; \ - __ret == 0; \ - })) - -# define __sigandset(dest, left, right) \ - (__extension__ ({ \ - int __cnt = _SIGSET_NWORDS; \ - sigset_t *__dest = (dest); \ - const sigset_t *__left = (left); \ - const sigset_t *__right = (right); \ - while (--__cnt >= 0) \ - __dest->__val[__cnt] = (__left->__val[__cnt] \ - & __right->__val[__cnt]); \ - (void)0; \ - })) - -# define __sigorset(dest, left, right) \ - (__extension__ ({ \ - int __cnt = _SIGSET_NWORDS; \ - sigset_t *__dest = (dest); \ - const sigset_t *__left = (left); \ - const sigset_t *__right = (right); \ - while (--__cnt >= 0) \ - __dest->__val[__cnt] = (__left->__val[__cnt] \ - | __right->__val[__cnt]); \ - (void)0; \ - })) - -/* These macros needn't check for a bogus signal number; - error checking is done in the non-__ versions. */ -# define __sigismember(set, sig) \ - (__extension__ ({ \ - unsigned long int __mask = __sigmask (sig); \ - unsigned long int __word = __sigword (sig); \ - (set)->__val[__word] & __mask ? 1 : 0; \ - })) - -# define __sigaddset(set, sig) \ - (__extension__ ({ \ - unsigned long int __mask = __sigmask (sig); \ - unsigned long int __word = __sigword (sig); \ - (set)->__val[__word] |= __mask; \ - (void)0; \ - })) - -# define __sigdelset(set, sig) \ - (__extension__ ({ \ - unsigned long int __mask = __sigmask (sig); \ - unsigned long int __word = __sigword (sig); \ - (set)->__val[__word] &= ~__mask; \ - (void)0; \ - })) +static inline unsigned long int +__sigword (int sig) +{ + return (sig - 1) / (8 * sizeof (unsigned long int)); +} + +/* Linux sig* functions only handle up to __NSIG_WORDS words instead of + full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and + bit 0 of a signal mask is for signal 1. */ + +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) + +static inline void +__sigemptyset (sigset_t *set) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + set->__val[cnt] = 0; +} + +static inline void +__sigfillset (sigset_t *set) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + set->__val[cnt] = ~0UL; +} + +static inline int +__sigisemptyset (const sigset_t *set) +{ + int cnt = __NSIG_WORDS; + int ret = set->__val[--cnt]; + while (ret == 0 && --cnt >= 0) + ret = set->__val[cnt]; + return ret == 0; +} + +static inline void +__sigandset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + dest->__val[cnt] = left->__val[cnt] & right->__val[cnt]; +} + +static inline void +__sigorset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + dest->__val[cnt] = left->__val[cnt] | right->__val[cnt]; +} + +static inline int +__sigismember (const sigset_t *set, int sig) +{ + unsigned long int mask = __sigmask (sig); + unsigned long int word = __sigword (sig); + return set->__val[word] & mask ? 1 : 0; +} + +static inline void +__sigaddset (sigset_t *set, int sig) +{ + unsigned long int mask = __sigmask (sig); + unsigned long int word = __sigword (sig); + set->__val[word] |= mask; +} + +static inline void +__sigdelset (sigset_t *set, int sig) +{ + unsigned long int mask = __sigmask (sig); + unsigned long int word = __sigword (sig); + set->__val[word] &= ~mask; +} #endif /* bits/sigsetops.h */ -- cgit v1.1