invoking a segfault within a segfault handler - is this undefinedbehavior?

Discussion in 'C Programming' started by Andrey Vul, Jul 26, 2010.

  1. Andrey Vul

    Andrey Vul Guest

    In the following code, the dereferencing of NULL at line main+2
    triggers a segfault, which calls handl(SEGV). Is the behavior
    dereferencing of NULL in the SEGV handler undefined, implementation-
    dependent, or standardized?
    It looks like the OS doesn't want to tolerate double pagefaults or
    nested fatal signals, and simply kills the offending process, which
    lead me to reading ISO 9899:1999.
    I couldn't find anything to do with nested terminate-or-core signals
    in the spec. Could I get clarification on this?

    Note: raise(u) instead of dereferencing NULL did not cause a crash.

    code:

    #include <stdio.h>
    #include <signal.h>
    sig_atomic_t dep;
    void handl(int u) {
    dep++;
    write(1, &dep, sizeof dep);
    *((char *)0) = 0;
    }
    int main() {
    dep=0;
    signal(SIGSEGV, handl);
    *((char *)0) = 0;
    return 0;
    }
     
    Andrey Vul, Jul 26, 2010
    #1
    1. Advertising

  2. Andrey Vul

    Andrey Vul Guest

    Basically, I'm asking for clarification wrt 7.14.1.1.3, specifically
    for computational-exception within a computational-exception handler.
     
    Andrey Vul, Jul 26, 2010
    #2
    1. Advertising

  3. Re: invoking a segfault within a segfault handler - is this undefined behavior?

    Andrey Vul <> writes:

    > Basically, I'm asking for clarification wrt 7.14.1.1.3, specifically
    > for computational-exception within a computational-exception handler.


    I'll annotate the text as best I can:

    When a signal occurs and func points to a function,

    This is awkward wording but I think it is clear. It is describing what
    happens when a signal occurs after the signal's action has been set by
    calling signal with a function pointer argument.

    it is implementation-defined whether the equivalent of signal(sig,
    SIG_DFL); is executed or the implementation prevents some
    implementation-defined set of signals (at least including sig) from
    occurring until the current signal handling has completed;

    Implementation defined means that the implementation must document what
    choice it makes between some set of alternatives. So either:

    (a) the signal's action is reset to the default, or
    (b) some set of signals is blocked. This set must be specified by the
    documentation and is must include the signal being handled.

    Your implementation is clearly doing (a).

    in the case of SIGILL, the
    implementation may alternatively define that no action is taken.

    No relevant but clear enough, I think.

    Then the equivalent of (*func)(sig); is executed.

    So the above happens before the handler is called.

    If and when the function returns, if the value of sig is SIGFPE,
    SIGILL, SIGSEGV, or any other implementation-defined value
    corresponding to a computational exception, the behavior is undefined;
    otherwise the program will resume execution at the point it was
    interrupted.

    The behaviour is undefined when the function returns. You are handling
    SIGSEGV which is one of the named computational exceptions (the
    implementation can specify others).

    Does that help? It would help to know what you want to do and how
    portable you want it to be.

    --
    Ben.
     
    Ben Bacarisse, Jul 26, 2010
    #3
  4. Andrey Vul

    Andrey Vul Guest

    On Jul 26, 7:43 am, Ben Bacarisse <> wrote:
    > Andrey Vul <> writes:
    > > Basically, I'm asking for clarification wrt 7.14.1.1.3, specifically
    > > for computational-exception within a computational-exception handler.

    >
    > I'll annotate the text as best I can:
    >
    >   When a signal occurs and func points to a function,
    >
    > This is awkward wording but I think it is clear.  It is describing what
    > happens when a signal occurs after the signal's action has been set by
    > calling signal with a function pointer argument.
    >
    >   it is implementation-defined whether the equivalent of signal(sig,
    >   SIG_DFL); is executed or the implementation prevents some
    >   implementation-defined set of signals (at least including sig) from
    >   occurring until the current signal handling has completed;
    >
    > Implementation defined means that the implementation must document what
    > choice it makes between some set of alternatives.  So either:
    >
    > (a) the signal's action is reset to the default, or
    > (b) some set of signals is blocked.  This set must be specified by the
    > documentation and is must include the signal being handled.
    >
    > Your implementation is clearly doing (a).
    >
    >   in the case of SIGILL, the
    >   implementation may alternatively define that no action is taken.
    >
    > No relevant but clear enough, I think.
    >
    >   Then the equivalent of (*func)(sig); is executed.
    >
    > So the above happens before the handler is called.
    >
    >   If and when the function returns, if the value of sig is SIGFPE,
    >   SIGILL, SIGSEGV, or any other implementation-defined value
    >   corresponding to a computational exception, the behavior is undefined;
    >   otherwise the program will resume execution at the point it was
    >   interrupted.
    >


    > The behaviour is undefined when the function returns.  You are handling
    > SIGSEGV which is one of the named computational exceptions (the
    > implementation can specify others).
    >
    > Does that help?  It would help to know what you want to do and how
    > portable you want it to be.


    What I was trying to do was force /sbin/init to abnormally terminate,
    causing system lockup.
    I got it work work with a double segfault, but was asking if this
    method caused undefined behavior.
     
    Andrey Vul, Jul 26, 2010
    #4
  5. Re: invoking a segfault within a segfault handler - is this undefined behavior?

    Andrey Vul <> writes:
    <snip>
    > What I was trying to do was force /sbin/init to abnormally terminate,
    > causing system lockup.
    > I got it work work with a double segfault, but was asking if this
    > method caused undefined behavior.


    I don't think so, but it would have been simpler to call abort or _Exit,
    no? I'm not sure what you can and can't change in this scenario, but if
    you added the original seg faulting code rather than simple exploiting
    an existing seg fault, you could have just put an abort or _Exit call in
    the there instead. If you can't do that, abort or _Exit from the signal
    handler would have done, I think.

    --
    Ben.
     
    Ben Bacarisse, Jul 26, 2010
    #5
  6. Andrey Vul

    Andrey Vul Guest

    On Jul 26, 2:27 pm, Ben Bacarisse <> wrote:
    > Andrey Vul <> writes:
    >
    > <snip>
    >
    > > What I was trying to do was force /sbin/init to abnormally terminate,
    > > causing system lockup.
    > > I got it work work with a double segfault, but was asking if this
    > > method caused undefined behavior.

    >
    > I don't think so, but it would have been simpler to call abort or _Exit,
    > no?  I'm not sure what you can and can't change in this scenario, but if
    > you added the original seg faulting code rather than simple exploiting
    > an existing seg fault, you could have just put an abort or _Exit call in
    > the there instead.  If you can't do that, abort or _Exit from the signal
    > handler would have done, I think.
    >


    abort() in the signal handler only kills the program from infinite
    recursion, as init's signal handler traps SIGABRT.
    I could've simply added a segfault in the handler, and do a #kill -11
    1 , but making a runlevel that triggers a double segfault was more fun
    to do :)
    However, _Exit without forced crash would've saved a few lines of
    code. Let me try that after a reboot.
     
    Andrey Vul, Jul 26, 2010
    #6
  7. Andrey Vul

    Andrey Vul Guest

    On Jul 26, 3:25 pm, Andrey Vul <> wrote:
    > On Jul 26, 2:27 pm, Ben Bacarisse <> wrote:
    >
    >
    >
    > > Andrey Vul <> writes:

    >
    > > <snip>

    >
    > > > What I was trying to do was force /sbin/init to abnormally terminate,
    > > > causing system lockup.
    > > > I got it work work with a double segfault, but was asking if this
    > > > method caused undefined behavior.

    >
    > > I don't think so, but it would have been simpler to call abort or _Exit,
    > > no?  I'm not sure what you can and can't change in this scenario, but if
    > > you added the original seg faulting code rather than simple exploiting
    > > an existing seg fault, you could have just put an abort or _Exit call in
    > > the there instead.  If you can't do that, abort or _Exit from the signal
    > > handler would have done, I think.


    Methinks signal(SIGSEGV, SIG_DFL); raise(SIGSEGV) would be even
    simpler.
    After all, it'd be more subtle than _Exit(SIGSEGV).
     
    Andrey Vul, Jul 27, 2010
    #7
  8. Andrey Vul

    Nobody Guest

    Re: invoking a segfault within a segfault handler - is this undefined behavior?

    On Tue, 27 Jul 2010 00:49:53 -0700, Andrey Vul wrote:

    >> > > What I was trying to do was force /sbin/init to abnormally terminate,
    >> > > causing system lockup.


    > Methinks signal(SIGSEGV, SIG_DFL); raise(SIGSEGV) would be even
    > simpler.
    > After all, it'd be more subtle than _Exit(SIGSEGV).


    Note that Linux treats init specially; the kill(2) manpage says:

    NOTES
    The only signals that can be sent to process ID 1, the init process,
    are those for which init has explicitly installed signal handlers.
    This is done to assure the system is not brought down accidentally.
     
    Nobody, Jul 27, 2010
    #8
  9. Andrey Vul

    Richard Bos Guest

    Re: invoking a segfault within a segfault handler - is this undefined behavior?

    Andrey Vul <> wrote:

    > In the following code, the dereferencing of NULL at line main+2
    > triggers a segfault, which calls handl(SEGV). Is the behavior
    > dereferencing of NULL in the SEGV handler undefined, implementation-
    > dependent, or standardized?


    7.14.1.1#3:
    # When a signal occurs and func points to a function, it is
    # implementation-defined whether the equivalent of signal(sig, SIG_DFL);
    # is executed or the implementation prevents some implementation-defined
    # set of signals (at least including sig) from occurring until the
    # current signal handling has completed;

    IOW, it's Standardised that a programmer-defined signal handler can't
    raise _itself_ recursively[1]. Whether it can raise the default handler
    instead is implementation-defined.
    C89 has text that is similar enough to mean the same thing for your
    program.

    > #include <stdio.h>
    > #include <signal.h>
    > sig_atomic_t dep;
    > void handl(int u) {
    > dep++;
    > write(1, &dep, sizeof dep);
    > *((char *)0) = 0;
    > }
    > int main() {
    > dep=0;
    > signal(SIGSEGV, handl);
    > *((char *)0) = 0;
    > return 0;
    > }


    Richard

    [1] Not _strictly_ true; but true in this case. You might be able to do
    it (if the implementation allows you to) by setting handl() for two
    different signals, and then raising one of those in main(), and
    another in handl(). Of course, it's quite possible that the "set of
    signals" referred to in the quotation include, for your compiler,
    _both_ signals you set for handl()... but not required.
     
    Richard Bos, Jul 30, 2010
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    4
    Views:
    11,417
    bhakthi
    Mar 4, 2009
  2. shruds
    Replies:
    1
    Views:
    840
    John C. Bollinger
    Jan 27, 2006
  3. Spartanicus
    Replies:
    3
    Views:
    439
    Spartanicus
    Sep 30, 2005
  4. Fred
    Replies:
    4
    Views:
    291
    sumsin
    Jun 4, 2008
  5. John Henry

    Invoking CutePDF from within Python

    John Henry, Feb 12, 2009, in forum: Python
    Replies:
    6
    Views:
    1,147
    John Henry
    Feb 17, 2009
Loading...

Share This Page