Loadable kernel module

Last updated

In computing, a loadable kernel module (LKM) is an object file that contains code to extend the running kernel, or so-called base kernel, of an operating system. LKMs are typically used to add support for new hardware (as device drivers) and/or filesystems, or for adding system calls. When the functionality provided by an LKM is no longer required, it can be unloaded in order to free memory and other resources.

Contents

Most current Unix-like systems and Microsoft Windows support loadable kernel modules under different names, such as kernel loadable module (kld) in FreeBSD, kernel extension (kext) in macOS (although support for third-party modules is being dropped [1] ), [2] kernel extension module in AIX, dynamically loadable kernel module in HP-UX, [3] kernel-mode driver in Windows NT [4] and downloadable kernel module (DKM) in VxWorks. They are also known as kernel loadable modules (or KLM), and simply as kernel modules (KMOD).

Advantages

Without loadable kernel modules, an operating system would have to include all possible anticipated functionality compiled directly into the base kernel. Much of that functionality would reside in memory without being used, wasting memory, and would require that users rebuild and reboot the base kernel every time they require new functionality.

Disadvantages

One minor criticism of preferring a modular kernel over a static kernel is the so-called fragmentation penalty. The base kernel is always unpacked into real contiguous memory by its setup routines; thus, the base kernel code is never fragmented. Once the system is in a state in which modules may be inserted, for example once the filesystems have been mounted that contain the modules, it is likely that any new kernel code insertion will cause the kernel to become fragmented, thereby introducing a minor performance penalty by using more TLB entries, causing more TLB misses.[ citation needed ]

Implementations in different operating systems

Linux

Loadable kernel modules in Linux are loaded (and unloaded) by the modprobe command. They are located in /lib/modules or /usr/lib/modules and have had the extension .ko ("kernel object") since version 2.6 (previous versions used the .o extension). [5] The lsmod command lists the loaded kernel modules. In emergency cases, when the system fails to boot due to e.g. broken modules, specific modules can be enabled or disabled by modifying the kernel boot parameters list (for example, if using GRUB, by pressing 'e' in the GRUB start menu, then editing the kernel parameter line).

License issues

In the opinion of Linux maintainers, LKM are derived works of the kernel[ citation needed ]. The Linux maintainers tolerate the distribution of proprietary modules,[ citation needed ] but allow symbols to be marked as only available to GNU General Public License (GPL) modules.

Loading a proprietary or non-GPL-compatible module will set a 'taint' flag [6] [7] in the running kernel—meaning that any problems or bugs experienced will be less likely to be investigated by the maintainers. [8] [9] LKMs effectively become part of the running kernel, so can corrupt kernel data structures and produce bugs that may not be able to be investigated if the module is indeed proprietary.

Linuxant controversy

In 2004, Linuxant, a consulting company that releases proprietary device drivers as loadable kernel modules, attempted to abuse a null terminator in their MODULE_LICENSE, as visible in the following code excerpt:

MODULE_LICENSE("GPL\0for files in the \"GPL\" directory; for others, only LICENSE file applies");

The string comparison code used by the kernel at the time tried to determine whether the module was GPLed stopped when it reached a null character (\0), so it was fooled into thinking that the module was declaring its license to be just "GPL". [10]

FreeBSD

Kernel modules for FreeBSD are stored within /boot/kernel/ for modules distributed with the operating system, or usually /boot/modules/ for modules installed from FreeBSD ports or FreeBSD packages, or for proprietary or otherwise binary-only modules. FreeBSD kernel modules usually have the extension .ko. Once the machine has booted, they may be loaded with the kldload command, unloaded with kldunload, and listed with kldstat. Modules can also be loaded from the loader before the kernel starts, either automatically (through /boot/loader.conf) or by hand.

macOS

Some loadable kernel modules in macOS can be loaded automatically. Loadable kernel modules can also be loaded by the kextload command. They can be listed by the kextstat command. Loadable kernel modules are located in bundles with the extension .kext. Modules supplied with the operating system are stored in the /System/Library/Extensions directory; modules supplied by third parties are in various other directories.

NetWare

A NetWare kernel module is referred to as a NetWare Loadable Module (NLM). NLMs are inserted into the NetWare kernel by means of the LOAD command, and removed by means of the UNLOAD command; the modules command lists currently loaded kernel modules. NLMs may reside in any valid search path assigned on the NetWare server, and they have .NLM as the file name extension.

