Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1647354 > unrolled thread
| Started by | "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> |
|---|---|
| First post | 2017-05-22 22:40 +0200 |
| Last post | 2017-05-24 22:20 +0200 |
| Articles | 8 — 2 participants |
Back to article view | Back to linux.kernel
Documenting sigaltstack SS_AUTODISRM "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> - 2017-05-22 22:40 +0200
Re: Documenting sigaltstack SS_AUTODISRM Stas Sergeev <stsp@list.ru> - 2017-05-23 01:40 +0200
Re: Documenting sigaltstack SS_AUTODISRM "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> - 2017-05-23 12:40 +0200
Re: Documenting sigaltstack SS_AUTODISRM Stas Sergeev <stsp@list.ru> - 2017-05-23 13:10 +0200
Re: Documenting sigaltstack SS_AUTODISRM "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> - 2017-05-23 14:30 +0200
Re: Documenting sigaltstack SS_AUTODISRM Stas Sergeev <stsp@list.ru> - 2017-05-24 01:10 +0200
Re: Documenting sigaltstack SS_AUTODISRM "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> - 2017-05-24 13:20 +0200
Re: Documenting sigaltstack SS_AUTODISRM Stas Sergeev <stsp@list.ru> - 2017-05-24 22:20 +0200
| From | "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> |
|---|---|
| Date | 2017-05-22 22:40 +0200 |
| Subject | Documenting sigaltstack SS_AUTODISRM |
| Message-ID | <tK2hs-1Tl-11@gated-at.bofh.it> |
Stas,
I have attempted to document the SS_AUTODISARM feature that you added
in Linux 4.7.
Could you please take a look at the SS_AUTODISARM pieces in the
sigaltstack() man page below? There is also one FIXME that I would
like help with.
It seems to me that the API has become rather odd now. It is no longer
possible to simply check whether code is executing on an alternative
stack by using
sigaltstack(NULL, &old_ss);
if (old_ss.ss_flags & SS_ONSTACK)
....
Thanks,
Michael
NAME
sigaltstack - set and/or get signal stack context
SYNOPSIS
#include <signal.h>
int sigaltstack(const stack_t *ss, stack_t *old_ss);
Feature Test Macro Requirements for glibc (see fea‐
ture_test_macros(7)):
sigaltstack():
_XOPEN_SOURCE >= 500
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
|| /* Glibc versions <= 2.19: */ _BSD_SOURCE
DESCRIPTION
sigaltstack() allows a process to define a new alternate signal
stack and/or retrieve the state of an existing alternate signal
stack. An alternate signal stack is used during the execution
of a signal handler if the establishment of that handler (see
sigaction(2)) requested it.
The normal sequence of events for using an alternate signal
stack is the following:
1. Allocate an area of memory to be used for the alternate sig‐
nal stack.
2. Use sigaltstack() to inform the system of the existence and
location of the alternate signal stack.
3. When establishing a signal handler using sigaction(2),
inform the system that the signal handler should be executed
on the alternate signal stack by specifying the SA_ONSTACK
flag.
The ss argument is used to specify a new alternate signal
stack, while the old_ss argument is used to retrieve informa‐
tion about the currently established signal stack. If we are
interested in performing just one of these tasks, then the
other argument can be specified as NULL.
The stack_t type used to type the arguments of this function is
defined as follows:
typedef struct {
void *ss_sp; /* Base address of stack */
int ss_flags; /* Flags */
size_t ss_size; /* Number of bytes in stack */
} stack_t;
To establish a new alternate signal stack, the fields of this
structure are set as follows:
ss.ss_flags
This field contains either 0, or the following flag:
SS_AUTODISARM (since Linux 4.7)
Clear the alternate signal stack settings on
entry to the signal handler. When the signal
handler returns, the previous alternate signal
stack settings are restored.
This flag was added in order make it safe to
switch away from the signal handler with swapcon‐
text(3). Without this flag, a subsequently han‐
dled signal will corrupt the state of the
switched-away signal handler. On kernels where
this flag is not supported, sigaltstack() fails
with the error EINVAL when this flag is supplied.
ss.ss_sp
This field specifies the starting address of the stack.
When a signal handler is invoked on the alternate stack,
the kernel automatically aligns the address given in
ss.ss_sp to a suitable address boundary for the underly‐
ing hardware architecture.
ss.ss_size
This field specifies the size of the stack. The con‐
stant SIGSTKSZ is defined to be large enough to cover
the usual size requirements for an alternate signal
stack, and the constant MINSIGSTKSZ defines the minimum
size required to execute a signal handler.
To disable an existing stack, specify ss.ss_flags as SS_DIS‐
ABLE. In this case, the kernel ignores any other flags in
ss.ss_flags and the remaining fields in ss.
If old_ss is not NULL, then it is used to return information
about the alternate signal stack which was in effect prior to
the call to sigaltstack(). The old_ss.ss_sp and old_ss.ss_size
fields return the starting address and size of that stack. The
old_ss.ss_flags may return either of the following values:
SS_ONSTACK
The process is currently executing on the alternate sig‐
nal stack. (Note that it is not possible to change the
alternate signal stack if the process is currently exe‐
cuting on it.)
SS_DISABLE
The alternate signal stack is currently disabled.
Alternatively, this value is returned if the process is
currently executing on an alternate signal stack that
was established using the SS_AUTODISARM flag. In this
case, it is safe to switch away from the signal handler
with swapcontext(3). It is also possible to set up a
different alternative signal stack using a further call
to sigaltstack().
┌─────────────────────────────────────────────────────┐
│FIXME │
├─────────────────────────────────────────────────────┤
│Was it intended that one can set up a different │
│alternative signal stack in this scenario? (In pass‐ │
│ing, if one does this, the sigaltstack(NULL, │
│&old_ss) now returns old_ss.ss_flags==SS_AUTODISARM │
│rather than old_ss.ss_flags==SS_DISABLE. The API │
│design here seems confusing... │
└─────────────────────────────────────────────────────┘
SS_AUTODISARM
The alternate signal stack has been marked to be
autodisarmed as described above.
By specifying ss as NULL, and old_ss as a non-NULL value, one
can obtain the current settings for the alternate signal stack
without changing them.
RETURN VALUE
sigaltstack() returns 0 on success, or -1 on failure with errno
set to indicate the error.
ERRORS
EFAULT Either ss or old_ss is not NULL and points to an area
outside of the process's address space.
EINVAL ss is not NULL and the ss_flags field contains an
invalid flag.
ENOMEM The specified size of the new alternate signal stack
ss.ss_size was less than MINSTKSZ.
EPERM An attempt was made to change the alternate signal stack
while it was active (i.e., the process was already exe‐
cuting on the current alternate signal stack).
ATTRIBUTES
For an explanation of the terms used in this section, see
attributes(7).
┌──────────────┬───────────────┬─────────┐
│Interface │ Attribute │ Value │
├──────────────┼───────────────┼─────────┤
│sigaltstack() │ Thread safety │ MT-Safe │
└──────────────┴───────────────┴─────────┘
CONFORMING TO
POSIX.1-2001, POSIX.1-2009, SUSv2, SVr4.
The SS_AUTODISARM flag is a Linux extension.
NOTES
The most common usage of an alternate signal stack is to handle
the SIGSEGV signal that is generated if the space available for
the normal process stack is exhausted: in this case, a signal
handler for SIGSEGV cannot be invoked on the process stack; if
we wish to handle it, we must use an alternate signal stack.
Establishing an alternate signal stack is useful if a process
expects that it may exhaust its standard stack. This may
occur, for example, because the stack grows so large that it
encounters the upwardly growing heap, or it reaches a limit
established by a call to setrlimit(RLIMIT_STACK, &rlim). If
the standard stack is exhausted, the kernel sends the process a
SIGSEGV signal. In these circumstances the only way to catch
this signal is on an alternate signal stack.
On most hardware architectures supported by Linux, stacks grow
downward. sigaltstack() automatically takes account of the
direction of stack growth.
Functions called from a signal handler executing on an alter‐
nate signal stack will also use the alternate signal stack.
(This also applies to any handlers invoked for other signals
while the process is executing on the alternate signal stack.)
Unlike the standard stack, the system does not automatically
extend the alternate signal stack. Exceeding the allocated
size of the alternate signal stack will lead to unpredictable
results.
A successful call to execve(2) removes any existing alternate
signal stack. A child process created via fork(2) inherits a
copy of its parent's alternate signal stack settings.
sigaltstack() supersedes the older sigstack() call. For back‐
ward compatibility, glibc also provides sigstack(). All new
applications should be written using sigaltstack().
History
4.2BSD had a sigstack() system call. It used a slightly dif‐
ferent struct, and had the major disadvantage that the caller
had to know the direction of stack growth.
EXAMPLE
The following code segment demonstrates the use of sigalt‐
stack():
stack_t ss;
ss.ss_sp = malloc(SIGSTKSZ);
if (ss.ss_sp == NULL)
/* Handle error */;
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1)
/* Handle error */;
BUGS
In the lead up to the development of the Linux 2.4 kernel,
someone got confused and allowed the kernel to accept
SS_ONSTACK in ss.ss_flags, which results behavior that is the
same as when ss_flags is 0. On other implementations, and
according to POSIX.1, SS_ONSTACK appears only as a reported
flag in old_ss.ss_flags. There is no need ever to specify this
flag in ss.ss_flags.
SEE ALSO
execve(2), setrlimit(2), sigaction(2), siglongjmp(3),
sigsetjmp(3), signal(7)
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
[toc] | [next] | [standalone]
| From | Stas Sergeev <stsp@list.ru> |
|---|---|
| Date | 2017-05-23 01:40 +0200 |
| Message-ID | <tK55E-3FX-17@gated-at.bofh.it> |
| In reply to | #1647354 |
22.05.2017 23:38, Michael Kerrisk (man-pages) пишет: > Stas, > > I have attempted to document the SS_AUTODISARM feature that you added > in Linux 4.7. > > Could you please take a look at the SS_AUTODISARM pieces in the > sigaltstack() man page below? There is also one FIXME that I would > like help with. > > It seems to me that the API has become rather odd now. It is no longer > possible to simply check whether code is executing on an alternative > stack by using > > sigaltstack(NULL, &old_ss); > if (old_ss.ss_flags & SS_ONSTACK) You mean, if SS_AUTODISARM was previously used, right? Because I don't think we broke the existing code, or did we? I can vaguely recall that I was submitting the patches that were returning SS_ONSTACK even when SS_AUTODISARM was used, but they were considered too complex. This is possible to implement, but the agreement was that it is not a big deal. > ss.ss_flags > This field contains either 0, or the following flag: Is this correct? AFAIK it can be SS_DISABLE too, and posix seems to allow any other value for enable, which can be (on linux) SS_ONSTACK, not only 0. And SS_AUTODISARM can be ORed with the value. > ┌─────────────────────────────────────────────────────┐ > │FIXME │ > ├─────────────────────────────────────────────────────┤ > │Was it intended that one can set up a different │ > │alternative signal stack in this scenario? (In pass‐ │ > │ing, if one does this, the sigaltstack(NULL, │ > │&old_ss) now returns old_ss.ss_flags==SS_AUTODISARM │ > │rather than old_ss.ss_flags==SS_DISABLE. The API │ > │design here seems confusing... │ > └─────────────────────────────────────────────────────┘ My memory may be wrong here, but I think setting up another alt stack was not supposed because the previous settings would be restored upon sighandler return. AFAIK I was trying to make up a proposal to get such attempts explicitly blocked rather than silently ignored, but again the simplicity was chosen. > SS_AUTODISARM > The alternate signal stack has been marked to be > autodisarmed as described above. Initially this flag was supposed to be ORed with the old values. Your descrition is correct, but if more bit flags are added, this may became a problem, as you are always treating it as a separate value, not a bit flag.
[toc] | [prev] | [next] | [standalone]
| From | "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> |
|---|---|
| Date | 2017-05-23 12:40 +0200 |
| Message-ID | <tKfom-1W6-23@gated-at.bofh.it> |
| In reply to | #1647493 |
Hello Stas,
On 05/23/2017 01:36 AM, Stas Sergeev wrote:
> 22.05.2017 23:38, Michael Kerrisk (man-pages) пишет:
>> Stas,
>>
>> I have attempted to document the SS_AUTODISARM feature that you added
>> in Linux 4.7.
>>
>> Could you please take a look at the SS_AUTODISARM pieces in the
>> sigaltstack() man page below? There is also one FIXME that I would
>> like help with.
>>
>> It seems to me that the API has become rather odd now. It is no longer
>> possible to simply check whether code is executing on an alternative
>> stack by using
>>
>> sigaltstack(NULL, &old_ss);
>> if (old_ss.ss_flags & SS_ONSTACK)
> You mean, if SS_AUTODISARM was previously used, right?
Yes, that's what I meant.
> Because I don't think we broke the existing code, or did we?
Probably not, but it seems to me that there is some small
possibility that library code that makes use of sigaltstack()
to test whether a signal is being handled on an alternate signal
stack, unaware that the main program employed SS_AUTODISARM,
could be confused/broken. I've no idea how likely this scenario
is though. (I imagine it's rather unlikely.)
> I can vaguely recall that I was submitting the patches
> that were returning SS_ONSTACK even when SS_AUTODISARM
> was used, but they were considered too complex.
> This is possible to implement, but the agreement was
> that it is not a big deal.
>
>> ss.ss_flags
>> This field contains either 0, or the following flag:
> Is this correct?
> AFAIK it can be SS_DISABLE too,
It's correct in context. Just above in the man page its says:
To establish a new alternate signal stack, the fields of this
structure are set as follows:
The discussion of SS_DISABLE to disable the SS is lower in the page.
> and posix seems to allow any
> other value for enable, which can be (on linux) SS_ONSTACK,
> not only 0.
Yes, long ago someone got confused, as I've noted in a recently added
BUGS section in the page:
BUGS
In the lead up to the development of the Linux 2.4 kernel,
someone got confused and allowed the kernel to accept
SS_ONSTACK in ss.ss_flags, which results behavior that is the
same as when ss_flags is 0. On other implementations, and
according to POSIX.1, SS_ONSTACK appears only as a reported
flag in old_ss.ss_flags. There is no need ever to specify this
flag in ss.ss_flags.
> And SS_AUTODISARM can be ORed with the value.
>
>> ┌─────────────────────────────────────────────────────┐
>> │FIXME │
>> ├─────────────────────────────────────────────────────┤
>> │Was it intended that one can set up a different │
>> │alternative signal stack in this scenario? (In pass‐ │
>> │ing, if one does this, the sigaltstack(NULL, │
>> │&old_ss) now returns old_ss.ss_flags==SS_AUTODISARM │
>> │rather than old_ss.ss_flags==SS_DISABLE. The API │
>> │design here seems confusing... │
>> └─────────────────────────────────────────────────────┘
> My memory may be wrong here, but I think setting
> up another alt stack was not supposed because the
> previous settings would be restored upon sighandler
> return. AFAIK I was trying to make up a proposal to
> get such attempts explicitly blocked rather than
> silently ignored, but again the simplicity was chosen.
So, I've done only limited experimentation here, but this is what
I see in one experiment:
[[
* Set up two handlers for SIGX and SIGY, both using SA_ONSTACK.
* Establish alternate SS (1) using SS_AUTODISARM
[SIGA is delivered]
* Handler for SIGA is called and handler is executed on alternate SS 1.
* The handler establishes a new alternate SS (2) with SS_AUTODISARM.
[SIGB is delivered]
* Handler for SIGB is called and handler is executed on alternate SS 2.
* Handler for SIGB returns
[SIGB is delivered]
* Handler for SIGB is called and handler is executed on alternate SS 2.
* Handler for SIGB returns
* Handler of SIGA returns
[SIGA is delivered]
* Handler for SIGA is called and handler is executed on alternate SS 1.
]]
Summary: setting up another alternate signal stack seems to "work".
API history is littered with stories where users found out that
something unforeseen "worked", and so they used it. The question
is: what can go wrong if people do try using this "feature"?
>> SS_AUTODISARM
>> The alternate signal stack has been marked to be
>> autodisarmed as described above.
> Initially this flag was supposed to be ORed with
> the old values. Your descrition is correct, but if
> more bit flags are added, this may became a
> problem, as you are always treating it as a separate
> value, not a bit flag.
Thanks for the confirmation.
At the end of this mail is a test program that I used to experiment
with this stuff. Here's a sample run that demonstrates the scenario
described above:
[[
$ ./t_sigaltstack_SS_AUTODISARM d 1
Autodisarm: YES
Try to establish new SS while on SS: YES
Initial SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
Top of standard stack is near 0x7ffc2b16382c
Signal stack allocated at 0x69a000-0x6ae000
About to change SS: sp = 0x69a000; size = 81920; flags = [ SS_AUTODISARM ]
SS after change: sp = 0x69a000; size = 81920; flags = [ SS_AUTODISARM ]
Send me a SIGQUIT (^\) or a SIGTSTP (^Z)
^\
Caught signal 3 (Quit)
Top of handler stack near 0x6adaa8
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
Now try establishing a new signal stack while still executing on this one (1)
Signal stack allocated at 0x1baf000-0x1bc3000
Modifying SS to: sp = 0x1baf000; size = 81920; flags = [ SS_AUTODISARM ]
SS after update: sp = 0x1baf000; size = 81920; flags = [ SS_AUTODISARM ]
sleep(2) before displaying SS (send a signal now, if desired)
^Z
Caught signal 20 (Stopped)
Top of handler stack near 0x1bc2aa8
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
sleep(2) before displaying SS (send a signal now, if desired)
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
sleep(2) before return from handler (send a signal now, if desired)
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
Returning from handler for signal 20
current SS: sp = 0x1baf000; size = 81920; flags = [ SS_AUTODISARM ]
sleep(2) before return from handler (send a signal now, if desired)
^Z
Caught signal 20 (Stopped)
Top of handler stack near 0x1bc2aa8
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
sleep(2) before displaying SS (send a signal now, if desired)
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
sleep(2) before return from handler (send a signal now, if desired)
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
Returning from handler for signal 20
current SS: sp = 0x1baf000; size = 81920; flags = [ SS_AUTODISARM ]
Returning from handler for signal 3
===============================
Back in main
current SS: sp = 0x69a000; size = 81920; flags = [ SS_AUTODISARM ]
^\
Caught signal 3 (Quit)
Top of handler stack near 0x6adaa8
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
sleep(2) before displaying SS (send a signal now, if desired)
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
sleep(2) before return from handler (send a signal now, if desired)
current SS: sp = (nil); size = 0; flags = [ SS_DISABLE ]
Returning from handler for signal 3
===============================
Back in main
current SS: sp = 0x69a000; size = 81920; flags = [ SS_AUTODISARM ]
^C
]]
Cheers,
Michael
/*#* t_sigaltstack_SS_AUTODISARM.c
COPYRIGHT-NOTICE
*/
#define _GNU_SOURCE
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define errExit(msg) do { fprintf(stderr, "[FAILED] "); \
perror(msg); exit(EXIT_FAILURE); \
} while (0)
#define errExitEN(en, msg) \
do { errno = en; perror(msg); \
exit(EXIT_FAILURE); } while (0)
#define SS_AUTODISARM (1U << 31)
static int tryNewStack = 0;
static void
showSS(char *prefix, stack_t * osp)
{
printf("%ssp = %p; size = %ld; flags = ", prefix,
osp->ss_sp, (long) osp->ss_size);
if (osp->ss_flags != 0) {
printf("[ ");
if (osp->ss_flags & SS_ONSTACK)
printf("SS_ONSTACK ");
if (osp->ss_flags & SS_DISABLE)
printf("SS_DISABLE ");
if (osp->ss_flags & SS_AUTODISARM)
printf("SS_AUTODISARM ");
printf("]");
}
printf("\n");
}
static void
showCurrentSS(char *msg)
{
stack_t os;
if (sigaltstack(NULL, &os) == -1)
errExit("sigaltstack");
showSS((msg != NULL) ? msg : "current SS: ", &os);
}
static const size_t stackSize = 10 * SIGSTKSZ;
static void
allocateSS(void **ss_sp)
{
int s;
void *p;
s = posix_memalign(ss_sp, 4096, stackSize);
if (s != 0)
errExitEN(s, "posix_memalign");
printf("Signal stack allocated at %p-%p\n",
*ss_sp, (char *) *ss_sp + stackSize);
for (s = 0; s < 256; s++)
posix_memalign(&p, 4096, stackSize);
}
static void
handler(int sig)
{
int x;
printf("\n\nCaught signal %d (%s)\n", sig, strsignal(sig));
printf("Top of handler stack near %10p\n", (void *) &x);
fflush(NULL);
showCurrentSS(NULL);
if (tryNewStack > 0) {
stack_t sigstack, os;
int s;
printf("\nNow try establishing a new signal stack "
"while still executing on this one (%d)\n", tryNewStack);
tryNewStack--;
allocateSS(&sigstack.ss_sp);
sigstack.ss_size = stackSize;
sigstack.ss_flags = SS_AUTODISARM;
showSS("Modifying SS to: ", &sigstack);
s = sigaltstack(&sigstack, NULL);
if (s == -1) {
fprintf(stderr, "[FAILED] ");
perror("sigaltstack");
}
if (sigaltstack(NULL, &os) == -1)
errExit("sigaltstack");
else
showCurrentSS("SS after update: ");
}
printf("\nsleep(2) before displaying SS "
"(send a signal now, if desired)\n");
sleep(2);
showCurrentSS(NULL);
printf("sleep(2) before return from handler"
"(send a signal now, if desired)\n");
sleep(2);
showCurrentSS(NULL);
printf("Returning from handler for signal %d\n", sig);
}
int
main(int argc, char *argv[])
{
stack_t sigstack;
struct sigaction sa;
int j;
int autodisarm;
autodisarm = 0;
if (argc > 1) {
if (strchr(argv[1], 'd') != NULL)
autodisarm = 1;
}
tryNewStack = (argc > 2) ? atoi(argv[2]) : 0;
printf("Autodisarm: %s\n",
autodisarm ? "YES" : "NO");
printf("Try to establish new SS while on SS: %s\n",
tryNewStack ? "YES" : "NO");
showCurrentSS("Initial SS: ");
printf("\nTop of standard stack is near %10p\n", (void *) &j);
/* Allocate alternate stack and inform kernel of its existence */
allocateSS(&sigstack.ss_sp);
sigstack.ss_size = stackSize;
sigstack.ss_flags = autodisarm ? SS_AUTODISARM : 0;
showSS("About to change SS: ", &sigstack);
if (sigaltstack(&sigstack, NULL) == -1)
errExit("sigaltstack");
showCurrentSS("SS after change: ");
/* Establish handlers for SIGQUIT and SIGTSTP */
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_ONSTACK | SA_NODEFER;
/* SA_NODEFER to allow experiments with interrupted handlers */
if (sigaction(SIGQUIT, &sa, NULL) == -1)
errExit("sigaction");
if (sigaction(SIGTSTP, &sa, NULL) == -1)
errExit("sigaction");
printf("\nSend me a SIGQUIT (^\\) or a SIGTSTP (^Z)\n");
for (;;) {
pause();
printf("===============================\n");
printf("\nBack in main\n");
showCurrentSS(NULL);
}
}
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
[toc] | [prev] | [next] | [standalone]
| From | Stas Sergeev <stsp@list.ru> |
|---|---|
| Date | 2017-05-23 13:10 +0200 |
| Message-ID | <tKfRn-2mS-11@gated-at.bofh.it> |
| In reply to | #1647932 |
23.05.2017 13:35, Michael Kerrisk (man-pages) пишет: > Hello Stas, Hi. :) >> Because I don't think we broke the existing code, or did we? > Probably not, but it seems to me that there is some small > possibility that library code that makes use of sigaltstack() > to test whether a signal is being handled on an alternate signal > stack, unaware that the main program employed SS_AUTODISARM, > could be confused/broken. I've no idea how likely this scenario > is though. (I imagine it's rather unlikely.) OK, so the original problem was that to get the more consistent checks, you'd need to keep alt stack still set up but disarmed, while inside the sighandler. If someone uses siglongjmp() at that point, then it will be left dangling. Likely there are ways around this, but nothing simple that I could think of. >> and posix seems to allow any >> other value for enable, which can be (on linux) SS_ONSTACK, >> not only 0. > Yes, long ago someone got confused, as I've noted in a recently added > BUGS section in the page: But my understanding differs. http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaltstack.html --- The /ss_flags/ member specifies the new stack state. If it is set to SS_DISABLE, the stack is disabled and /ss_sp/ and /ss_size/ are ignored. Otherwise, the stack shall be enabled --- As you can see, it doesn't say "SS_DISABLE or 0 are only possible values". It does not even mention 0 at all as being a possible or suggested value, it only uses it in an example. So what you call a confusion, looks valid to me, according to the above spec. Moreover, I use it in a real-life code, and it would be interesting to know how many other people do the same. If its just me, its one thing, but if it is a common practice, then perhaps this part of a man page should be reconsidered. >> And SS_AUTODISARM can be ORed with the value. >> >>> ┌─────────────────────────────────────────────────────┐ >>> │FIXME │ >>> ├─────────────────────────────────────────────────────┤ >>> │Was it intended that one can set up a different │ >>> │alternative signal stack in this scenario? (In pass‐ │ >>> │ing, if one does this, the sigaltstack(NULL, │ >>> │&old_ss) now returns old_ss.ss_flags==SS_AUTODISARM │ >>> │rather than old_ss.ss_flags==SS_DISABLE. The API │ >>> │design here seems confusing... │ >>> └─────────────────────────────────────────────────────┘ >> My memory may be wrong here, but I think setting >> up another alt stack was not supposed because the >> previous settings would be restored upon sighandler >> return. AFAIK I was trying to make up a proposal to >> get such attempts explicitly blocked rather than >> silently ignored, but again the simplicity was chosen. > So, I've done only limited experimentation here, but this is what > I see in one experiment: > > [[ > * Set up two handlers for SIGX and SIGY, both using SA_ONSTACK. > * Establish alternate SS (1) using SS_AUTODISARM > > [SIGA is delivered] > > * Handler for SIGA is called and handler is executed on alternate SS 1. > * The handler establishes a new alternate SS (2) with SS_AUTODISARM. > > [SIGB is delivered] > > * Handler for SIGB is called and handler is executed on alternate SS 2. > * Handler for SIGB returns > > [SIGB is delivered] > > * Handler for SIGB is called and handler is executed on alternate SS 2. > * Handler for SIGB returns > * Handler of SIGA returns At this point the alt stack is set back to SS1, undoing the effect of the just-done sigaltstack() call. > [SIGA is delivered] > > * Handler for SIGA is called and handler is executed on alternate SS 1. > ]] > > Summary: setting up another alternate signal stack seems to "work". Only if you deliver SIGB while still inside SIGA handler, which is a bit unusual. Certainly not worth calling this "works" IMHO. The fact that this will be undone at SIGA exit, is much more confusing to the user, so I'd say just don't do that. There IS a way to set a new alt stack while inside SIGA, and I use that in a real-life code. It is to write the new values to uc_stack. If you do this, the new settings will be activated at the return from SIGA handler. Maybe you can mention this possibility instead. > API history is littered with stories where users found out that > something unforeseen "worked", and so they used it. The question > is: what can go wrong if people do try using this "feature"? It will disappear at the exit from SIGA. To me this is "wrong enough" to not suggest doing so. >>> SS_AUTODISARM >>> The alternate signal stack has been marked to be >>> autodisarmed as described above. >> Initially this flag was supposed to be ORed with >> the old values. Your descrition is correct, but if >> more bit flags are added, this may became a >> problem, as you are always treating it as a separate >> value, not a bit flag. > Thanks for the confirmation. > > At the end of this mail is a test program that I used to experiment > with this stuff. Here's a sample run that demonstrates the scenario > described above: The kernel already has the sigaltstack test-case, so maybe you can add some checks to it from your test-case.
[toc] | [prev] | [next] | [standalone]
| From | "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> |
|---|---|
| Date | 2017-05-23 14:30 +0200 |
| Message-ID | <tKh6N-38u-17@gated-at.bofh.it> |
| In reply to | #1647940 |
Hello Stas,
On 23 May 2017 at 13:03, Stas Sergeev <stsp@list.ru> wrote:
> 23.05.2017 13:35, Michael Kerrisk (man-pages) пишет:
>>
>> Hello Stas,
>
> Hi. :)
>
>
>>> Because I don't think we broke the existing code, or did we?
>>
>> Probably not, but it seems to me that there is some small
>> possibility that library code that makes use of sigaltstack()
>> to test whether a signal is being handled on an alternate signal
>> stack, unaware that the main program employed SS_AUTODISARM,
>> could be confused/broken. I've no idea how likely this scenario
>> is though. (I imagine it's rather unlikely.)
>
> OK, so the original problem was that to get the
> more consistent checks, you'd need to keep alt
> stack still set up but disarmed, while inside the
> sighandler. If someone uses siglongjmp() at that
> point, then it will be left dangling. Likely there are
> ways around this, but nothing simple that I could
> think of.
Okay.
>>> and posix seems to allow any
>>> other value for enable, which can be (on linux) SS_ONSTACK,
>>> not only 0.
>>
>> Yes, long ago someone got confused, as I've noted in a recently added
>> BUGS section in the page:
>
> But my understanding differs.
> http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaltstack.html
> ---
> The /ss_flags/ member specifies the new stack state.
> If it is set to SS_DISABLE, the stack is disabled and /ss_sp/
> and /ss_size/ are ignored. Otherwise, the stack shall be enabled
> ---
>
> As you can see, it doesn't say "SS_DISABLE or 0 are
> only possible values". It does not even mention 0 at all
> as being a possible or suggested value, it only uses it in
> an example.
> So what you call a confusion, looks valid to me, according
> to the above spec.
I think this is a misreading of the spec. The spec is saying that
(ss_flags & SS_DISABLE) != 0
means disable the stack and
(ss_flags & SS_DISABLE) == 0
means disable the stack.
POSIX.1 make no statement about the use of SS_ONSTACK to enable the
stack. And as far as I know, no other implementation attaches meaning
to SS_ONSTACK when establishing a signal stack. Some systems' man
pages are loosely worded in the manner of POSIX, but others are quite
explicit, with Solaris 8 and Irix 6.5 containing text such as the
following:
If ss is not NULL, it points to a structure specifying the
alternate
signal stack that will take effect upon return from sigaltstack. [...]
The ss_flags field specifies the new stack state and may be set
to the following:
SS_DISABLE The stack is to be disabled and ss_sp and ss_size are
ignored. If SS_DISABLE is not set, the stack will be
enabled.
The strong implication there is that no value other than SS_DISABLE is
meaningful in ss.ss_flags. No other man page that I could find (and I
have quite a collection) suggested the (ss.ss_flags == SSONSTACK) is
meaningful.
> Moreover, I use it in a real-life code,
> and it would be interesting to know how many other people
> do the same. If its just me, its one thing, but if it is a common
> practice, then perhaps this part of a man page should be
> reconsidered.
By "use it" I presume you mean (ss.ss_flags == SS_ONSTACK).
Sure, you can use it on Linux, but it's a no-op there. And I just went
to check the Illumos source (which presumably mirrors its Solaris
ancestry), and there is this check in the sigaltstack()
implementation:
if (ss.ss_flags & ~SS_DISABLE)
return (set_errno(EINVAL));
And in the FreeBSD source we find similar:
if ((ss->ss_flags & ~SS_DISABLE) != 0)
return (EINVAL);
So, using SS_ONSTACK on Linux is a no-op that decreases code
portability. (And I am supposing that you use (ss.ss_flags ==
SS_ONSTACK) only because you've been misled into thinking its
legitimate from reading the kernel source.)
>>> And SS_AUTODISARM can be ORed with the value.
>>>
>>>> ┌─────────────────────────────────────────────────────┐
>>>> │FIXME │
>>>> ├─────────────────────────────────────────────────────┤
>>>> │Was it intended that one can set up a different │
>>>> │alternative signal stack in this scenario? (In pass‐ │
>>>> │ing, if one does this, the sigaltstack(NULL, │
>>>> │&old_ss) now returns old_ss.ss_flags==SS_AUTODISARM │
>>>> │rather than old_ss.ss_flags==SS_DISABLE. The API │
>>>> │design here seems confusing... │
>>>> └─────────────────────────────────────────────────────┘
>>>
>>> My memory may be wrong here, but I think setting
>>> up another alt stack was not supposed because the
>>> previous settings would be restored upon sighandler
>>> return. AFAIK I was trying to make up a proposal to
>>> get such attempts explicitly blocked rather than
>>> silently ignored, but again the simplicity was chosen.
>>
>> So, I've done only limited experimentation here, but this is what
>> I see in one experiment:
>>
>> [[
>> * Set up two handlers for SIGX and SIGY, both using SA_ONSTACK.
>> * Establish alternate SS (1) using SS_AUTODISARM
>> [SIGA is delivered]
>>
>> * Handler for SIGA is called and handler is executed on alternate SS 1.
>> * The handler establishes a new alternate SS (2) with SS_AUTODISARM.
>>
>> [SIGB is delivered]
>>
>> * Handler for SIGB is called and handler is executed on alternate SS 2.
>> * Handler for SIGB returns
>>
>> [SIGB is delivered]
>>
>> * Handler for SIGB is called and handler is executed on alternate SS 2.
>> * Handler for SIGB returns
>> * Handler of SIGA returns
>
> At this point the alt stack is set back to SS1,
> undoing the effect of the just-done sigaltstack()
> call.
(Yes.)
>
>> [SIGA is delivered]
>>
>> * Handler for SIGA is called and handler is executed on alternate SS 1.
>> ]]
>>
>> Summary: setting up another alternate signal stack seems to "work".
>
> Only if you deliver SIGB while still inside SIGA handler,
> which is a bit unusual. Certainly not worth calling this
> "works" IMHO. The fact that this will be undone at SIGA
> exit, is much more confusing to the user, so I'd say just
> don't do that.
I agree that it is an unusual scenario. But, user-space programmers
outnumber kernel developers 10000 to 1, and over time they will find
every possible way to creatively use an API if it "works for them".
[1]
> There IS a way to set a new alt stack while inside SIGA,
> and I use that in a real-life code. It is to write the new
> values to uc_stack. If you do this, the new settings will
> be activated at the return from SIGA handler. Maybe
> you can mention this possibility instead.
>
>> API history is littered with stories where users found out that
>> something unforeseen "worked", and so they used it. The question
>> is: what can go wrong if people do try using this "feature"?
>
> It will disappear at the exit from SIGA.
> To me this is "wrong enough" to not suggest doing so.
See my comment above. It's weird because it will disappear at exit
from SIGA, but not "wrong". And it would not surprise me if one day
someone decided they had a use for it. (And the "don't document it" or
even "warn people in the documentation that they should not do it"
will not stop some intrepid souls from tying it.)
>>>> SS_AUTODISARM
>>>> The alternate signal stack has been marked to be
>>>> autodisarmed as described above.
>>>
>>> Initially this flag was supposed to be ORed with
>>> the old values. Your descrition is correct, but if
>>> more bit flags are added, this may became a
>>> problem, as you are always treating it as a separate
>>> value, not a bit flag.
>>
>> Thanks for the confirmation.
>>
>> At the end of this mail is a test program that I used to experiment
>> with this stuff. Here's a sample run that demonstrates the scenario
>> described above:
>
> The kernel already has the sigaltstack test-case,
> so maybe you can add some checks to it from your
> test-case.
I must admit I'm still trying to grasp some details of what's
possible. What tests do you think could be usefully added?
Cheers,
Michael
[1] I mean, people are always aghast when I explain the existence of
libsigsegv and most people are surprised to learn that a file
permissions mask such as rw----r-- is actually used by some
applications to deny access to a group. I don't suppose either notion
was in the mind of the original UNIX kernel developers.
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
[toc] | [prev] | [next] | [standalone]
| From | Stas Sergeev <stsp@list.ru> |
|---|---|
| Date | 2017-05-24 01:10 +0200 |
| Message-ID | <tKr6a-1QN-11@gated-at.bofh.it> |
| In reply to | #1647983 |
23.05.2017 15:26, Michael Kerrisk (man-pages) пишет: >>>> and posix seems to allow any >>>> other value for enable, which can be (on linux) SS_ONSTACK, >>>> not only 0. >>> Yes, long ago someone got confused, as I've noted in a recently added >>> BUGS section in the page: >> But my understanding differs. >> http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaltstack.html >> --- >> The /ss_flags/ member specifies the new stack state. >> If it is set to SS_DISABLE, the stack is disabled and /ss_sp/ >> and /ss_size/ are ignored. Otherwise, the stack shall be enabled >> --- >> >> As you can see, it doesn't say "SS_DISABLE or 0 are >> only possible values". It does not even mention 0 at all >> as being a possible or suggested value, it only uses it in >> an example. >> So what you call a confusion, looks valid to me, according >> to the above spec. > I think this is a misreading of the spec. The spec is saying that > > (ss_flags & SS_DISABLE) != 0 > > means disable the stack and > > (ss_flags & SS_DISABLE) == 0 > > means disable the stack. You probably meant to say "enable" somewhere along the lines. Could you please point and cite the spec that says exactly this? > POSIX.1 make no statement about the use of SS_ONSTACK to enable the > stack. Unfortunately the spec mentions only "SS_DISABLE" and "otherwise". So the one can assume "SS_DISABLE+1", "SS_DISABLE-1" and "SS_DISABLE+100" to enable sas, but never 0. 0 can be assumed _only_ if you know exactly that flags is a bit-mask and SS_DISABLE is its (only possible) bit. You claim above that "spec is saying" it to be a bit-mask. Unfortunately I haven't seen such spec, and until that I assume SS_DISABLE is a value, not a bit of bitmask. And the value can itself be 0, so unless the spec is very clear on this (and it is likely not), I assume it is much safer to use SS_ONSTACK for the very simple fact: it is guaranteed to not be equal to SS_DISABLE, while 0, with my understanding of spec, is not guaranteed to be different from SS_DISABLE. > And as far as I know, no other implementation attaches meaning > to SS_ONSTACK when establishing a signal stack. Some systems' man > pages are loosely worded in the manner of POSIX, but others are quite > explicit, with Solaris 8 and Irix 6.5 containing text such as the > following: > > If ss is not NULL, it points to a structure specifying the > alternate > signal stack that will take effect upon return from sigaltstack. [...] > The ss_flags field specifies the new stack state and may be set > to the following: > > SS_DISABLE The stack is to be disabled and ss_sp and ss_size are > ignored. If SS_DISABLE is not set, the stack will be > enabled. > > The strong implication there is that no value other than SS_DISABLE is I guess you take "SS_DISABLE is not set" as a witness that it is a bitmask, but I wonder if that solaris-specific witness is strong enough to claim that the linux implementation is a confusion... > meaningful in ss.ss_flags. No other man page that I could find (and I > have quite a collection) suggested the (ss.ss_flags == SSONSTACK) is > meaningful. SS_ONSTACK is meaningful in a sense to always be != SS_DISABLE. > So, using SS_ONSTACK on Linux is a no-op that decreases code > portability. (And I am supposing that you use (ss.ss_flags == > SS_ONSTACK) only because you've been misled into thinking its > legitimate from reading the kernel source.) How about me supposing you use SS_DISABLE as a bitmask only because you took that view from the opensolaris and freebsd sources? :) Well, this is definitely under-specced, so we are unlikely to find any kind of "truth" here. But I am disappointed with the fact that the linux implementation was called a "confusion" based on a very small evidence from the solaris man page. IMHO to put such claims into a man page, the one had to open a defect report to posix, asking them to clarify first. And even if they confirm this view, the linux implementation should not be regarded as a confusion, but as a "consequence of the ambiguous wording in posix". >>> [SIGA is delivered] >>> >>> * Handler for SIGA is called and handler is executed on alternate SS 1. >>> ]] >>> >>> Summary: setting up another alternate signal stack seems to "work". >> Only if you deliver SIGB while still inside SIGA handler, >> which is a bit unusual. Certainly not worth calling this >> "works" IMHO. The fact that this will be undone at SIGA >> exit, is much more confusing to the user, so I'd say just >> don't do that. > I agree that it is an unusual scenario. But, user-space programmers > outnumber kernel developers 10000 to 1, and over time they will find > every possible way to creatively use an API if it "works for them". Another danger is someone trying to set up the same sas before exiting from the sighandler. If they set up same sas and get nested handler, the stack will be corrupted. This was not possible before, because without SS_AUTODISARM you'd get EPERM in such case. >>> API history is littered with stories where users found out that >>> something unforeseen "worked", and so they used it. The question >>> is: what can go wrong if people do try using this "feature"? >> It will disappear at the exit from SIGA. >> To me this is "wrong enough" to not suggest doing so. > See my comment above. It's weird because it will disappear at exit > from SIGA, but not "wrong". What do you mean? There was no any notion of the "sigaltstack scope", so with the existing semantic it is wrong, because currently sigaltstack has no scope and can't change at random moments. You can make it "not wrong" by inventing a new semantic with some notion of the "sigaltstack scope" though. Whether it worth the troubles, is what we will see. :) >> The kernel already has the sigaltstack test-case, >> so maybe you can add some checks to it from your >> test-case. > I must admit I'm still trying to grasp some details of what's > possible. What tests do you think could be usefully added? If you are going to add the scoped/nested sigaltstacks, then perhaps you should add the test that nesting works correctly (you have that already in your test-case), and maybe also the direct manipulations to uc_stack, as this is the only _reliable_ way to set the new sas inside the sighandler, that I can think of.
[toc] | [prev] | [next] | [standalone]
| From | "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com> |
|---|---|
| Date | 2017-05-24 13:20 +0200 |
| Message-ID | <tKCuC-1DS-13@gated-at.bofh.it> |
| In reply to | #1648996 |
Hello Stas, On 05/24/2017 01:01 AM, Stas Sergeev wrote: > 23.05.2017 15:26, Michael Kerrisk (man-pages) пишет: >>>>> and posix seems to allow any >>>>> other value for enable, which can be (on linux) SS_ONSTACK, >>>>> not only 0. >>>> Yes, long ago someone got confused, as I've noted in a recently added >>>> BUGS section in the page: >>> But my understanding differs. >>> http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaltstack.html >>> --- >>> The /ss_flags/ member specifies the new stack state. >>> If it is set to SS_DISABLE, the stack is disabled and /ss_sp/ >>> and /ss_size/ are ignored. Otherwise, the stack shall be enabled >>> --- >>> >>> As you can see, it doesn't say "SS_DISABLE or 0 are >>> only possible values". It does not even mention 0 at all >>> as being a possible or suggested value, it only uses it in >>> an example. I missed this point earlier, but I think that detail is also relevant. >>> So what you call a confusion, looks valid to me, according >>> to the above spec. >> I think this is a misreading of the spec. The spec is saying that >> >> (ss_flags & SS_DISABLE) != 0 >> >> means disable the stack and >> >> (ss_flags & SS_DISABLE) == 0 >> >> means disable the stack. > You probably meant to say "enable" somewhere along > the lines. Yes. > Could you please point and cite the spec that says > exactly this? I take your point: the text of the spec could be more precise. It does not provide a complete support for my assertion. But, I do think the interpretation I suggest is the more natural one, for many reasons: 1. The field is named '*flags', which commonly means a bit mask. 2. The example in that you mention that is in the spec is part of the spec. It illustrates the understanding of the developers of the spec about the interface they were specifying. 3. Various existing implementations treat the field as a bit mask for which there is only one valid bit (SS_DISABLE), doing tests of the form (ss.ss_flags & SS_DISABLE). 4. Some implementations (including *all* the ones that I looked at the source code for, that is Illumos, FreeBSD, OpenBSD) explicitly error if ss.ss_flags has bits other than SS_DISABLE set. 5. The man pages on Solaris and Irix explicitly note that SS_DISABLE is the only value (other than no value, i.e., 0) that may be placed in ss.ss_flags. No man page that I can find suggests the use of SS_ONSTACK in ss.ss_flags. 6. Before kernel 2.4 (Jan 2001), Linux also used to do 3 & 4! 7. Re points 3 and 4, POSIX/SUS normally specifies existing behavior. The SUS specification of sigaltstack() dates back at least to 1994 (SUSv1). This presumably means that the text came from the original POSIX.1-1990. The SUSv1 spec includes the example code snippet. 8. The standard explicitly mentions that SS_ONSTACK may be returned in old_ss.ss_flags, but makes no mention of the use of SS_ONSTACK in ss.ss_flags. That fact should, IMO, be taken as a strong hint that the standard developers did not believe that SS_ONSTACK was to be used with ss.ss_flags. On top of the above (to repeat what I already said earlier): * SS_ONSTACK in ss.ss_flags is a no-op on Linux. * SS_ONSTACK in ss.ss_flags in flags explicitly errors on various implementations (see points 4 and 6 above). >> POSIX.1 make no statement about the use of SS_ONSTACK to enable the >> stack. > Unfortunately the spec mentions only "SS_DISABLE" > and "otherwise". So the one can assume "SS_DISABLE+1", > "SS_DISABLE-1" and "SS_DISABLE+100" to enable sas, > but never 0. That's a possible reading of the standard, but not a natural one I would say, given the points above. > 0 can be assumed _only_ if you know exactly that > flags is a bit-mask and SS_DISABLE is its (only possible) > bit. You claim above that "spec is saying" it to be a bit-mask. > Unfortunately I haven't seen such spec, and until that > I assume SS_DISABLE is a value, not a bit of bitmask. > And the value can itself be 0, so unless the spec is very > clear on this (and it is likely not), I assume it is much > safer to use SS_ONSTACK for the very simple fact: it is > guaranteed to not be equal to SS_DISABLE, while 0, That's my point. It is not safe: it breaks portability. > with my understanding of spec, is not guaranteed to > be different from SS_DISABLE. > >> And as far as I know, no other implementation attaches meaning >> to SS_ONSTACK when establishing a signal stack. Some systems' man >> pages are loosely worded in the manner of POSIX, but others are quite >> explicit, with Solaris 8 and Irix 6.5 containing text such as the >> following: >> >> If ss is not NULL, it points to a structure specifying the >> alternate >> signal stack that will take effect upon return from sigaltstack. [...] >> The ss_flags field specifies the new stack state and may be set >> to the following: >> >> SS_DISABLE The stack is to be disabled and ss_sp and ss_size are >> ignored. If SS_DISABLE is not set, the stack will be >> enabled. >> >> The strong implication there is that no value other than SS_DISABLE is > I guess you take "SS_DISABLE is not set" as a witness that > it is a bitmask, but I wonder if that solaris-specific witness > is strong enough to claim that the linux implementation is > a confusion... It's not just Solaris specific. By now we have Solaris (Illumos), FreeBSD, OpenBSD, and Irix. How many more do you need ? :-) >> meaningful in ss.ss_flags. No other man page that I could find (and I >> have quite a collection) suggested the (ss.ss_flags == SSONSTACK) is >> meaningful. > SS_ONSTACK is meaningful in a sense to always be != SS_DISABLE. > >> So, using SS_ONSTACK on Linux is a no-op that decreases code >> portability. (And I am supposing that you use (ss.ss_flags == >> SS_ONSTACK) only because you've been misled into thinking its >> legitimate from reading the kernel source.) > How about me supposing you use SS_DISABLE as a bitmask > only because you took that view from the opensolaris and > freebsd sources? :) Well, you could suppose that :-). But actually, it's from my reading of the standards 15+ years ago. (I only read the opensolkaris and FreeBSD source code yesterday.) > Well, this is definitely under-specced, so we are unlikely to > find any kind of "truth" here. But I am disappointed with the > fact that the linux implementation was called a "confusion" > based on a very small evidence from the solaris man page. Solaris (Illumos), FreeBSD, OpenBSD, Irix... > IMHO to put such claims into a man page, the one had to > open a defect report to posix, asking them to clarify first. > And even if they confirm this view, the linux implementation > should not be regarded as a confusion, but as a "consequence > of the ambiguous wording in posix". One could do this I suppose, but I read POSIX differently from you and, more importantly, SS_ONSTACK breaks portability on numerous other systems and is a no-op on Linux. So, the Linux man page really should warn against its use in the strongest terms. >>>> [SIGA is delivered] >>>> >>>> * Handler for SIGA is called and handler is executed on alternate SS 1. >>>> ]] >>>> >>>> Summary: setting up another alternate signal stack seems to "work". >>> Only if you deliver SIGB while still inside SIGA handler, >>> which is a bit unusual. Certainly not worth calling this >>> "works" IMHO. The fact that this will be undone at SIGA >>> exit, is much more confusing to the user, so I'd say just >>> don't do that. >> I agree that it is an unusual scenario. But, user-space programmers >> outnumber kernel developers 10000 to 1, and over time they will find >> every possible way to creatively use an API if it "works for them". > Another danger is someone trying to set up the > same sas before exiting from the sighandler. If > they set up same sas and get nested handler, the > stack will be corrupted. This was not possible before, > because without SS_AUTODISARM you'd get EPERM > in such case. > >>>> API history is littered with stories where users found out that >>>> something unforeseen "worked", and so they used it. The question >>>> is: what can go wrong if people do try using this "feature"? >>> It will disappear at the exit from SIGA. >>> To me this is "wrong enough" to not suggest doing so. >> See my comment above. It's weird because it will disappear at exit >> from SIGA, but not "wrong". > What do you mean? > There was no any notion of the "sigaltstack scope", > so with the existing semantic it is wrong, because > currently sigaltstack has no scope and can't change I'm not sure what you mean by "currently" here. I'm pointing out that whereas before one could not change the signal stack while executing a handler that is using a signal stack, now it seems to be possible. But, it's not random: the programmer must explicitly make this happen (and be lucky in the timing of signals). > at random moments. You can make it "not wrong" > by inventing a new semantic with some notion of > the "sigaltstack scope" though. Whether it worth the > troubles, is what we will see. :) I don't think I'm inventing a new semantic. I think you already did that :-). The question is what we should say about it in the man page. I don't think being silent on this detail is the way to go. Perhaps noting a few details and warning the reader strongly against relying on this "feature" in any way is appropriate? >>> The kernel already has the sigaltstack test-case, >>> so maybe you can add some checks to it from your >>> test-case. >> I must admit I'm still trying to grasp some details of what's >> possible. What tests do you think could be usefully added? > If you are going to add the scoped/nested sigaltstacks, > then perhaps you should add the test that nesting works > correctly (you have that already in your test-case), and > maybe also the direct manipulations to uc_stack, as this > is the only _reliable_ way to set the new sas inside the > sighandler, that I can think of. See above. I'm not sure that we want to specify things to this level. But my point is that in the lack of any text in the man page on the topic, some user-space programmers will discover the feature and perhaps try to use it. The question is what the man page should say to those programmers. Do you see what I mean? Cheers, Michael -- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
[toc] | [prev] | [next] | [standalone]
| From | Stas Sergeev <stsp@list.ru> |
|---|---|
| Date | 2017-05-24 22:20 +0200 |
| Message-ID | <tKKVc-6Ww-27@gated-at.bofh.it> |
| In reply to | #1649481 |
Hello, 24.05.2017 14:09, Michael Kerrisk (man-pages) пишет: >> Could you please point and cite the spec that says >> exactly this? > I take your point: the text of the spec could be more precise. It > does not provide a complete support for my assertion. > > But, I do think the interpretation I suggest is the more natural one, > for many reasons: Note: below I am not arguing to whether it is good or bad to use SS_ONSTACK. This question is closed as soon as you pointed to EINVAL in other OSes (it doesn't make it bad immediately, but at least the outcome of its usage is now pretty clear for me). What I still want to point out is the fact that the implementation in linux was very unlikely caused by a confusion. It was the decision made in agreement with the most straight-forward reading of the posix spec, just maybe without knowing about this EINVAL problem. And it can't create a compatibility problem by itself because no one have explicitly promoted its use: 0 is still accepted. Why it could create a compatibility problem is only because people suddenly started to use it, and for the very simple reason (judging by myself): I was absolutely confused with this '0' in the example, and after many attempts to find even a slightest hint in the same doc why it is safe (why SS_DISABLE can't be 0), I resorted to looking into the kernel and the code of other projects. And SS_ONSTACK looked like a perfectly valid solution, fully agreeing with the text (i.e. SS_ONSTACK != SS_DISABLE). So what really creates a compatibility problem here, is only a misleading text (or a misleading implementation of it in other OSes). And as such, stating that "someone was confused" looks more like an unjustified insult to me. :) > 1. The field is named '*flags', which commonly means a bit mask. Indeed, but the value suggests otherwise. The name for a flag could be "SS_DISABLED" (with D at the end), while "SS_DISABLE" suggests an action. And indeed, it doesn't change a property of a performing action the way SS_AUTODISARM does. Instead it changes the action itself: the sas get cleared instead of being set, and all the other arguments are ignored. Eg I would be very surprised seeing the "MAP_UNMAP" flag to mmap() that turns it into munmap(). This more resembles the "action" argument of the sigprocmask() call. > 2. The example in that you mention that is in the spec is part of > the spec. It illustrates the understanding of the developers > of the spec about the interface they were specifying. > 3. Various existing implementations treat the field as a bit mask > for which there is only one valid bit (SS_DISABLE), doing > tests of the form (ss.ss_flags & SS_DISABLE). > 4. Some implementations (including *all* the ones that I looked at > the source code for, that is Illumos, FreeBSD, OpenBSD) > explicitly error if ss.ss_flags has bits other than SS_DISABLE set. Well, yes, those are the practical arguments that can't be ignored... Of course the one can try to submit the patch to these projects that nullifies this argument. :) > 6. Before kernel 2.4 (Jan 2001), Linux also used to do 3 & 4! Is there a discussion about this change somewhere? > 8. The standard explicitly mentions that SS_ONSTACK may be returned > in old_ss.ss_flags, but makes no mention of the use of SS_ONSTACK > in ss.ss_flags. That fact should, IMO, be taken as a strong hint > that the standard developers did not believe that SS_ONSTACK was > to be used with ss.ss_flags. But this doesn't matter as they "seemingly" allow any other value than SS_DISABLE, and this one is the most reasonable value of all (unless you know this is a bitmask, of course). So to make it clear: I am not arguing to what is better or more portable. I am just not satisfied with the statement that whoever implemented it that way (and whoever uses it, too, obviously), was confused or read the standard badly. It is not the case. Also I don't agree that this implementation can create any (portability or any other) kind of problem: it still accepts 0, and its author didn't advice anyone to use SS_ONSTACK. So in my eyes the implementation is perfectly valid, no ifs no buts. :) Man page can warn people to not use SS_ONSTACK, but it shouldn't blame the author of the kernel code in question IMHO. >>>>> API history is littered with stories where users found out that >>>>> something unforeseen "worked", and so they used it. The question >>>>> is: what can go wrong if people do try using this "feature"? >>>> It will disappear at the exit from SIGA. >>>> To me this is "wrong enough" to not suggest doing so. >>> See my comment above. It's weird because it will disappear at exit >>> from SIGA, but not "wrong". >> What do you mean? >> There was no any notion of the "sigaltstack scope", >> so with the existing semantic it is wrong, because >> currently sigaltstack has no scope and can't change > I'm not sure what you mean by "currently" here. I'm pointing > out that whereas before one could not change the signal stack > while executing a handler that is using a signal stack, now it > seems to be possible. But, it's not random: the programmer must > explicitly make this happen (and be lucky in the timing of signals). By "random points" I meant that sas swaps back to the previous one on a sighandler return. This sighandler return is just a random point for anyone who assumes the global scope of the sas. And the scope of sas was always global, so from that POV it doesn't work reliably. If you invent some notion of the scoped sigaltstacks, then you will turn that into a working functionality with new semantic. But I don't think you can call this "working" without first inventing an adequate semantic for it. >> at random moments. You can make it "not wrong" >> by inventing a new semantic with some notion of >> the "sigaltstack scope" though. Whether it worth the >> troubles, is what we will see. :) > I don't think I'm inventing a new semantic. I think you already > did that :-). The question is what we should say about it in the > man page. I don't think being silent on this detail is the way to > go. Perhaps noting a few details and warning the reader strongly > against relying on this "feature" in any way is appropriate? This is entirely up to you. My point is just that it is not a "few details", but really a new semantic with a notion of a sas's scope. I.e. when the control goes out of current scope (sighandler return), sas reverts to the one of the parent scope. Since this was not envisioned and is unlikely needed to anyone, I was just suggesting to not do this, but if you want to spec this all - why not. :) >>>> The kernel already has the sigaltstack test-case, >>>> so maybe you can add some checks to it from your >>>> test-case. >>> I must admit I'm still trying to grasp some details of what's >>> possible. What tests do you think could be usefully added? >> If you are going to add the scoped/nested sigaltstacks, >> then perhaps you should add the test that nesting works >> correctly (you have that already in your test-case), and >> maybe also the direct manipulations to uc_stack, as this >> is the only _reliable_ way to set the new sas inside the >> sighandler, that I can think of. > See above. I'm not sure that we want to specify things to this > level. But my point is that in the lack of any text in the man > page on the topic, some user-space programmers will discover the > feature and perhaps try to use it. The question is what the man > page should say to those programmers. Do you see what I mean? Yes, but I don't see what the man page should say to those programmers. :) Or if I do, the description would became too lengthy and complex.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web