I have run into problem using sigaddset() with constant signal argument in kernel code. A code like the following gets miscompiled: sigset_t a; sigset_t b; sigset_t c; ........... sigaddset(&a, const1); sigaddset(&a, const2); ................................ b =a; /* this line causes incorrect code; any 64-bit assignment seems to cause a problem! */ sigaddset(&c, const2); sigaddset(&c, const3); /* more sigaddset to c */ At some iteration of sigaddset to c, c may get the value of a! All versions of compilers and all kernel versions are affected. The problem is also reproducible in user space (with kernel sigaddset definition). Looking at the dissassembly (or running in the debugger) clearly shows that gcc miscompiled the code. The problem goes away if optimization is disabled, if just -O flag is used, or if variables are used instead of constants. Attached please find a C code (can be compiled into module or executable) that demonstrates the problem (problem occurs if -O2 flag is used). Attached is also a patch that fixes the problem (the patch was prepared against 2.6 tree). I defined sigaddset a macro (similar to sigismember) that calls one function for constant argument and another for variable. In addition to fixing the problem, it also makes sigaddset() faster for constant arguments. To be on the safe side, I changed sigdelset() in the same way (I think the same gcc bug may apply).
Created attachment 121167 [details] A sample of code using kernel sigaddset that shows the problem with -O2 flags
Created attachment 121168 [details] Proposed patch fo sigaddset and sigdelset to constant signal argument case miscompilation.
Created attachment 121170 [details] fix wrong sigaddset sigdelset for i386
According to jakub, who closed bug 173460, it is a pure kernel bug and not gcc problem. Instead of __asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig-1) : "cc"); sigsaddset must use __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig-1) : "cc"); I have reworked the pacth but kept the constant case optimization.
Created attachment 121174 [details] fix wrong sigaddset sigdelset for i386 Previous patch had a typo.
Removing dependency on bug 173460.
The bug has been fixed in 2.6.15 kernel (Linus accepted my patch). The bug remains in advanced server 3 release.
This bug is filed against RHEL 3, which is in maintenance phase. During the maintenance phase, only security errata and select mission critical bug fixes will be released for enterprise products. Since this bug does not meet that criteria, it is now being closed. For more information of the RHEL errata support policy, please visit: http://www.redhat.com/security/updates/errata/ If you feel this bug is indeed mission critical, please contact your support representative. You may be asked to provide detailed information on how this bug is affecting you.