VxWorks

A downloadable kernel module (DKM) type project can be created to generate a ".out" file which can then be loaded to kernel space using "ld" command. This downloadable kernel module can be unloaded using "unld" command.

Solaris

Solaris has a configurable kernel module load path, which defaults to /platform/platform-name/kernel /kernel /usr/kernel. Most kernel modules live in subdirectories under /kernel; those not considered necessary to boot the system to the point that init can start are often (but not always) found in /usr/kernel. When running a DEBUG kernel build the system actively attempts to unload modules.

Binary compatibility

Linux does not provide a stable API or ABI for kernel modules. This means that there are differences in internal structure and function between different kernel versions, which can cause compatibility problems. In an attempt to combat those problems, symbol versioning data is placed within the .modinfo section of loadable ELF modules. This versioning information can be compared with that of the running kernel before loading a module; if the versions are incompatible, the module will not be loaded.

Other operating systems, such as Solaris, FreeBSD, macOS, and Windows keep the kernel API and ABI relatively stable, thus avoiding this problem. For example, FreeBSD kernel modules compiled against kernel version 6.0 will work without recompilation on any other FreeBSD 6.x version, e.g. 6.4. However, they are not compatible with other major versions and must be recompiled for use with FreeBSD 7.x, as API and ABI compatibility is maintained only within a branch.

Security

While loadable kernel modules are a convenient method of modifying the running kernel, this can be abused by attackers on a compromised system to prevent detection of their processes or files, allowing them to maintain control over the system. Many rootkits make use of LKMs in this way. Note that, on most operating systems, modules do not help privilege elevation in any way, as elevated privilege is required to load a LKM; they merely make it easier for the attacker to hide the break-in. [11]

Linux

Linux allows disabling module loading via sysctl option /proc/sys/kernel/modules_disabled. [12] [13] An initramfs system may load specific modules needed for a machine at boot and then disable module loading. This makes the security very similar to a monolithic kernel. If an attacker can change the initramfs, they can change the kernel binary.

macOS

In OS X Yosemite and later releases, a kernel extension has to be code-signed with a developer certificate that holds a particular "entitlement." Such a developer certificate is only provided by Apple on request and not automatically given to Apple Developer members. This feature, called "kext signing", is enabled by default and it instructs the kernel to stop booting if unsigned kernel extensions are present. [14] In OS X El Capitan and later releases, it is part of System Integrity Protection.

In older versions of macOS, or if kext signing is disabled, a loadable kernel module in a kernel extension bundle can be loaded by non-root users if the OSBundleAllowUserLoad property is set to True in the bundle's property list. [15] However, if any of the files in the bundle, including the executable code file, are not owned by root and group wheel, or are writable by the group or "other", the attempt to load the kernel loadable module will fail. [16]

Solaris

Kernel modules can optionally have a cryptographic signature ELF section which is verified on load depending on the Verified Boot policy settings. The kernel can enforce that modules are cryptographically signed by a set of trusted certificates; the list of trusted certificates is held outside of the OS in the ILOM on some SPARC based platforms. Userspace initiated kernel module loading is only possible from the Trusted Path when the system is running with the Immutable Global Zone feature enabled.

See also

Related Research Articles

A monolithic kernel is an operating system architecture where the entire operating system is working in kernel space. The monolithic model differs from other operating system architectures in that it alone defines a high-level virtual interface over computer hardware. A set of primitives or system calls implement all operating system services such as process management, concurrency, and memory management. Device drivers can be added to the kernel as modules.

Darwin is the core Unix operating system of macOS, iOS, watchOS, tvOS, iPadOS, visionOS, and bridgeOS. It previously existed as an independent open-source operating system, first released by Apple Inc. in 2000. It is composed of code derived from NeXTSTEP, BSD, Mach, and other free software projects' code, as well as code developed by Apple.

<span class="mw-page-title-main">GNU GRUB</span> Boot loader package

GNU GRUB is a boot loader package from the GNU Project. GRUB is the reference implementation of the Free Software Foundation's Multiboot Specification, which provides a user the choice to boot one of multiple operating systems installed on a computer or select a specific kernel configuration available on a particular operating system's partitions.

<span class="mw-page-title-main">Multi-booting</span> Act of installing multiple operating systems on a single computer

Multi-booting is the act of installing multiple operating systems on a single computer, and being able to choose which one to boot. The term dual-booting refers to the common configuration of specifically two operating systems. Multi-booting may require a custom boot loader.

<span class="mw-page-title-main">XNU</span> Computer operating system kernel

XNU is the computer operating system (OS) kernel developed at Apple Inc. since December 1996 for use in the Mac OS X operating system and released as free and open-source software as part of the Darwin OS, which in addition to macOS is also the basis for the Apple TV Software, iOS, iPadOS, watchOS, visionOS, and tvOS OSes. XNU is an abbreviation of X is Not Unix.

<span class="mw-page-title-main">UEFI</span> Operating system and firmware specification

In computing, Unified Extensible Firmware Interface is a specification that defines the architecture of the platform firmware used for booting the computer hardware and its interface for interaction with the operating system. Examples of firmware that implement the specification are AMI Aptio, Phoenix SecureCore, TianoCore EDK II, InsydeH2O. UEFI replaces the BIOS which was present in the boot ROM of all personal computers that are IBM PC compatible, although it can provide backwards compatibility with the BIOS using CSM booting. Intel developed the original Extensible Firmware Interface (EFI) specification. Some of the EFI's practices and data formats mirror those of Microsoft Windows. In 2005, UEFI deprecated EFI 1.10.

<span class="mw-page-title-main">DTrace</span> Dynamic tracing framework for kernel and applications

DTrace is a comprehensive dynamic tracing framework originally created by Sun Microsystems for troubleshooting kernel and application problems on production systems in real time. Originally developed for Solaris, it has since been released under the free Common Development and Distribution License (CDDL) in OpenSolaris and its descendant illumos, and has been ported to several other Unix-like systems.

launchd is an init and operating system service management daemon created by Apple Inc. as part of macOS to replace its BSD-style init and SystemStarter. There have been efforts to port launchd to FreeBSD and derived systems.

<span class="mw-page-title-main">NDISwrapper</span> Driver wrapper for Windows devices used on Linux

NDISwrapper is a free software driver wrapper that enables the use of Windows XP network device drivers on Linux operating systems. NDISwrapper works by implementing the Windows kernel and NDIS APIs and dynamically linking Windows network drivers to this implementation. As a result, it only works on systems based on the instruction set architectures supported by Windows, namely IA-32 and x86-64.

In computing, a dynamic linker is the part of an operating system that loads and links the shared libraries needed by an executable when it is executed, by copying the content of libraries from persistent storage to RAM, filling jump tables and relocating pointers. The specific operating system and executable format determine how the dynamic linker functions and how it is implemented.

<span class="mw-page-title-main">Apple–Intel architecture</span> Unofficial name used for Macintosh models that use Intel x86 processors

The Apple–Intel architecture, or Mactel, is an unofficial name used for Macintosh personal computers developed and manufactured by Apple Inc. that use Intel x86 processors, rather than the PowerPC and Motorola 68000 ("68k") series processors used in their predecessors or the ARM-based Apple silicon SoCs used in their successors. As Apple changed the architecture of its products, they changed the firmware from the Open Firmware used on PowerPC-based Macs to the Intel-designed Extensible Firmware Interface (EFI). With the change in processor architecture to x86, Macs gained the ability to boot into x86-native operating systems, while Intel VT-x brought near-native virtualization with macOS as the host OS.

<span class="mw-page-title-main">EFI system partition</span> Partition used by Unified Extensible Firmware Interface

The EFIsystem partition or ESP is a partition on a data storage device that is used by computers having the Unified Extensible Firmware Interface (UEFI). When a computer is booted, UEFI firmware loads files stored on the ESP to start installing operating systems and various utilities.

<span class="mw-page-title-main">FreeBSD</span> Free and open-source Unix-like operating system

FreeBSD is a free and open-source Unix-like operating system descended from the Berkeley Software Distribution (BSD). The first version of FreeBSD was released in 1993. In 2005, FreeBSD was the most popular open-source BSD operating system, accounting for more than three-quarters of all installed and permissively licensed BSD systems.

