IsBadReadPtr analogue on Unix
Is there a function analogous to IsBadReadPtr in Unix? At least some functionalities of IsBadReadPtr?
I want to write a procedure which would react if something bad happens to a pr开发者_StackOverflowocess (like SIGSEGV
) and recover some information. But I want to check the pointers to make sure that the data is not corrupt and see if they can be accessed safely. Otherwise the crash handling procedure itself will crash, thus becoming useless.
Any suggestions?
The usual way to do this on POSIX systems is to use the write()
system call. It will return EFAULT
in errno
rather than raising a signal if the memory cannot be read:
int nullfd = open("/dev/random", O_WRONLY);
if (write(nullfd, pointer, size) < 0)
{
/* Not OK */
}
close(nullfd);
(/dev/random
is a good device to use for this on Linux, because it can be written by any user and will actually try to read the memory given. On OSes without /dev/random
or where it isn't writeable, try /dev/null
). Another alternative would be an anonymous pipe, but if you want to test a large region you'll need to regularly clear the reading end of the pipe.
How can you do it?
You try to do it and then handle the error.
To do this, first you set up a sigsetjmp and a SIGSEGV signal handler. Then attempt to use the pointer. If it was a bad pointer then the SIGSEGV handler is called and you can jump to safety and report the error to the user.
You can never tell "whether a pointer can be accessed safely", on Windows or on Unix. But for some similar information on some unix platforms, check out cat /proc/self/maps
.
I ran into the same issue trying to read a 'pixel' from a framebuffer while running Ubuntu from within a virtualbox. There seemed to be no secure way to check access without crashing or acutally hanging gdb. The suggestion made by StasM hinted me towards to following working 'local' solution using fork.
void *some_address;
int pid = fork();
if (pid== 0)
{
someaddress[0] = some_address[0];
_exit(123);
}
bool access_ok = true;
int status;
int result = waitpid(pid, &status, 0);
if (result == -1 || WIFEXITED(status) == 0 || WEXITSTATUS(status) != 123)
{
access_ok = false;
}
精彩评论