System Calls Tracking Module - Requirements

$Id: syscall_tracker_requirements.html,v 1.6 2001/09/09 15:17:43 chooga Exp $

TOC

  1. Preface
  2. Purpose Of The Syscall Tracking Module
  3. Similar Existing Tools
  4. Mode Of Operation
  5. Module Features
    1. System Calls Invocation Filtering
      1. System Call ID Matching
      2. Parameters Pattern Matching
      3. Process State Pattern Matching
    2. Actions For Filtered System Calls
      1. Logging
      2. System Call Disabling
      3. Modifying Process State
  6. Design Considerations
    1. Security
    2. Efficiency
    3. Portability
  7. Module Versions Roadmap


Preface

This document describes the requirements for a system calls tracking module. The requirements pertain to its features, as well as its basic mode of operation.


Purpose Of The Syscall Tracking Module

The syscall tracking module is meant to allow a system administrator or a programmer to define a set of system calls invocations to be tracked by the module. System calls tracking includes filtering system calls (choosing which specific system call invocations to track) and actions to take for tracked system calls (e.g. logging the invocation, halting the calling process, etc).

Some scenarios for using this module:


Similar Existing Tools

The 'strace' utility is an existing utility that allows a user to filter system calls invoked by a specific system process (and follow its child processes as well). However, this utility differs from our proposed module in the following aspects:

  1. strace does not allow to trace system calls performed by _all_ processes on the system.
  2. strace causes a large performance penalty for the traced process(es), due to the need to switch between user-mode and kernel-mode constantly.
  3. strace (as is written today) only allows _logging_ system calls invocations. it does not allow supporting other features (e.g. canceling a specific invocation). Adding such features to strace might require changing the kernel.
  4. strace has the major limitation that only one process can 'ptrace' another process at the same time. this is a commonly used anti-debugging technique, where a process will ptrace itself to avoid other processes from ptracing it.
On the other hand, the filtering features of strace are quite powerful, and some of them would be "adopted" by the proposed module.

The 'medusa security system' is a linux kernel patch and corresponding user space utilities used to add tighter security to linux systems by (along with many other things) controlling system call invocations. it's available at http://medusa.fornax.sk/


Mode Of Operation

The syscall tracker module will be loaded either at boot time or when the administrator wants to start tracking system call invocations. It will be configured via ioctl calls, sysctl calls or the proc file system, to filter certain syscall invocations, and will also be told what actions to take for the filtered system calls.

The module will then "hijack" the entries in the system call table ( sys_call_table as of kernel v2.2.X and v2.4.x), so its tracking functions will be invoked instead of the original system calls. Each such function will check the parameters it receives, and if they match one of the filtering rules, the module will perform the relevant action.

Logging data might be performed either by using printk directly, or by writing log records into a special device file, and have a user-space program that would read data from the device file, and do the actual logging to a file.

When the module is unloaded, it will release any hijacked system call table entries, and allow the system to continue working, as if the module was never loaded.


Module Features

The syscall tracker module would support a set of filtering features, as well as a set of actions to take for filtered system calls. A user-space utility program will also be written, that will parse a configuration file, and translate its rules into calls to ioctl (or sysctl) to configure the module.

Re-configuration would be trivially achieved by modifying the configuration file and notifying the kernel (via one of the method mentioned above). Reconfiguring the module while it is running could be achieved using a command line utility that allows a single rule add/modify/delete operation at a time.


System Calls Invocation Filtering

The filtering is the most critical part in the flow of the module. It should be performed in a way that will place the smallest performance penalty possible on the system. Filtering would be done based on the specific system call(s) to track, the values of parameters passed to those system calls, and the state of the process invoking them (e.g. the UID of the process, the name of the command it is running, etc.).


System Call ID Matching

In the filtering rules, the user will be able to specify that the module track certain system calls. This filtering may be combined with other criteria, as explained below.


Parameters Pattern Matching

A user may add parameters matching criteria to filtering rules. Thus, a user may specify that all invocations of 'open' will be tracked, or that all invocations of 'open' whose flags parameter have the O_RDONLY flag set will be tracked, or that all invocations of 'open' in which the file parameter ends with the name 'passwd' are to be tracked.

For numeric parameters, the user may specify matches based on exact value, value ranges, and bit operations (e.g. match if bit 0 is set).

For string parameters, the user may specify matches based on exact string, substrings and _simple_ regular expressions. Regular expressions should be kept simple to reduce filtering overhead.

For structure parameters, the user will be able to filter based on the contents of their various fields.


Process State Pattern Matching

