After Segfault: Is there a way, to check if pointer is still valid?

拜拜、爱过 提交于 2019-12-31 07:05:08

问题


I plan to create a logging/tracing mechanism, which writes the address (const char*) of string literals to a ring-buffer. These strings are in the read-only data-segment and are created by the preprocessor with __function__ or __file__.

The Question: Is it possible, to analyze this ring-buffer content after a Segfault, if all pointers are valid? With "valid" I mean that they point to a mapped memory area and dereferencing won't cause a segmentation fault.

I'm working with Linux 2.6.3x and GCC 4.4.x.

Best regards,

Charly


回答1:


Of course if the stack or other memory that you rely upon has been corrupted then there could be problems, but that is true for any code.

Assuming that that there is no problem with the stack or other memory that you rely upon, and assuming that you do not call any functions like malloc() that are not async-signal safe, and assuming that you do not attempt to return from your signal handler, then there should be no problem reading or writing your buffer from within your signal handler.

If you are trying to test whether a particular address is valid, you could use a system call such as mincore() and check for an error result.




回答2:


I think the approach you are looking for is to handle a SIGSEGV signal via sigaction.

void handler(int, siginfo_t *info, ucontext_t *uap)
{
   /* Peek at parameters here...  I'm not sure exactly what you want to do. */
}

/* Set up the signal handler... */

struct sigaction sa, old_sa;
memset(&sa, 0 sizeof(sa));

sa.sa_sigaction = handler;
sa.sa_flags = SA_SIGINFO;

if (sigaction(SIGSEGV, &sa, &old_sa))
{
   /* TODO: handle error */
}

Note however that catching SIGSEGV on your own process is kind of weird. The process is likely in a bad state that can't be recovered from. The actions you'll be able to do in response to it may be limited, and it's most likely the process being killed is a good thing.

If you want it to be a bit more stable, there is the sigaltstack call which lets you specify an alternate stack buffer, so that if you've completely hosed your stack you can still handle SIGSEGV. To use this you need to set SA_ONSTACK in sa.sa_flags above.

If you want to respond to SEGV from the safety of another process (thereby isolating yourself from the poorly behaving segfaulting code and making it so that you won't crash while inspecting it), you can use ptrace. This interface is complex, has many non-portable parts, and is mainly used to write debuggers. But you can do great things with it, like read and write the process's memory and registers, and alter its execution.




回答3:


The usual way to check if dereferencing a memory region will cause a segfault is to use read() or write(). Eg to check if the first 128 bytes pointed to by ptr are safely readable:

int fd[2];
if (pipe(fd) >= 0) {
    if (write(fd[1], ptr, 128) > 0)
        /* OK */
    else
        /* not OK */
    close(fd[0]);
    close(fd[1]);
}

(write() will return EFAULT rather than raising a signal if the region isn't readable).

If you want to test more than PIPE_BUF bytes at a time, you'll need to read and discard from the reading side of the pipe.




回答4:


Once you've received a segfault, all bets are off. The pointers may be valid or they may have been corrupted. You just don't know. You may be able to compare them with valid values or the pointer to the ring buffer itself may have been corrupted. In which case, you'll probably get garbage.



来源:https://stackoverflow.com/questions/4401193/after-segfault-is-there-a-way-to-check-if-pointer-is-still-valid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!