gcc / Linux : hook exit() call to prevent exit from happening - c

I have a pretty unique case where I am calling a 3rd party library (which I cannot modify) from a higher-level C program.
This code has a clean-up routine that calls exit() - which terminates the whole application.
However, I do not want to terminate the whole application at this time, as there is still some work that must be done by the main application.
So to solve this, I tried to 'trick' this 3rd party library by temporarily 'aliasing' the exit() function call to a dummy function using dlsym - and then later restoring exit() to its normal state.
This solution almost works - using LD_PRELOAD to point to the dummy exit wrapper I can see this dummy exit function being called - however, imminently after this I get a segmentation fault when this function goes out of scope.
I suspect this has to do with the fact that gcc by default puts an attribute called noreturn on this function.
Is there a way to remove this noreturn attribite, or better still another way of preventing this 3rd party library from calling exit()?
Any and all suggestions would be most appreciated.

Ignoring the fact that this may be a bad idea and that this is an old question and it seams to be answered in the comments.
There is an alternative solution to this if using gcc on Linux (maybe other systems to, I wouldn't know).
/* compile with "gcc -Wl,-wrap,exit -o test wrap_exit.c" */
/* check exit status with "echo $?" */
#include <stdio.h>
#include <stdlib.h>
void __real_exit(int status);
void __wrap_exit(int status)
{
int stat = 2;
printf("trying to exit with status %d\n", status);
printf("now exiting for real with status %d\n", stat);
__real_exit(stat);
}
int main(void)
{
exit(1);
return 0;
}

Related

C: Terminate a called function that is stuck in infinite loop from main

Let's assume I've got the following main in a c file
int f();
int main(){
//terminate f() if in infinite loop
return f();
}
and then a separate c file that could potentially hold the following:
int f() {
for(;;) {}
return 0;
}
Is there any way to detect that the function f() is in an infinite loop and terminate it's execution from within the main function?
EDIT:
I need this functionality as I am writing a testbench where the function called could potentially have an infinite loop - that's what I am checking for in the end. Therefore, I cannot modify f() in anyway. I'm also in a Linux environment.
No, there is no way to definitively determine if a function contains an infinite loop.
However, we can make a few assumptions to detect a potential infinite loop and exit a program gracefully within the program (e.g. we don't have to press Ctrl+C). This method is common in several testing frameworks used in JS. Basically, we set some arbitrary time limit for a function to complete in. If the function does not complete within that time limit, we assume it will not complete and we throw an error.
In C/C++ you could implement this with pthreads if you're on a Unix system. In Windows, you would use windows.h. I only have experience with pthreads, so I'll show a simple example of how you might get this working using pthreads.
#include <pthread.h> // Load pthread
#include <signal.h> // If f() does not exit, we will need this library to send it a signal to kill itself.
#include <stdbool.h> // You could use an int or char.
#include <stddef.h> // Defines NULL
#include <unistd.h> // Defines sleep()
bool testComplete; // Has the test completed?
/**
* The function being tested.
*/
void f() {
while(true);
}
/**
* This method handles executing the test. This is the function pthread will
* use as its start routine. It takes no arguments and returns no results.
* The signature is required for pthread_create().
*/
void *runTest(void *ptr) {
testComplete = false;
f();
testComplete = true;
}
int main() {
pthread_t testThread;
pthread_create(&testThread, NULL, runTest, NULL); // Create and start the new thread. It will begin executing runTest() eventually.
sleep(5); // Give it 5 seconds to complete (this should be adjusted or could even be made dynamic).
if(testComplete) {
// Test completed successfully.
pthread_join(testThread, NULL);
} else {
// The test did not exit successfully within the time limit. Kill it and you'll probably what to provide some feedback here.
pthread_kill(testThread, SIGPIPE); // There are other signals, but this one cannot be ignored or caught.
}
}
To compile this, you would need to execute gcc your_filename.c -o output_filename -lpthread.
If you expect the program to run on both Unix and Windows systems, you may want to consider making some unified interface for accessing threads and then adapting the OS-specific interfaces to your interface. It will make things a little simpler, especially when expanding this library.
You could call f() in a different thread and have main time-out f() when it reaches a certain limit. However, I don't think this is practical and you should really work on solving the infinite loop first.
On a Posix system (Linux, MacOS) you can schedule an alarm in the future with setitimer() before calling the function. Signal SIGALRM will be delivered to the process after the specified delay. Make sure that your program has the signal handler, you should register it with sigaction() before starting the timer.
When the signal handler takes control after the signal is raised, you may get out if the offending loop with setjmp() and longjmp().
If you call f() the way you showed (from main) then at that point the main context is in f, not main and therefore you cannot "check f from main".
What you can try is calling f() from a separate thread and check whether that thread has finished within specified time limit. However I'm not sure about practicality of this. While I don't know what you really plan to do in that function, n some cases you may stop this function from executing at the point where it did soemthing that requires cleaning up. One example that comes to mind is it calling malloc but but being able to call free at the point where you interrupt it.
Honestly, if there's a certain requirement about the time in which given function has to finish, just put that check within the function itself and return false to indicate it didn't finish successfully.

how to call pkill in c program without using "system() library function"

In the below program, I've used system library function to execute "pkill" command. Is there any system call available for pkill(Because PID is unknown). I don't want to use "system" library function. Please let me know how to do it
#include <stdio.h>
int main()
{
char test[1024] = "pkill -15 radio";
system(test);
return 0;
}
The system call for sending signals to processes is kill; however, you need the process id for. If you intend to launch the program to be killed from within your application, too, use fork together with one of the exec-functions and you have it. Otherwise, you will most likely have to iterate over the /proc/* subdirectories.

Why does pthread_exit(0) hangs the program?

Running the following C code causes the program to hang, and does not respond to signals (including CTRL-C).
int main()
{
pthread_exit(0);
return 0;
}
Any idea why?
The behaviour is normal when other threads have been created and are running, but I would like to know if I always have to check that before using pthread_exit(0).
EDIT:
This is the complete code that hangs. However, I was building with glib (-lglib-2.0). Using simply cc -o foo foo.c works as expected.
Your entire use case is described in the notes of the pthread_exit man page.
In your case, as you correctly edited your OP, glib started another thread. You exited the main thread and the other thread kept running. You labeled this as a hang.
In general, if you want to exit the application in full, just use exit or return from main().
Only when you need additional magic (rarely) like detached threads, use pthread_exit() on the main thread.

OSX "Illegal instruction 4" with nested function

The goal here was to catch SIGINT to close the server socket on a little socket server. I've tried to use a nested functions to keep the code clean. But...
When I do Ctrl-C (SIGINT, right?), I get Illegal instruction: 4. After reading this post, I've tried adding -mmacosx-version-min=10.8 to the compile flags since I'm on 10.8. Same error when doing Ctrl-C.
Two questions here: Why do I get `Illegal instruction 4"? How can I close the server socket without using a global variable?
My software:
Mac OSX 10.8.4
GCC 4.2.1
Here's how I'm compiling:
gcc -fnested-functions main.c
Here's the code:
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void register_sigint_handler(int *serverSocket)
{
void sigint_handler(int signal) {
printf("Shutting down...\n");
printf("Server socket was %d\n", *serverSocket);
close(*serverSocket);
exit(0);
}
signal(SIGINT, &sigint_handler);
}
int main(void) {
int serverSocket = 0, guestSocket = 0;
register_sigint_handler(&serverSocket);
serverSocket = socket(PF_INET, SOCK_STREAM, 0);
while (1) {}
close(serverSocket);
return 0;
}
While I can't tell you specifically what happens, the gcc docs have a generalization:
If you try to call the nested function through its address after the
containing function exits, all hell breaks loose.
Passing the function pointer to signal() will do exactly that, call your local function after the containing function has exited. So you shouldn't pass a nested function pointer to signal()
You should probably just use a normal function for the handler, which sets a flag.
static volatile int do_exit;
void sigint_handler(int sig)
{
do_exit = 1;
}
In a server one usually have main loop of some sort, around e.g. select or poll, your main loop, the empty while loop can now become
while (!do_exit) {
pause();
}
(Note that sockets are automatically closed by the operating system when the process exits;)
"Don't do that, then."
GCC's nested-functions-in-C extension does not provide true closures. When you take the address of sigint_handler, a "trampoline" (a small piece of self-modifying code) is written to the stack; as soon as register_sigint_handler exits, the trampoline is destroyed; a subsequent attempt to invoke the trampoline (by the kernel, in order to dispatch the signal) causes undefined behavior.
Signal handlers are process-global by definition. Therefore, it is incorrect in principle to attempt to avoid using global variables in signal handlers. Imagine what you'd do to make this code cope with two server sockets: you can only have one SIGINT handler registered, so somehow it has to close both sockets.
All open file descriptors are automatically closed when your process terminates. Therefore, it is not necessary to close them by hand first. Furthermore, it is a breach of convention to exit successfully on ^C. If this program were being driven by a supervisory process, that process would want to know (via waitpid's status code) that it exited because of a SIGINT. Putting those two things together, you should not have this signal handler at all.
(That stops being true if you need to do something to your active sockets on exit. For instance, if you wanted to write something to every active client connection on exit, you'd want a signal handler. But at that point you want to have the signal handler alert the main event loop, and do the work there.)
(Consider using libevent for this sort of thing rather than doing all the low-level goo yourself.)

GCC how to block system calls within a program?

Does anyone tell me how to block some specific system calls within a program, please? I am building a system which takes a piece of C source code, compiles it with gcc and runs it. For security reasons, I need to prevent the compiled program from calling some system calls. Is there any way to do it, from the source code level (e.g. stripping the header files of gcc, detecting malicious external calls, ...) to the executable level?
Edited #1: Add details about malicious calls.
Edited #2: My system is a GNU/Linux one.
Edited #3:
I have tried some methods within a few days and here are the conclusions I've got so far:
Scanning the source code does not solve the main problem since one can always obsfucate his/her C source file quite well.
"Overriding C symbol" works well for libraries, but for system calls I have not achieved what I wanted. This idea is not dead, however, doing this would definitely cause me a lot of time hacking (gcc and/or ld).
Permission deescalation works like a charm. I could use fakeroot or a "guest" user to do it. This method is also the easiest to implement.
The other one is native client which I have not tried yet but I definitely would in near future due to the common between the project and my work.
As others have noted, it's impossible for a program to avoid making system calls, they permate the C library all over the place.
However you might be able to make some headway with careful use of the LD_PRELOAD mechanism, if your platform supports it (e.g. Linux): you write a shared library with the same symbol names as those in the C library, which are called instead of the intended libc functions. (For example, Electric Fence is built as a shared library on Debian-based systems and intercepts calls to malloc, free et al.)
I suspect you could use this mechanism to trap or argument-check calls to any libc functions you don't like, and perhaps to note those which you consider unconditionally safe. It might then be reasonable to scan the compiled executable for the code corresponding to INT 0x80 to trap out any attempts to make raw syscalls (0xcd 0x80 - though beware of false positives). However I have only give this a few moments of thought, I could easily have missed something or this might turn out to be impractical...
You could run the compiled program by forking it from a wrapper and use the Linux ptrace(2) facility to intercept and inspect all system calls invoked by the program.
The following example code shows a wrapper that runs the /usr/bin/w command, prints each system call invoked by the command, and terminates the command if it tries to invoke the write(2) system call.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <sys/reg.h>
#define BAD_SYSCALL __NR_write
int main(int argc, char *argv)
{
pid_t child;
int status, syscall_nr;
child = fork();
if (child == 0) {
/* In child. */
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/usr/bin/w", NULL, NULL);
// not reached
}
/* In parent. */
while (1) {
wait(&status);
/* Abort loop if child has exited. */
if (WIFEXITED(status) || WIFSIGNALED(status))
break;
/* Obtain syscall number from the child's process context. */
syscall_nr = ptrace(PTRACE_PEEKUSER, child, 4 * ORIG_EAX, NULL);
printf("Child wants to execute system call %d: ", syscall_nr);
if (syscall_nr != BAD_SYSCALL) {
/* Allow system call. */
printf("allowed.\n");
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
} else {
/* Terminate child. */
printf("not allowed. Terminating child.\n");
ptrace(PTRACE_KILL, child, NULL, NULL);
}
}
exit(EXIT_SUCCESS);
}
You can do much more powerful things using ptrace, such as inspect and change a process' address space (e.g., to obtain and modify the parameters passed to a system call).
A good introduction can be found in this Linux Journal Article and its follow-up.
You can't.
Even this program:
#include <stdio.h>
int main()
{
printf("Hello, World\n");
return 0;
}
makes at least one system call (to send the string "Hello, World\n" to standard out). System calls are the only way for a program to interact with the outside World. Use the operating system's security model for security.
Edited for this comment:
I meant not all system calls but malicious system calls, e.g. execv() could be used to execute a BASH script which wipes out my data on the disk.
Your operating system already includes mechanisms to stop that sort of thing happening. For instance, in order for a bash script to wipe out your data, the process must already have write access to that data. That means it must have been started by you or root. Your only real option is not to install untrustworthy software.
By the way, depending on your platform, execv is not necessarily a system call. On Linux, it's a C library wrapper for the real system call (execve).
Just to illustrate that this is not possible, the following program:
int main() {
return 0;
}
makes over 20 system calls as reported using strace. The calls include open (twice) which is one of the calls you seem to want to block.
Well, if you just want to block specific calls, why not just do a grep through the source code before attempting to compile it ? And reject programs which use the insecure system calls.
Some project have similar idea you can take a look at nacl: http://code.google.com/p/nativeclient/

Resources