Process state would be used to further fine-tune filtering rules. The user will be able to specify matches based on the UID, EUID, GID and EGID, PID and PPID (parent PID) of the process invoking the system call, based on the command the process is running, etc.


Actions For Filtered System Calls

The user may specify a set of actions to perform once a certain filtering rule is matched. The matched invocation could be simply logged to a log file. However, sometimes this is not sufficient. For example, if we want to find who erases a certain file, logging the process's UID and command might show that the command '/bin/rm' erases the file. However, we have no idea if it was invoked from an interactive shell, or via some program. In such a case, we might want to simply suspend the process that is trying to invoke this system call. Thus, when the administrator later gets to the system and sees (via the log file) that a process tried to erase the file, the administrator will be able to find the stopped process, and possibly check who is its parent process.


Logging

Logging is the most basic action to take when a filtering rule matches. The logging format should be concise, in order to use as few resources as possible (time to perform the logging, amount of data that might cross into user-space, size of log file). A utility program will be supplied that reads a log file and prints it out in human-readable form (e.g. translating system call numbers into names, translating UID into user name and formatting the output in a readable form). Alternatively, if logging is done to syslog via 'printk', a log parser utility could be written to present the log output in a comfortable manner.


System Call Disabling

Sometimes we might want to just disable (fail) a specific system call invocation. For example, disable any attempt to remove a certain file from the system, etc. Using the proposed module is surely not an efficient method to perform such blocking (e.g. the path name to the file in the 'rm' system call isn't necessarily a full path, and thus some calculations might be required), but could serve as a temporary means, until the real problem is solved (e.g. the culprit program's source code is fixed).


Modifying Process State

Modifying process state could include killing the process that performed a certain syscall invocation, suspending this process, removing its SUID status, etc.


Design Considerations

Certain considerations should affect the design of the module. We outline a few of them here.


Security

The module should be written in a clean manner, to avoid adding security holes to the kernel. Parameter accessing should be done in the exact same manner as the original system call performs it. The module should be as simple as possible (although not simpler). Any code which is not kernel specific should be developed, debugged and tested in user space.

Note also that this module is not meant to be used to add tighter security to the Linux kernel.


Efficiency

The module should add the lowest overhead possible to the invocation of system calls. Thus, it should perform all filtering operations in kernel mode, and not revert to user-mode programs for that purpose. Performing the filter rules matching should be done in the most efficient manner possible, without modifying the kernel (more on this in the 'portability' considerations section).

System calls that do not appear in any filtering rule should not be hijacked, and thus no overhead would be added when they are invoked. When the module is not loaded, there should be no performance penalty at all for any system call invocation.

Logging should be performed in the most efficient manner possible (the two alternatives are using printk directly, or writing logging records to a device file, and have a user-space process that will read data from this device file).


Portability

The module should not require patching the kernel, and should use as few kernel-specific variables as possible. Of-course using the process structure for filtering is un-avoidable. This will make it easier to port the module between different hardware platforms (Intel, Alpha, Sparc...) and between different kernel versions.

Because of this requirement, we cannot re-implement system calls inside the module, nor add the filtering inside the kernel's code proper - the original kernel-supplied system call functions should be called right after the tracking operation is performed.

Finally, the module should work both on single-processor machines as well as on multi-processor machines (running in SMP mode).


Module Versions Roadmap

In order to facilitate rapid development for the syscall tracking module, development will be performed incrementally, adding features as versions are completed. Here is a suggested roadmap:

  1. Basic Logging - support for a set of "interesting" system calls, with filtering only based on system call ID. Logging will be done without any special formatting. Logging will be done using printk calls. Configuration file allows specifying which system calls to log. ioctl() support for interacting with the module. "interesting" systems calls: open, close, read, write, unlink, mkdir, rmdir, rename, symlink, creat, chdir.
  2. Process State Filtering - adding the possibility to filter based on a few process parameters: UID, GID, EUID, EGID, command string.
  3. Parameter Parsing - adding support for parsing syscall parameters and filtering based on their values.
  4. Syscall Disabling - adding support for system-call disabling actions.
  5. Process State Modification - adding support for process state modification actions.
  6. Device File - adding support for writing log records into a device file, and writing a user-space program that reads from that device file and writes to syslog. Need to find a method to assure no loss of data if the user-space process is being stopped for a short duration.
  7. All System Calls - adding support for all system calls.
  8. Other Architectures - testing the module on architectures other then Intel's (Sparc? Alpha?).
  9. Other Kernel Versions - testing the module on other kernel versions then the one(s) it was developed for, including porting where needed.