License compatibility is a legal framework that allows for pieces of software with different software licenses to be distributed together. The need for such a framework arises because the different licenses can contain contradictory requirements, rendering it impossible to legally combine source code from separately-licensed software in order to create and publish a new program. Proprietary licenses are generally program-specific and incompatible; authors must negotiate to combine code. Copyleft licenses are commonly deliberately incompatible with proprietary licenses, in order to prevent copyleft software from being re-licensed under a proprietary license, turning it into proprietary software. Many copyleft licenses explicitly allow relicensing under some other copyleft licenses. Permissive licenses are compatible with everything, including proprietary licenses; there is thus no guarantee that all derived works will remain under a permissive license.

<span class="mw-page-title-main">Berkeley Software Distribution</span> Unix operating system

The Berkeley Software Distribution or Berkeley Standard Distribution (BSD) is a discontinued operating system based on Research Unix, developed and distributed by the Computer Systems Research Group (CSRG) at the University of California, Berkeley. The term "BSD" commonly refers to its open-source descendants, including FreeBSD, OpenBSD, NetBSD, and DragonFly BSD.

ptrace is a system call found in Unix and several Unix-like operating systems. By using ptrace one process can control another, enabling the controller to inspect and manipulate the internal state of its target. ptrace is used by debuggers and other code-analysis tools, mostly as aids to software development.

<span class="mw-page-title-main">NetBSD</span> Free and open-source Unix-like operating system

NetBSD is a free and open-source Unix operating system based on the Berkeley Software Distribution (BSD). It was the first open-source BSD descendant officially released after 386BSD was forked. It continues to be actively developed and is available for many platforms, including servers, desktops, handheld devices, and embedded systems.

<span class="mw-page-title-main">OpenZFS</span> Open-source implementation of the ZFS file system

OpenZFS is an open-source implementation of the ZFS file system and volume manager initially developed by Sun Microsystems for the Solaris operating system and now maintained by the OpenZFS Project. It supports features like data compression, data deduplication, copy-on-write clones, snapshots, and RAID-Z. It also supports the creation of virtual devices, which allows for the creation of file systems that span multiple disks.

References

  1. "Deprecated Kernel Extensions and System Extension Alternatives". Apple Inc. Retrieved 13 March 2021.
  2. "Kernel Extension Programming Topics: Introduction". Apple Inc. September 1, 2010. Archived from the original on May 4, 2013. Retrieved May 5, 2013.
  3. "Managing and Developing DynamicallyLoadable Kernel Modules". Hewlett-Packard. June 7, 2001.
  4. "What Determines When a Driver Is Loaded". Microsoft Developer Network . Microsoft. November 21, 2012. Archived from the original on March 6, 2013. Retrieved May 5, 2013.
  5. "The Linux Kernel Module Programming Guide, section 2.2 "Compiling Kernel Modules"" . Retrieved 2020-10-05.
  6. Linus Torvalds; et al. (2011-06-21). "Documentation/oops-tracing.txt". kernel.org. Archived from the original on 2011-10-02. Retrieved 2011-10-03.
  7. "Tainted kernels". The Linux kernel user’s and administrator’s guide.
  8. Jonathan Corbet (2006-03-24). "Tainting from user space". LWN.net. Archived from the original on 2011-11-16. Retrieved 2011-10-03.
  9. "Novell support documentation: Tainted kernel". 2007-07-26. Retrieved 2011-10-03.
  10. Jonathan Corbet (April 27, 2004). "Being honest with MODULE_LICENSE". LWN.net. Archived from the original on November 2, 2012. Retrieved October 30, 2012.
  11. Exploiting Loadable Kernel Modules Archived 2012-02-04 at the Wayback Machine
  12. "Sysctl/kernel.txt". Archived from the original on April 15, 2013. Retrieved January 4, 2013.
  13. Kees Cook (2012-11-28). "Clean module disabling". outflux.net. Retrieved 2020-10-05.
  14. "Kernel Extensions". Mac Developer Library. Apple. September 16, 2015. Archived from the original on August 17, 2016. Retrieved September 29, 2016.
  15. "Info.plist Properties for Kernel Extensions". Apple Inc. Archived from the original on September 26, 2012. Retrieved September 27, 2012.
  16. kextload(8)    Darwin and macOS System Manager's Manual