SEH, access violation and stack guard page - c

I've posted a question about validating a pointer's accessibility. The conclusion was either to use IsBadReadPtr to check the pointer, or SEH to catch the exception (and preferably to use neither, and debug the application, but that's not the issue here).
IsBadReadPtr is said to be bad because, among other reasons, it would try to read the pointer, and would catch any exception. It might catch a stack guard page exception, and thus prevent it from reaching the memory manager, which should have enlarged the stack.
If I use SEH and catch only EXCEPTION_ ACCESS_VIOLATION exceptions, would this create the same problem?
Another thing: What are the implications of using SEH?
This article suggests that "the compiler can’t perform flow analysis in code protected by SEH". How about if I call a function inside __try block. Would the compiler not optimize the called function at all?

If I use SEH and catch only EXCEPTION_ ACCESS_VIOLATION exceptions, would this create the same problem?
I think it would. A workaround might be to probe the stack[s] of any thread[s] you know and care about, before you start calling IsBadReadPtr (by "probe the stack" I mean to deliberately touch every memory page in the stack, to ensure every page is pre-allocated).
Would the compiler not optimize the called function at all?
If the function is not inlined, I would expect the compiler to apply the usual optimizations (optimization of the function wouldn't be affected by where the function is called from).

Related

Safe usage of `setjmp` and `longjmp`

I know people always say don't use longjmp, it's evil, it's dangerous.
But I think it can be useful for exiting deep recursions/nested function calls.
Is a single longjmp faster than a lot of repeated checks and returns like if(returnVal != SUCCESS) return returnVal;?
As for safety, as long as dynamic memory and other resources are released properly, there shouldn't be a problem, right?
So far it seems using longjmp isn't difficult and it even makes my code terser. I'm tempted to use it a lot.
(IMHO in many cases there is no dynamic memory/resources allocated within a deep recursion in the first place. Deep function call seems more common for data parsing/manipulation/validation. Dynamic allocation often happens at a higher level, before invoking the function where setjmp appears.)
setjmp and longjmp can be seen as a poor man's exception mechanism. BTW, Ocaml exceptions are as quick as setjmp but have a much clearer semantics.
Of course a longjmp is much faster than repeatedly returning error codes in intermediate functions, since it pops up a perhaps significant call stack portion.
(I am implicitly focusing on Linux)
They are valid and useful as long as no resources are allocated between them, including:
heap memory (malloc)
fopen-ing FILE* handles
opening operating system file descriptors (e.g. for sockets)
other operating system resources, such as timers or signal handlers
getting some external resource managed by some server, e.g. X11 windows (hence using any widget toolkit like GTK), or database handle or connection...
etc...
The main issue is that that property of not leaking resources is a global whole-program property (or at least global to all functions possibly called between setjmp and longjmp), so it prohibits modular software development : any other colleague having to improve some code in any function between setjmp and longjmp has to be aware of that limitation and follow that discipline.
Hence, if you use setjmp document that very clearly.
BTW, if you only care about malloc, using systematically Boehm's conservative garbage collector would help a lot; you'll use GC_malloc instead of malloc everywhere and you won't care about free, and practically that is enough; then you can use setjmp without fears (since you could call GC_malloc between setjmp and longjmp).
(notice that the concepts and the terminology around garbage collector are quite related to exception handling and setjmp, but many people don't know them enough. Reading the Garbage Collection Handbook should be worthwhile)
Read also about RAII and learn about C++11 exceptions (and their relation to destructors). Learn a bit about continuations and CPS.
Read setjmp(3), longjmp(3) (and also about sigsetjmp, siglongjmp, and setcontext(3)) and be aware that the compiler has to know about setjmp
You should note that calling setjmp in some contexts is not guaranteed to be safe (for example, you can't portably store the return value of setjmp).
Also, if you want to access local variables after calling setjmp, in the same function, that could have been changed you should mark that variables as volatile.
Using setjmp and longjmp is also useful because if the recursion causes a Stack Overflow, you can recover with a longjmp from the signal handler (don't forget to set an alternate stack) and return an error instead. If you want to do that you should consider to use sigsetjmp and siglongjmp for preserving signal dispositions.

How does try ... catch ... [finally] work?

It's found in almost every language and I've used it most of time.
I don't know it's internal, and wonder how does it really works.
How does it work at native levels at runtime of any language ?
For ex: If a stackoverflow or dividebyzero occurs inside try, then how does catch prevents falling of program ?
The statement "at the native level at runtime of any language," is an oxymoron. All native parts of exception handling are platform, not language, dependent. Some parts of exception handling are even hardware dependent (Divide by zero is always a hardware exception, for instance.)
In the specific case of divide by zero on .NET, on Windows, on x86, it goes something like this:
Your application tries to divide by zero.
The CPU saves some application state and executes code located the "Divide Error" address in the trap table (which so happens to be the zeroth element of the trap table.)
The trap handler code (which is part of the Windows Kernel) triggers mechanisms to eventually (in the executive) raise an SEH exception for divide by zero which will be propagated into the Object Manager, then into the .NET runtime.
The .NET runtime code in mscoree.dll gets the divide by zero as an HRESULT COR_E_DIVIDEBYZERO from a COM object.
.NET converts the HRESULT into a System.DivideByZeroException.
Your code sees the exception as a glorified long jump to the "closest" enclosing catch block, or finally block.
You either handle the exception, or it gets propagated out of your code and then your application crashes.
In general, you can think of exceptions as long jumps that carry a pointer to some Thread-local state information (the exception). The target of the long jump is usually known at compile time.
Not every language has exception handling built in, either. C, for instance, does not have structured exception handling.
When an exception is thrown and control passes from a try block to a handler, the run time calls destructors for all automatic objects constructed since the beginning of the try block. This process is called stack unwinding.

Should my library handle SIGSEGV on bad pointer input?

I'm writing a small library that takes a FILE * pointer as input.
If I immediately check this FILE * pointer and find it leads to a segfault, is it more correct to handle the signal, set errno, and exit gracefully; or to do nothing and use the caller's installed signal handler, if he has one?
The prevailing wisdom seems to be "libraries should never cause a crash." But my thinking is that, since this particular signal is certainly the caller's fault, then I shouldn't attempt to hide that information from him. He may have his own handler installed to react to the problem in his own way. The same information CAN be retrieved with errno, but the default disposition for SIGSEGV was set for a good reason, and passing the signal up respects this philosophy by either forcing the caller to be handle his errors, or by crashing and protecting him from further damage.
Would you agree with this analysis, or do you see some compelling reason to handle SIGSEGV in this situation?
Taking over handlers is not library business, I'd say it's somewhat offensive of them unless explicitly asked for. To minimize crashes library may validate their input to some certain extent. Beyond that: garbage in — garbage out.
The prevailing wisdom seems to be "libraries should never cause a crash."
I don't know where you got that from - if they pass an invalid pointer, you should crash. Any library will.
I would consider it reasonable to check for the special case of a NULL pointer. But beyond that, if they pass junk, they violated the function's contract and they get a crash.
This is a subjective question, and possibly not fit for SO, but I will present my opinion:
Think about it this way: If you have a function that takes a nul-terminated char * string and is documented as such, and the caller passes a string without the nul terminator, should you catch the signal and slap the caller on the wrist? Or should you let it crash and make the bad programmer using your API fix his/her code?
If your code takes a FILE * pointer, and your documentation says "pass any open FILE *", and they pass a closed or invalidated FILE * object, they've broken the contract. Checking for this case would slow down the code of people who properly use your library to accommodate people who don't, whereas letting it crash will keep the code as fast as possible for the people who read the documentation and write good code.
Do you expect someone who passes an invalid FILE * pointer to check for and correctly handle an error? Or are they more likely to blindly carry on, causing another crash later, in which case handling this crash may just disguise the error?
Kernels shouldn't crash if you feed them a bad pointer, but libraries probably should. That doesn't mean you should do no error checking; a good program dies immediately in the face of unreasonably bad data. I'd much rather a library call bail with assert(f != NULL) than to just trundle on and eventually dereference the NULL pointer.
Sorry, but people who say a library should crash are just being lazy (perhaps in consideration time, as well as development efforts). Libraries are collections of functions. Library code should not "just crash" any more than other functions in your software should "just crash".
Granted, libraries may have some issues around how to pass errors across the API boundary, if multiple languages or (relatively) exotic language features like exceptions would normally be involved, but there's nothing TOO special about that. Really, it's just part of the burden of writing libraries, as opposed to in-application code.
Except where you really can't justify the overhead, every interface between systems should implement sanity checking, or better, design by contract, to prevent security issues, as well as bugs.
There are a number of ways to handle this, What you should probably do, in order of preference, is one of:
Use a language that supports exceptions (or better, design by contract) within libraries, and throw an exception on or allow the contract to fail.
Provide an error handling signal/slot or hook/callback mechanism, and call any registered handlers. Require that, when your library is initialised, at least one error handler is registered.
Support returning some error code in every function that could possibly fail, for any reason. But this is the old, relatively insane way of doing things from C (as opposed to C++) days.
Set some global "an error has occurred flag", and allow clearing that flag before calls. This is also old, and completely insane, mostly because it moves error status maintence burden to the caller, AND is unsafe when it comes to threading.

Switching stacks efficiently

Due to some reason, I switch the stack for calling some functions in my application. I use makecontext/getcontext/swapcontext for that purpose. However, I find it to be too slow.
I tried to use custom made code for that purpose, which saves the stack pointer and other registers and then assign the stack pointer the value of the new memory which I want to use as a stack. However, I keep getting stack smashing detected error.
Are there some special permissions set for the stack by the OS or else what is the matter here? How to circumvent the problem.
The excellent GNU Pth library makes heavy use of these techniques. It's very well documented, and determines the most efficient context switching mechanism at compile time. edit: at configure time actually.
The author's paper: rse-pmt.ps gives a technical account of user-space context switching and related issues - alternative signal stacks, etc.
You could look at other software doing the same dirty tricks as you do. In particular Chicken Scheme. You might perhaps consider using longjmp after manually doing dirty things on the target jmp_buf. Of course, none of this is portable.
But please explain more your overall goal. Your questions are generally too mysterious....
(and that is repulsive to some)
The makecontext()/getcontext()/setcontext()/swapcontext() are quite efficient as they merely save the current values of the processor registers. However, in Linux/GLIBC at least, setcontext() and getcontext() invoke the rt_sigprocmask() system call to save/restore the signal mask of the calling thread. This may be the reason why you face some performance issues as this triggers a context switch into the kernel.

Can function pointers be used to run "data"?

This is not something most people would probably use, but it just came to mind and was bugging me.
Is it possible to have some machine code in say, a c-string, and then cast its address to a function pointer and then use it to run that machine code?
In theory you can, per Carl Norum. This is called "self-modifying code."
In practice what will usually stop you is the operating system. Most of the major modern operating systems are designed to make a distinction between "readable", "readwriteable", and "executable" memory. When this kind of OS kernel loads a program, it puts the code into a special "executable" page which is marked read-only, so that a user application cannot modify it; at the same time, trying to GOTO an address that is not in an "executable" page will also cause a fault exception. This is for security purposes, because many kinds of malware and viruses and other hacks depend upon making the program jump into modified memory. For example, a hacker might feed an app data that causes some function to write malicious code into the stack, and then run it.
But at heart, what the operating system itself does to load a program is exactly what you describe -- it loads code into memory, flags the memory as executable, and jumps into it.
In the embedded hardware world, there may not be an OS to get in your way, and so some platforms use this pretty regularly. On the PlayStation 2 I used to do this all the time -- if there was some code that was specific to, say, the desert level, and used nowhere else, I wouldn't keep it in memory all the time -- instead I'd load it along with the desert level, and fix up my function pointers to the right executable. When the user left the level, I'd dump that code from memory, set all those function pointers to an exception handler, and load the code for the next level into the same space.
Yes, you can absolutely do that. There's nothing stopping you unless your system or compiler prevent it somehow (like you have a Harvard architecture, for example). Just make sure your 'data' is valid instructions before you jump, or you risk disaster.
It is not possible even to attempt doing something like this legally in C language, since there's no legal way to make a function pointer to point to "data". Function pointers in C language can only be initialized/assigned from other function pointers, even if you use an explicit conversion. If you violate this rule, the behavior is undefined.
It is also possible to initialize a function pointer from an integer (by using an explicit conversion) with implementation-defined results (as opposed to undefined results in other cases). However, an attempt to execute the "data" by making a call through a pointer obtained in such a way still leads to undefined behavior.
If you are willing to ignore the fact that the behavior is undefined, then the actual manifestations of that undefined behavior will look differently on different platforms. On some platform it might even appear to "work".
One could also imagine a superoptimzer doing this to test small assembler sequences against the specifications of the function it optimizes.

Resources