########################################################################### # Device Drivers Introduction # # Anuradha Weeraman, 30 June 2002 # # Adapted from "Linux Device Drivers", Alessandro Rubini # # $Id: devicedriverintro.txt,v 1.1 2004/06/02 21:17:53 anuradha Exp $ # ########################################################################### Linux device drivers work as black boxes that make a particular piece of hardware respond to well-defined internal programming interface. User activities are performed by a set of standard calls that are independent of the specific driver. Mapping those calls to device specific operations that act on real hardware is the job of the device driver. Drivers can be plugged in at run time by way of kernel modules. The role of the device driver should be to provide "mechanism" (what capabilities are to be provided), not "policy" (how those capabilities are to be used). Many device drivers are released with user programs to help with configuration, access to the target device and other policy related functions. Kernel roles : Process management Memory management Filesystems Device control Networking Unix distinguishes between three types of device types. So each kernel module usually implements one of these types : Char module Block module Network module A character (Char) device is one that can be accessed as a stream of bytes. A char driver is in charge of implementing this behaviour. Such a driver usually implements at least the open, close, read and write system calls. E.g. /dev/console, /dev/ttyS0 etc. A char device can only be accessed sequentially, and you can't traverse back and forth like in a regular file. There are a few exceptions to this theory though. Like char devices, block devices are accessed by filesystem nodes in the /dev directory. A block device is something that can host a filesystem, like a disk. In most Unix systems, a block device can be accessed only as multiples of a block, where a block is usually one KB or data or another power of 2. Therefore, block and char devices differ only in the way data is managed internally by the kernel. A block driver offers the kernel the same interface as a char driver, as well as an additional block oriented interface that is invisible to the user or applications. That block interface though, is essential to be able to mount a filesystem. Network transactions are made through interfaces. This could be hardware but also be purely software (loopback). A network interface isn't easily mapped into a node in the filesystem. It is still assigned a unique name by the kernel (e.g. eth0), but that doesn't have a corresponding entry in the filesystem. Communication between the kernel and network interface is completely different from that used in char and block devices. Instead of read and write, the kernel calls functions related to packet transmission. Other classes of driver modules exist in Linux. E.g. SCSI. Although every peripheral connected to the SCSI bus appears in /dev as either a char device or a block device, the internal organization of the software is different. Some other classes of device drivers : USB, FireWire, I20 In addition to device drivers, filesystems are perhaps the most important class of modules on a Linux system. A filesystem type determines how information is organized on a block device in order to represent a tree of directories and files. Since there is no explicit device associated, filesystems are software drivers, because it maps low-level data structures to high-level data structures. The filesystem module must implement the lowest level of the system calls that access directories and files. Such an interface is completely independent of the actual data transfer to and from the disk (or other medium), which is accomplished by a block device driver. The ability to decode filesystem information stays at the lowest level of the kernel hierarchy and is of utmost importance for almost everything. Security has two faces : deliberate, incidental. A kernel module can do ANYTHING and is just as powerful as a superuser shell. If the kernel has security holes, the system has security holes. In the official kernel, only authorized users can load kernel modules. The system call create_module if the invoking process is authorized to load a module into the kernel, which is usually superuser, or a cracker who has just gotten superuser access. Driver writers should avoid including security policy in kernel modules. They should be handled by higher levels within the kernel, under the control of the system administrator. Exceptions could be some types of device access which could adversely affect the system as a whole. Common C security problems such as buffer overflows, should be avoided. Never trust input from user processes. Any memory obtained from the kernel should be zeroed or otherwise initialized before making it available to user processes or devices. Any operations that could affect the whole system (e.g. reloading the firware, formatting a disk), should be restricted to privileged users. It is possible to compile a kernel without loadble module support. This requires that all drivers be compiled into the kernel. This would prevent rogue kernel modules from being loaded. This feature is available in kernels 2.2 and afterwards via the capability mechanism.