diff mbox series

[v2] sigaction.2: Document SA_EXPOSE_TAGBITS and the flag support detection protocol

Message ID 20201117235447.816252-1-pcc@google.com (mailing list archive)
State New, archived
Headers show
Series [v2] sigaction.2: Document SA_EXPOSE_TAGBITS and the flag support detection protocol | expand

Commit Message

Peter Collingbourne Nov. 17, 2020, 11:54 p.m. UTC
Signed-off-by: Peter Collingbourne <pcc@google.com>
---
These features are implemented in this patch series:
  https://lore.kernel.org/linux-arm-kernel/cover.1605235762.git.pcc@google.com/
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.

v2:
- fix formatting
- address feedback from Dave

 man2/sigaction.2 | 125 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)

Comments

Alejandro Colomar Nov. 18, 2020, 11:42 a.m. UTC | #1
[[ 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@google.com>
> ---
> These features are implemented in this patch series:
>
https://lore.kernel.org/linux-arm-kernel/cover.1605235762.git.pcc@google.com/
> 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.

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
> +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
>
Alejandro Colomar Nov. 18, 2020, 2:04 p.m. UTC | #2
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@google.com>
>> ---
>> These features are implemented in this patch series:
>>
> https://lore.kernel.org/linux-arm-kernel/cover.1605235762.git.pcc@google.com/
>> 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
>>
Alejandro Colomar Dec. 18, 2020, 10:27 a.m. UTC | #3
Hi Peter,

Linux 5.10 has been recently released.
Was this merged to 5.10 or 5.11?
Do you have any updates for this patch?

Thanks,

Alex

On 11/18/20 3:04 PM, Alejandro Colomar (man-pages) wrote:
> 
> 
> 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@google.com>
>>> ---
>>> These features are implemented in this patch series:
>>>
>> https://lore.kernel.org/linux-arm-kernel/cover.1605235762.git.pcc@google.com/
>>> 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
>>>
Peter Collingbourne Dec. 21, 2020, 6:17 p.m. UTC | #4
Hi Alex,

The feature is due to be merged in 5.11 so presumably we should wait
until then. I have no updates for the patch; at this point I am hoping
for comments (or a Reviewed-by) from Dave.

I saw your s/.IR/.I/ and I will do that once I have another update for
the patch.

Peter

On Fri, Dec 18, 2020 at 2:27 AM Alejandro Colomar (man-pages)
<alx.manpages@gmail.com> wrote:
>
> Hi Peter,
>
> Linux 5.10 has been recently released.
> Was this merged to 5.10 or 5.11?
> Do you have any updates for this patch?
>
> Thanks,
>
> Alex
>
> On 11/18/20 3:04 PM, Alejandro Colomar (man-pages) wrote:
> >
> >
> > 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@google.com>
> >>> ---
> >>> These features are implemented in this patch series:
> >>>
> >> https://lore.kernel.org/linux-arm-kernel/cover.1605235762.git.pcc@google.com/
> >>> 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
> >>>
>
> --
> Alejandro Colomar
> Linux man-pages comaintainer; https://www.kernel.org/doc/man-pages/
> http://www.alejandro-colomar.es/
diff mbox series

Patch

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
+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