Message ID | 20210715204610.575999-1-pcc@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v4] sigaction.2: Document SA_EXPOSE_TAGBITS and the flag support detection protocol | expand |
Hi Peter, On 7/15/21 10:46 PM, Peter Collingbourne wrote: > Signed-off-by: Peter Collingbourne <pcc@google.com> Thanks! I applied the patch. I applied some minor tweaks in a following commit (I didn't send it back to you because it was a bit of my fault for not having seen it before, and didn't want to make you lose more time with that): sigaction.2: Apply minor tweaks to Peter's patch - Move example program to a new EXAMPLES section - Invert logic in the handler to have the failure in the conditional path, and the success out of any conditionals. - Use NULL, EXIT_SUCCESS, and EXIT_FAILURE instead of magic numbers - Separate declarations from code - Put function return type on its own line - Put function opening brace on its line You can see the diff in my tree: <https://github.com/alejandro-colomar/man-pages> I'll resend it to Michael very soon (I hope today), so you'll see there anyway. You can comment there if you find something that you don't like , or if I broke anything accidentally :) Cheers, Alex > --- > v4: > - s/.BR/.BR/ in one location > - 4 space indentation > - raise(SIGSEGV) instead of manual SIGSEGV > - use C99 initialization > > v3: > - s/5.x/5.11/g > - s/.IR/.I/ in one location > > v2: > - fix formatting > - address feedback from Dave > > man2/sigaction.2 | 123 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 123 insertions(+) > > diff --git a/man2/sigaction.2 b/man2/sigaction.2 > index 57ad6418c..4bf6f095e 100644 > --- a/man2/sigaction.2 > +++ b/man2/sigaction.2 > @@ -261,6 +261,44 @@ This flag is meaningful only when establishing a signal handler. > .\" .I sa_sigaction > .\" field was added in Linux 2.1.86.) > .\" > +.TP > +.B 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 > +.I oldact->sa_flags > +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.11)" > +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.11 > +must use > +.B SA_UNSUPPORTED > +to probe for support. > .SS The siginfo_t argument to a SA_SIGINFO handler > When the > .B SA_SIGINFO > @@ -846,6 +884,91 @@ 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.11 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.11. > +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 = {0}; > + act.sa_flags = SA_SIGINFO | SA_UNSUPPORTED | SA_EXPOSE_TAGBITS; > + act.sa_sigaction = handler; > + if (sigaction(SIGSEGV, &act, 0) != 0) { > + perror("sigaction"); > + return 1; > + } > + > + raise(SIGSEGV); > +} > +.EE > .SH RETURN VALUE > .BR sigaction () > returns 0 on success; on error, \-1 is returned, and >
diff --git a/man2/sigaction.2 b/man2/sigaction.2 index 57ad6418c..4bf6f095e 100644 --- a/man2/sigaction.2 +++ b/man2/sigaction.2 @@ -261,6 +261,44 @@ This flag is meaningful only when establishing a signal handler. .\" .I sa_sigaction .\" field was added in Linux 2.1.86.) .\" +.TP +.B 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 +.I oldact->sa_flags +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.11)" +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.11 +must use +.B SA_UNSUPPORTED +to probe for support. .SS The siginfo_t argument to a SA_SIGINFO handler When the .B SA_SIGINFO @@ -846,6 +884,91 @@ 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.11 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.11. +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 = {0}; + act.sa_flags = SA_SIGINFO | SA_UNSUPPORTED | SA_EXPOSE_TAGBITS; + act.sa_sigaction = handler; + if (sigaction(SIGSEGV, &act, 0) != 0) { + perror("sigaction"); + return 1; + } + + raise(SIGSEGV); +} +.EE .SH RETURN VALUE .BR sigaction () returns 0 on success; on error, \-1 is returned, and
Signed-off-by: Peter Collingbourne <pcc@google.com> --- v4: - s/.BR/.BR/ in one location - 4 space indentation - raise(SIGSEGV) instead of manual SIGSEGV - use C99 initialization v3: - s/5.x/5.11/g - s/.IR/.I/ in one location v2: - fix formatting - address feedback from Dave man2/sigaction.2 | 123 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+)