Go to main content

STREAMS Programming Guide

Exit Print View

Updated: November 2020
 
 

ioctl Processing

STREAMS is a special type of character device driver that is different from the historical character input/output (I/O) mechanism in several ways.

In a classical device driver, all ioctl calls are processed by the single device driver, which is responsible for their resolution. A classical device driver has user context, that is, all data can be copied directly to and from the user space.

By contrast, the stream head itself can process some ioctl calls. STREAMS ioctl calls operate independently of any particular module or driver on the stream. This means the valid ioctl calls that are processed on a stream change over time, as modules are pushed and popped on the stream. The stream modules have no user context and must rely on the stream head to perform copyin and copyout requests. For more information, see the ioctl(2) and streamio(4I) man pages.

There is no user context in a module or driver when the information associated with the ioctl call is received. This prevents use of ddi_copyin or ddi_copyout by the module. No user context also prevents the module and driver from associating any kernel data with the currently running process. In any case, by the time the module or driver receives the ioctl call, the process generating can have exited. For more information, see the ddi_copyin(9F) and ddi_copyout(9F) man pages.

STREAMS enables user processes to control functions on specific modules and drivers in a stream using ioctl calls. In fact, many streamio ioctl commands go no further than the stream head. They are fully processed there and no related messages are sent downstream. For an I_STR ioctl or an unrecognized ioctl command, the stream head creates an M_IOCTL message, which includes the ioctl argument. This is then sent downstream to be processed by the pertinent module or driver. STREAMS ensures that there is only one user-driven M_IOCTL operating on a stream at a time. The M_IOCTL message is the precursor message type carrying ioctl information to modules. Other message types are used to complete the ioctl processing in the stream. Each module has its own set of M_IOCTL messages it must recognize.


Caution  - Hardening Information. Modules and drivers should never assume that user data is correct. Users might be able to pass offsets that exceed the buffers supplied, or data that might be in kernel space. Values should always be checked against the range of data that is requested or supplied. Otherwise, panics or data corruption may occur.