Messages in this thread | | | Date | Mon, 1 Mar 1999 16:14:18 +0000 (GMT) | From | Mark Hemment <> | Subject | Re: 2.2.1: memory corruption and SIGSEGV handlers. |
| |
Hi Tigran,
Had a quick look at this. A _possible_ reason for the problem is;
i) Page-fault to grow the stack (say the call to fprintf() generates this) ii) Size of stack has reached hard-limit, so calls force_signal(SIGSEGV, tsk) iii) Returning from the page-fault handler causes the signal to be delivered. iv) do_signal() sees a handler is installed and calls handle_signal(), which calls setup_frame(). v) setup_frame() calls get_sigframe() to find the address to build the frame at (the normal user-stack if altsigstack isn't being used). vi) access_ok() returns true as you're not running on an old i386, so only the address limit is checked. This doesn't seem to be a strong enough check. It is possible there is not enough distance between the top of stack and the hard stack size limit (ulimit) for a full frame. vii) If there isn't enough space, building up the stack frame causes a page-fault, which cannot grow the stack (as the limit has been reached).
Am I correct in my understanding at step vi)? If so the fix would be another, stronger check in setup_frame() and setup_rt_frame(). If there isn't enough distance, the handler should be removed before delivering the signal (SIGSEGV - ie. drop core).
Mark
On Mon, 1 Mar 1999, Tigran Aivazian wrote:
> Hi guys, > > Below is a simple program that does this: > > 1. Registers a handler for SIGSEGV using sigaction(2) with no special > flags. > > 2. Causes the first SIGSEGV to be sent by *(int *)0 = 0; > > 3. Inside the handler prints something and does *(int *)0 = 0; > > This results in a recursive invocation of the handler, which is > reasonable. > > However, there are two problems I personally see here: > > a) eventually, the program hangs (presumably when we run out of user > stack) > > b) if you, additionally do something like ulimit -sH 1 before running the > program, it causes some memory (page cache?) corruption (i.e. next time > you run gcc(1) to compile something you get Internal error: signal 11 > stuff). > > This is clearly wrong so someone should have a look at the different code > paths corresponding to signal delivery in the case of kill(2) and via GP > fault (trap handler). (i.e. if I replace *0 = 0 with kill(getpid(), > SIGSEGV) everything is ok). > > Regards, > ------ > Tigran A. Aivazian | http://www.sco.com > Escalations Research Group | tel: +44-(0)1923-813796 > Santa Cruz Operation Ltd | http://www.aivazian.demon.co.uk > > #include <stdio.h> > #include <signal.h> > #include <unistd.h> > > int sig = SIGSEGV; > > void gotsig(int signo) > { > int stack; > fprintf(stderr, "%d: signal%d (stack=%p) ", > getpid(), signo, &stack); > *(int *)0 = 0; > } > > int main(int argc, char *argv[]) > { > struct sigaction act; > act.sa_handler = gotsig; > sigemptyset(&act.sa_mask); > act.sa_flags = 0; > if ( -1 == sigaction(sig, &act, NULL)) { > perror("sigaction()"); > exit(1); > } > *(int *)0 = 0; > return 0; > } > > > - > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.rutgers.edu > Please read the FAQ at http://www.tux.org/lkml/
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |