kmod_util Kernel Service

Purpose

Registers routines to be called before and after specified system calls are invoked.

Syntax

#include <sys/sysconfig.h>

int kmod_util ( flags, buffer, blen)
int flags;
void * buffer;
long blen;

Parameters

Item Description
flags

Specifies the operation. Valid values are KU_INTERCEPT, KU_INTERCEPT_STOP, and KU_INTERCEPT_CANCEL.

buffer

Points to a buffer containing a system call interception header and an array of system call interception structures.

blen

Specifies the length of the buffer.

Description

The kmod_util kernel service allows system calls to be intercepted. Routines called pre-sc functions are specified to be called before the intercepted system call. Routines called post-sc functions are specified to be called after the intercepted system call. In addition, a pre-sc function is allowed to abort the system call, providing its own return value and preventing subsequent pre-sc functions and the system call itself from being called. Similarly, each post-sc function may examine and alter the return value. If a system call does not return (e.g., thread_terminate), post-sc functions are not called.

For each intercepted system call, either a pre-sc function, a post-sc function, or both, must be specified. If a pre-sc function and post-sc function are registered for the same system call in the same kmod_util invocation, they are considered paired. All pre-sc and post-sc functions specified in a kmod_util call must be defined in the same kernel extension as the caller of the kmod_util kernel service. Other kernel extensions, however, can intercept the same system calls. The most recently registered pre-sc function is called first, and its paired post-sc function is called last.

The interception of a system call is implemented so that all calls to the system call are intercepted, even for existing processes.

It may be necessary to prevent the interception of certain system calls to avoid destabilizing the system. A future version or release of the kmod_util kernel service may prevent the interception of additional system calls, and such a change will not be considered a violation of binary compatibility.

The prototype of a pre-sc function is

int pre_sc(uintptr_t *rc, void *parms, uintptr_t cookie, void *buffer);

where parms is a pointer to the parameters of the system call, cookie is an opaque value specified by the caller of kmod_util, buffer is a scratch 128-byte buffer for use by the pre-sc function and its paired post-sc function.

If the pre-sc function returns non-zero, the system call is aborted. The rc parameter is the address where an alternate return value can be specified. Subsequent pre_sc functions are not called, nor is the system call. For pre-sc functions already called, their paired post-sc functions are called.

The prototype of a post-sc function is

void post_sc(uintptr_t *rc, void *parms, uintptr_t cookie,
			void *buffer);

The parameters of the post-sc function are the same as those of the pre-sc function. In particular, the buffer parameter is the same buffer that was passed to the paired pre-sc function. The return value can be modified by a post-sc function.

For calls to the kmod_util kernel service, the buffer contains a header and an array of elements about system calls to be intercepted. The layout of these structures is defined in <sys/sysconfig.h>.

An array element is ignored if the KU_IGNORE flag is set in the kue_iflag field. Otherwise, each array element in the input buffer is validated, and if any errors are found, the entire call fails without any partial execution.

Intercepting System Calls
Calls to kmod_util() with the KU_INTERCEPT flag initiate system call interception.
Stopping System Call Interception

Calls to kmod_util() with the KU_INTERCEPT_STOP flag suspend the interception of the specified system calls. If a pre-sc function has already been called for a specified system call, its paired post-sc function will still be called, but future calls to the system call will not invoke either the pre-sc or post-sc function. It is not valid to stop interception of a system call that was not originally intercepted by the calling kernel extension.

If the interception of a system call has been suspended, it may be resumed by calling the kmod_util() function with the KU_INTERCEPT flag, as long as the same values are specified, such as the pre-sc and post-sc functions.

Cancelling System Call Interception

System call interception can be cancelled by specifying the KU_INTERCEPT_CANCEL flag. When interception is cancelled, the post-sc function is not called even if its paired pre-sc function was called. It is not valid to cancel interception of a system call that was not originally intercepted by the calling kernel extension, but interception can be cancelled without first stopping interception.

Once interception of a system call has been cancelled, it can be intercepted anew by calling the kmod_util() function with the KU_INTERCEPT flag. Different pre-sc and pre-sc functions can be specified in this case.

Return Values

If the specified operations can be enacted for all specified system calls, 0 is returned. Otherwise, a non-zero value is returned and no change in the state of system call interception occurs. If an error occurs because of a validation error in a particular array element, the kue_oflags field usually identifies the error in more detail.

ERROR CODES

If an error results, one of the following error values is returned:

Return Value Description
EINVAL

The flags parameter is not KU_INTERCEPT, KU_INTERCEPT_STOP, nor KU_INTERCEPT_CANCEL.

The fields in the header are invalid or the blen parameter is not consistent with the number of array elements.

The buffer was invalid. For KU_INTERCEPT, at least one of the pre-sc and post-sc must be supplied for each system call to be intercepted. All pre-sc and post-sc functions must be in the same kernel extension as the caller of kmod_util().

EBUSY

A request was made to intercept a system call that was already being intercepted.

ENOENT

A request was made to stop or cancel interception of a system call that was not being intercepted.

ENOMEM

Memory could not be allocated to satisfy the request.

ENOTSUPP

One of the specified system calls is not allowed to be intercepted.