On 11/18/20 12:42 PM, Alejandro Colomar (man-pages) wrote: > [[ Removed some CCs because gmail > didn't allow me to send it with so many CCs: > Kevin B., Andrey K., Helge D., David S. > ]] > > On 11/18/20 12:54 AM, Peter Collingbourne wrote: >> Signed-off-by: Peter Collingbourne <pcc@xxxxxxxxxx> >> --- >> These features are implemented in this patch series: >> > https://lore.kernel.org/linux-arm-kernel/cover.1605235762.git.pcc@xxxxxxxxxx/ >> which is still under review, so the patch should not be applied >> yet. >> >> Alejandro, thanks for the review. Since the patch was almost >> rewritten I didn't base this on your patch, instead I tried to >> use the correct formatting in this patch. > > Hi Peter, > > Fine. > See below a small fix. D'oh! Fixing the CCs I forgot to add the fix to the code. See below now. > > Cheers, > > Alex > >> >> v2: >> - fix formatting >> - address feedback from Dave >> >> man2/sigaction.2 | 125 +++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 125 insertions(+) >> >> diff --git a/man2/sigaction.2 b/man2/sigaction.2 >> index 6a8142324..0e4236a43 100644 >> --- a/man2/sigaction.2 >> +++ b/man2/sigaction.2 >> @@ -250,6 +250,44 @@ This flag is meaningful only when establishing a > signal handler. >> .\" .I sa_sigaction >> .\" field was added in Linux 2.1.86.) >> .\" >> +.TP >> +.BR SA_UNSUPPORTED >> +Used to dynamically probe for flag bit support. >> +.IP >> +If an attempt to register a handler succeeds with this flag set in >> +.I act->sa_flags >> +alongside other flags that are potentially unsupported by the kernel, >> +and an immediately subsequent >> +.BR sigaction () >> +call specifying the same signal number n and with non-NULL >> +.I oldact >> +yields >> +.B SA_UNSUPPORTED >> +.I clear >> +in >> +.IR oldact->sa_flags , >> +then >> +.IR oldact->sa_flags s/.IR/.I/ There's no roman part there. >> +may be used as a bitmask >> +describing which of the potentially unsupported flags are, >> +in fact, supported. >> +See the section "Dynamically probing for flag bit support" >> +below for more details. >> +.TP >> +.BR SA_EXPOSE_TAGBITS " (since Linux 5.x)" >> +Normally, when delivering a signal, >> +an architecture-specific set of tag bits are cleared from the >> +.I si_addr >> +field of >> +.IR siginfo_t . >> +If this flag is set, >> +an architecture-specific subset of the tag bits will be preserved in >> +.IR si_addr . >> +.IP >> +Programs that need to be compatible with Linux versions older than 5.x >> +must use >> +.B SA_UNSUPPORTED >> +to probe for support. >> .SS The siginfo_t argument to a SA_SIGINFO handler >> When the >> .B SA_SIGINFO >> @@ -833,6 +871,93 @@ Triggered by a >> .BR seccomp (2) >> filter rule. >> .RE >> +.SS Dynamically probing for flag bit support >> +The >> +.BR sigaction () >> +call on Linux accepts unknown bits set in >> +.I act->sa_flags >> +without error. >> +The behavior of the kernel starting with Linux 5.x is that a second >> +.BR sigaction () >> +will clear unknown bits from >> +.IR oldact->sa_flags . >> +However, historically, a second >> +.BR sigaction () >> +call would typically leave those bits set in >> +.IR oldact->sa_flags . >> +.PP >> +This means that support for new flags cannot be detected >> +simply by testing for a flag in >> +.IR sa_flags , >> +and a program must test that >> +.B SA_UNSUPPORTED >> +has been cleared before relying on the contents of >> +.IR sa_flags . >> +.PP >> +Since the behavior of the signal handler cannot be guaranteed >> +unless the check passes, >> +it is wise to either block the affected signal >> +while registering the handler and performing the check in this case, >> +or where this is not possible, >> +for example if the signal is synchronous, to issue the second >> +.BR sigaction () >> +in the signal handler itself. >> +.PP >> +In kernels that do not support a specific flag, >> +the kernel's behavior is as if the flag was not set, >> +even if the flag was set in >> +.IR act->sa_flags . >> +.PP >> +The flags >> +.BR SA_NOCLDSTOP , >> +.BR SA_NOCLDWAIT , >> +.BR SA_SIGINFO , >> +.BR SA_ONSTACK , >> +.BR SA_RESTART , >> +.BR SA_NODEFER , >> +.BR SA_RESETHAND , >> +and, if defined by the architecture, >> +.B SA_RESTORER >> +may not be reliably probed for using this mechanism, >> +because they were introduced before Linux 5.x. >> +However, in general, programs may assume that these flags are supported, >> +since they have all been supported since Linux 2.6, >> +which was released in the year 2003. >> +.PP >> +The following example program exits with status 0 if >> +.B SA_EXPOSE_TAGBITS >> +is determined to be supported, and 1 otherwise. >> +.PP >> +.EX >> +#include <signal.h> >> +#include <stdio.h> >> +#include <unistd.h> >> + >> +void handler(int signo, siginfo_t *info, void *context) { >> + struct sigaction oldact; >> + if (sigaction(SIGSEGV, 0, &oldact) == 0 && >> + !(oldact.sa_flags & SA_UNSUPPORTED) && >> + (oldact.sa_flags & SA_EXPOSE_TAGBITS)) { >> + _exit(0); >> + } else { >> + _exit(1); >> + } >> +} >> + >> +int main(void) { >> + struct sigaction act = {}; >> + act.sa_flags = SA_SIGINFO | SA_UNSUPPORTED | SA_EXPOSE_TAGBITS; >> + act.sa_sigaction = handler; >> + if (sigaction(SIGSEGV, &act, 0) != 0) { >> + perror("sigaction"); >> + return 1; >> + } >> + >> + /* Force a SIGSEGV. */ >> + *(volatile int *)0 = 0; >> + return 1; >> +} >> +.EE >> .SH RETURN VALUE >> .BR sigaction () >> returns 0 on success; on error, \-1 is returned, and >>