When I try to do the command "/bin/kill -11 0" on bash, tcsh or zsh, it doesn't segfault but when I try to do it in mine, it does.
So I must have something I didn't handle.
Do you know what it can be ?
Thanks.
Your program doesn't actually segfault when it sends itself signal 11.
If the execution of a programs results in a "segment fault" (that is, the program performs an illegal memory reference), then the operating system sends the program SIGSEGV (signal 11 on Linux). The program cannot distinguish between a SIGSEGV sent by the operating system as the result of a program fault and a SIGSEGV sent by a call to raise or kill, possibly from another process, so it will respond as though there had been a real program error.
If you want to protect your shell from signals sent to pid 0 from a child process, you need to make sure that your child processes are in a different process group by calling setpgid in the child after the fork.
By default, a program is terminated by SIGSEGV. By default, the shell which invoked the program will then report that the program was terminated by SIGSEGV. This is popularly known as "segfaulting", but as indicated above, it might not have been the result of a real program fault.
If you want your program to do something else, you have to catch signal SIGSEGV with a signal handler; for example, if some cleanup needs to be done before the program terminates. Most shells (and databases) do that, but it is rarely necessary in user code.
Note: Signal 11 is SIGSEGV on Linux, but there is no guarantee that SIGSEGV will be signal 11 on a different OS (or even in some future version of Linux). You should always use the name of the signal rather than the number.
Related
I've recently had a problem with signals. I'd like to write a program in C which would print anything after a signal is sent to the process. For example: If I send SIGTERM to my process (which is simply running program), I want the program to print out for example, "killing the process denied" instead of killing the process. So how to do that? How to force process to catch and change the meaning of such signal. Also I have a question if there is any possibility to kill the init process (I know it's kind of a stupid question, but I was wondering how linux deals with such a signal, and how would it technically look if I type: sudo kill -9 1.
Don't use the signal handler to print. You can set a variable of type volatile sig_atomic_t instead, and have your main thread check this (see this example).
When your main thread has nothing else to do (which should be most of the time), let it block on a blocking function call (e.g. sleep()) that will wake up immediately when the signal is received (and set errno to EINTR).
C++ gotcha: Unlike the C sleep() function, std::this_thread::sleep_for() (in recent versions of glibc) does not wake up when a signal is received.
Regarding if it's possible to kill pid 1, see this question. The answer seems to be no, but I remember that Linux got very grumpy once I booted with init=/bin/bash and later exited this shell – had to hard reboot.
If you're looking for trouble, better kill pid -1.
Background: I'm fuzzing a long-lived process with afl-fuzz by passing to it the filename to process from a stub that afl-fuzz runs for each sample.
When the long-lived process crashes via SIGSEGV, I want the stub to also generate a SIGSEGV, so that afl-fuzz will mark the sample as interesting.
Will calling kill(stub_pid, SIGSEGV) from the long-lived process's SIGSEGV handler work ?
Will calling kill(stub_pid, SIGSEGV) from the long-lived process's SIGSEGV handler work ?
If a process ends up in a SIGSEGV-handler something very bad happened, which might include a completely destroyed stack and/or memory management.
It is not a good idea to rely on anything any more at this point, but just that the process goes down.
Trying to invoke any functionally beyond this point is likely to fail, that is unreliable.
A much safer approach to this would be to have the calling process monitor its child, and if the child happens to terminated unexpected (typically via SIGSEGV) start the appropriate actions.
Have a look at signal handling inside shell scripts (seach-key: "trap"), as such a script might be the parent to the process you want to monitor.
not recommended to do this through SIGSEGV but you can do this if you have proper permission.
Instead of wondering how to cause a segmentation fault in your program so that AFL would notice something odd, just call abort(). SIGABRT is caught by AFL as well and is much easier to trigger.
When I was googling my gdb and sigwait issue, I found this kernel bug thread
GDB is not trapping SIGINT. Ctrl+C terminates program when should break gdb.
Quote:
gdb puts the debugged process in its own pgrp and sets the terminal to that pgrp.
When you hit C-c, the signal goes to the current pgrp, i.e. to the debugged process and not to gdb. When a signal is delivered, ptrace will intercept it and let gdb decide what to do before it actually reaches the debugged process.
However, your program uses sigwait and so the signal is never actually delivered. Instead, you dequeue it via sigwait without going through actual signal delivery. ptrace only reports a signal that is about to be delivered. When you use sigwait, technically the signal is blocked the whole time and never delivered as such.
This comment got me more curious about how signal and GDB actually works,
1) What is the difference between "signal delivered" and "signal queued"?
2) How does GDB trap signals while the signal is sent to the debugged process?
Thanks,
First of all, I do know that there was a similar question here in the past.
But that question wasn't answered properly. Instead, it diverted into suggestion what to do to catch signals.
So just to clarify: I've done whatever needs to be done to handle signals.
I have an application that forks a daemon that monitors the main process through pipe.
If a main process crashes (e.g. segmentation fault), it has a signal handler that writes all the required info to pipe and aborts.
The goal is to have as much info as possible when something bad happens to the application, w/o messing with "normal" operation, such as SIGHUP, SIGUSR1, etc.
So my question is: which signals should I catch?
I mean signals that w/o me catching them would cause application to abort anyway.
So far I've come up with the following list:
SIGINT (^C, user-initiated, but still good to know)
SIGTERM (kill <pid> from shell or, AFAIK, can be result of OutOfMemory)
SIGSEGV
SIGILL
SIGFPE
SIGBUS
SIGQUIT
Does anybody know if I miss something? kill -l has lots of them... :)
I'm looking at my copy of advanced programming the unix environment (Stevens). According to the table in the section on signals, the following POSIX signals will by default terminate the process, if you don't catch them. It wouldn't be unreasonable to monitor all of these that you don't use:
SIGABRT
SIGALRM
SIGFPE
SIGHUP
SIGILL
SIGINT
SIGKILL
SIGPIPE
SIGQUIT
SIGSEGV
SIGTERM
SIGUSR1
SIGUSR2
You can catch all of these except SIGKILL, but hopefully SIGKILL won't come up very often for you.
Note that your signal man page (man 7 signal) should give you the proper list for your system - this is the POSIX list, and may differ depending on your architecture.
You should not catch the signal and write the code to a pipe. This is both unnecessary and not failsafe.
Let me quote an answer from the question you linked to, to point out why it's not failsafe: "What makes you think that a SEGV hasn't already corrupted your program memory"
Now you may be wondering how to do it better, and why I've said it is "unnecessary".
The return code of the waitpid syscall can be checked using WIFSIGNALED() to determine whether the process was terminated normally or via a signal, and WTERMSIG() will return the signal number.
This is failsafe and it does not require a handler or a pipe. Plus, you don't need to worry what to catch, because it will report every signal that terminates your process.
It depends: whatever signal you like if that's useful to inform the user something bad just happened. However SIGKILL and SIGSTOP cannot be caught.
Trying to build a debugger in C for fuzzing.
Basically in linux, I just want to start a process via fork and then execve(), then monitor this process to see if it crashes after 1 second.
On linux, is this done via creating the process then monitoring the SIGNALs it generates for anything that looks like a crash? Or is it about monitoring the application and? I'm not sure.
Use the ptrace(2) system call:
While being traced, the child will stop each time a signal is
delivered, even if the signal is being ignored. (The exception is
SIGKILL, which has its usual effect.) The parent will be notified at
its next wait(2) and may inspect and modify the child process while it
is stopped. The parent then causes the child to continue, optionally
ignoring the delivered signal (or even delivering a different signal
instead).
The signals you should be interested in, regarding to the process having crashed are SIGSEGV (restricted memory access), SIGBUS (unaligned data access), SIGILL (illegal instruction), SIGFPE (illegal floating-point operation), etc.