signal: move the "sig < SIGRTMIN" check into siginmask(sig)
PATCH 1/1 signal: move the "sig < SIGRTMIN" check into siginmask(sig)
All the users of siginmask() must ensure that sig < SIGRTMIN. sig_fatal() doesn't and this is wrong:
[ 211.406327] UBSAN: Undefined behaviour in kernel/signal.c:911:6 [ 211.406365] shift exponent 32 is too large for 32-bit type 'long unsigned int'
the patch doesn't add the neccesary check to sig_fatal(), it moves the check into siginmask() and updates other callers.
Reported-by Meelis Roos <[email protected]>
Signed-off-by Oleg Nesterov <[email protected]>
--- include/linux/signal.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
include/linux/signal.h +7 -9
@@ -385,7 +385,9 @@ int unhandled_signal(struct task_struct *tsk, int sig);#else #define rt_sigmask (sig) sigmask(sig)#endif -#define siginmask (sig, mask) (rt_sigmask(sig) & (mask)) + +#define siginmask (sig, mask) \ + ((sig) < SIGRTMIN && (rt_sigmask(sig) & (mask)))#define SIG_KERNEL_ONLY_MASK (\ rt_sigmask(SIGKILL) | rt_sigmask(SIGSTOP))
@@ -406,14 +408,10 @@ int unhandled_signal(struct task_struct *tsk, int sig); rt_sigmask(SIGCONT) | rt_sigmask(SIGCHLD) | \ rt_sigmask(SIGWINCH) | rt_sigmask(SIGURG) ) -#define sig_kernel_only (sig) \ - (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_ONLY_MASK)) -#define sig_kernel_coredump (sig) \ - (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_COREDUMP_MASK)) -#define sig_kernel_ignore (sig) \ - (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_IGNORE_MASK)) -#define sig_kernel_stop (sig) \ - (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_STOP_MASK)) +#define sig_kernel_only (sig) siginmask(sig, SIG_KERNEL_ONLY_MASK) +#define sig_kernel_coredump (sig) siginmask(sig, SIG_KERNEL_COREDUMP_MASK) +#define sig_kernel_ignore (sig) siginmask(sig, SIG_KERNEL_IGNORE_MASK) +#define sig_kernel_stop (sig) siginmask(sig, SIG_KERNEL_STOP_MASK)#define sig_user_defined (t, signr) \ (((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) && \
Signature · 1 line
2.5.0
Quoted 11 lines
All the users of
siginmask()must ensure that sig < SIGRTMIN.sig_fatal()doesn't and this is wrong:[ 211.406327] UBSAN: Undefined behaviour in kernel/signal.c:911:6 [ 211.406365] shift exponent 32 is too large for 32-bit type 'long unsigned int'the patch doesn't add the neccesary check to
sig_fatal(), it moves the check intosiginmask()and updates other callers.Reported-by Meelis Roos <[email protected]>Signed-off-by Oleg Nesterov <[email protected]>
Tested on the same AthlonMP, on HP Proliant DL360G3 and PowerMac G4, successfully - system still works, warnings are gone.
Signature · 1 line
Meelis Roos ([email protected])