System call interposition based security mechanism can constrain the behavior of application processes when they access system resources. Systems such as Janus and systrace implement the principle of "least privileges". In particular, they record the system calls and parameters made by applications into a prior knowledge set and make decisions based on this priori. However, since such systems focus on only the system security rather than the security of monitored programs themselves. Attackers may leverage legitimate privileges granted to application programs to compromise the system security.
To solve this problem, this project introduce the context information for system call based sandbox in order to further constrain the behaviors of user applications. The context refers all the available information that helps constructing the "situation" where a system call is made. This context information will prevent attackers from invoking any permitted system calls at anywhere or anytime.
In implementation, we leverage the learning feature of systrace to automatically generate security policies for each security sensitive system call at learning time. In particular, as the program is running, it maintains a large "sliding window" that records the context information, the most recent N system calls and parameters. So, whenever a sensitive system is made, it generates a policy that records the current system call number and parameters along with its "context". Then, at running time, when the sensitive system call is made, both the parameters and its "context information" will be checked to make sure this system call is made at the "right situation".
The context information could (or maybe should) be extended to add low level information such as the stack information and the PC address of the instruction that generate the system call. This information help security policies to know for sure whether an operation is made by the application or the attacker . Adding this low level properties certainly help improving the effectiveness for security protection, but for simplicity and performance issue, our project does not use it.
Segmentation fault is often a problem for programmers. It generally happens when a program is trying access a virtual memory address that cpu cannot physically address. But in fact, segmentation fault could happen in a lot more cases. For instance, in Unix systems running on top of x86 processor, a program will get a segmentation fault when some processor protection mechanisms are violated. This fault is internally represented as the General Protection Fault. Segmentation fault could also occurs when the running program receives a SIGSEGV from other process (e.g. you use "kill -11 your_program" in your terminal). Moreover, Segmentation fault is also a default behavior that kernel enforces when signal handling has any problems (the kernel routine in v3.0 is force_sigsegv())
I find this interesting article in Phrack that could keep your program free from SIGSEGV. Generally, it is a helpful solution that tolerants fault. In particular, it may help when you are using some buggy but useful tool (e.g. a buggy netscape to surf on the Internet, you will be fine when it has bugs when openning a web page, but don't want the whole browser crashed)
The basic idea in this article is to register a signal handler in a preloaded library. It will intercept the SIGSEGV signal from the target program and help the program jump over the faulting instruction.
Unfortunately, the solution in Phrack does not work right now for two reasons. This first one is that it cannot accurately caculate the address of EIP in signal frame. Failing to update EIP will force the program to re-execute the faulting instruction and killed by the kernel. The second reason is that when it modifies the EIP, it SIMPLY "increment the EIP by one". This is a dangerious solution, since CPU will begin decoding instruction from EIP+1 which may generate other faults (e.g. SIGILL as illegal instruction) and terminate the program if EIP+1 happens to be "halt" (0xf4)
Based on the work above, I make the solution up to date. In particular, I use the library call sigaction(3) rather than signal(3) to intercept signal handling, since sigaction() allows to access sigal stack using the third parameter in the signal handler function, while the function registered by signal() has only one argument (the signal num). On the other hand, rather than "incrementing EIP by one", I use a disassembler opdis to get the correct size of the faulting instruction. This will help the program "jump over" exactly to the next legitimate instruction.