Automatically installing Linux kernel modules with the DKMS framework is a convenient way of distributing drivers that are maintained outside of the official kernel. However, while DKMS is included in many popular Linux distributions and supports most kernel modules, it canโt always guarantee proper installation of a third-party module.
In this article, we discuss the pros and cons of using DKMS and explain in which cases itโs not the best solution for Linux driver installation. This article will be useful for driver developers who are debating whether to use DKMS to distribute their software.
Contents
What is DKMS?
What is DKMS? Dynamic Kernel Module Support (DKMS) is a framework developed by Dell to automatically distribute kernel module updates to its customers. It simplifies both driver development and system administration, increasing overall system stability.
This framework allows developers to provide users with drivers that arenโt included in the official kernel release. DKMS also significantly increases the quality of module source code, as developers can test their drivers simultaneously on numerous machines.
DKMS also has advantages for system administrators, as it automatically installs device driver updates to the existing version of the kernel without introducing any changes to the kernel. So system administrators no longer have to wait for a new kernel version to be released.
Keep in mind that DKMS is not the only solution for installing kernel modules. There are also DKMS alternatives such as:
- AKMOD, a Fedora solution which relies on tools including GNU Compiler Collection and auto-make
- module-assistant (often abbreviated as m-a), a tool for manually compiling kernel modules
DKMS and AKMOD are similar, as they both rebuild modules for new kernel installation, while m-a requires manual execution and can build modules only for a currently running kernel. But this can be inconvenient, for example when installing a graphics driver.
Working on a complex driver project?
Entrust your driver creation activities to Apriorit engineers with experience in Linux development and a strong focus on cybersecurity.
Understanding the DKMS lifecycle
Letโs look closer at how DKMS works. DKMS duplicates the module tree outside of the kernel tree. This module tree includes module source code and its compiled binaries. When a new Linux kernel or driver version is released, DKMS uses a standardized approach to collect and build its source code.
Specifically, DKMS is a universal tool that can build driver code into loadable compiled module binary files, then install and uninstall those modules on any Linux kernel.
In addition, the framework provides special features for managing and maintaining modules across multiple systems, showing which module version is installed on which kernel version.
When considering whether to use DKMS, itโs necessary to understand its module lifecycle. Here is the flow of DKMS and its main commands for executing and managing a kernel module.
As you can see, thereโs a special set of commands for performing the main actions with Linux drivers.
You can see the current status of modules by running:
dkms status
This command shows the name, version, and state of each kernel module. Using this command, you can quickly understand if a device driver has been updated.
To add a module and its version to the existing DKMS tree, run the following:
dkms add [-m MODULE_NAME] [-v VERSION] [/path/to/module-src/]
If -m or -v options are omitted, DKMS will look up /usr/src/module-module-version
for sources as well as the dkms.conf file, or copy the passed /path/to/module-src/
to /usr/src/module-module-version
.
After the module is placed in the tree, you can build the module using the build command:
dkms build -m MODULE -v VERSION -k $(uname -r)
This command allows developers and system administrators to compile a previously added module for the current kernel. It also lets developers check a driver for bugs during development. After this, your module will be compiled but not installed.
If you want to copy compiled modules to the kernel tree, use the install command:
dkms install -m MODULE -v VERSION -k $(uname -r)
If there are two modules with the same name, the previously installed module will be backed up in /var/dkms/MODULE/original-module directory
. It will be saved as an original module so it can be restored if the newer module is uninstalled.
There are two commands for deleting a module from the DKMS tree: uninstall
and remove
.
The uninstall
command will delete the installed module and, if possible, replace it with a backup copy:
dkms uninstall -m MODULE -v VERSION -k $(uname โr)
To remove
the module from the kernel tree for the passed -k kernel version and architecture, run:
dkms remove -m MODULE -v VERSION -k $(uname -r)
If you want to remove a module from all installed kernels, add -all
:
dkms remove -m MODULE -v VERSION โall
The difference between the remove and uninstall commands is that uninstall
only deletes a module from the kernel tree, leaving the module in the built
state, while remove
also checks if other instances of the module exist for other kernels and, if there are none, cleans up the DKMS tree. After the tree is cleaned, the Linux user must add the module again to use it with DKMS.
Other noteworthy commands are match and auto-installer. The match
command is useful when you need to use one module for several kernels. In this case, match
uses the configuration from the module installed on one kernel and applies it to another.
Auto-installer
checks if the configuration file contains the AUTOINSTALL parameter and, if it does, DKMS will rebuild and install the module for this kernel when booting on a new kernel.
To use DKMS, you should provide a dkms.conf
file like this one:
PACKAGE_NAME="MY_MODULE"
PACKAGE_VERSION="1.0"
MAKE="make --uname_r=$kernelver"
CLEAN="make clean"
BUILT_MODULE_NAME="$PACKAGE_NAME"
DEST_MODULE_LOCATION="/kernel/drivers/misc"
REMAKE_INITRD="yes"
AUTOINSTALL="yes
The use of DKMS depends on the form in which a Linux driver is provided to its users. Below, weโll explain why.
Related project
Developing a Custom Secrets Management Desktop Application for Secure Password Sharing and Storage
Our client leveraged Aprioritโs cybersecurity expertise to develop a solution supporting Linux, Windows, and macOS. Find out how our partnership allowed the client to receive an efficient solution for safeguarding their sensitive information and protecting their valuable assets.
Main forms of Linux driver distribution
Linux driver developers can distribute their software in the following forms:
- As a precompiled kernel module
In this case, Linux users donโt have to worry about requirements for building the driver. Precompiled modules are released with the Linux kernel and require support for different flavors of Linux and different configuration options. However, it can take some time between the release of a new kernel and the release of the necessary version of a module. - As full-module source code
With full-module source code, a user can build a driver on their own. But this method relies on an installed compiler, additional build tools, and the appropriate kernel header files. - As a kernel module with closed-source binary parts and source code for a kernel interface layer
This type of kernel module is often used as a workaround for license infringement or distributions such as Free/Net BSD (Berkeley Software Distribution) and some Linux distributions in which combined binary firmware is accepted along with open-source interface parts.
DKMS expects that kernel modules will be supplied with open-source code, but sometimes drivers come with closed-source binary parts (like NVIDIA video drivers). In this case, the main part of the driver includes a closed-source binary linked object, also called a binary blob, and the source code for the kernel interface layer. The kernel interface, compiled as a general module, must be linked with the closed-source parts and must be compiled specifically for each kernel.
Building modules from source code usually requires a kernel-headers package, a compiler (like the GNU Compiler Collection), and a linker (usually /usr/bin/ld
from the binutils package). These components are necessary in case any changes are made to the closed-source part or just a module source code. In case any changes are made to the kernel application binary interface (ABI), such as changes to function signatures, the number of parameters, or their types, the correct kernel interface is required to support the interface code linked with the blob part.
Read also
How to Secure and Manage File Access with SELinux
Protect your product from potential hacks, data leaks, and breaches. Explore how to monitor and restrict access to potentially malicious files using custom policies and sandboxes in Security-Enhanced Linux (SELinux).
DKMS benefits and limitations
Though DKMS is undoubtedly a useful tool for Linux kernel driver distribution, it has limitations that can make driver developers shy away from it. So letโs look closer at the pros and cons of DKMS.
Pros of using DKMS:
- Itโs a convenient framework for building, installing, and removing various Linux kernel modules.
- It ensures that a Linux driver will be properly updated and installed in the right place.
- It allows you to manage installed modules and check their status.
- It lets you add a custom step, such as adding a customer driver digital signature via POST_BUILD and POST_INSTALL. This guarantees the safety of module installation.
- It supports the installation of deb and rpm packages out of the box.
- Itโs available for many Linux distributions.
- Linux users can update their drivers immediately after theyโre fixed. Therefore, they donโt need to wait for a new kernel version from the vendor.
- With this framework, itโs hard to forget to install the module for a newly installed kernel because all processes are automated.
Cons of using DKMS:
- Additional handling is required for resident modules.
- Source code for NVIDIA-like modules with blob parts arenโt convenient to deliver with DKMS, as they require source code for the kernel interface compiled for each kernel version.
- Thereโs a risk that a module wonโt be built by DKMS if its function names have changed or if there are changes in the ways the kernel interacts with its components.
- DKMS doesnโt guarantee proper installation in case of changes to the kernel application binary interface, as kernel interface and module source support are still required.
Related project
Supporting and Improving Legacy Data Management Software
Discover the success story of supporting a containerized Linux-based legacy solution for synchronizing data between local and cloud file storage. See how Apriorit helped the client to improve user experience by fixing issues, developing custom features, and enhancing software supportability.
Driver distribution without DKMS
In one of our Linux driver development projects, we were tasked with creating a driver that would be protected against module unloading and attempts to prevent its loading. Our client wanted to be sure of the moduleโs persistence and the boot sequence.
To achieve this goal, we decided to distribute the driver with precompiled modules. As our driver had closed-source binary parts, using DKMS wouldnโt have guaranteed proper installation.
However, the first issue that we faced was a wide range of Linux kernel versions and supported distributions. So we had to choose which to add our driver to.
Additionally, we encountered some issues while implementing our own system for module building and installation:
- Linux users may use different package managers, and the names of common build tools and kernel header packages can vary across distributions. So thereโs a risk that our driver wonโt be built properly.
- Some kernel versions donโt have available packages for kernel headers (for example, on Fedora) as they were taken out of public access.
- Some Linux kernels donโt support the PKCS7 digital signature algorithm, so we had to use the default signing mechanism instead.
- Thereโs an ambiguous and distribution-dependent approach for obtaining an installed kernel list, which confirms the presence of the kernel header package.
- We had issues with module building on some specific distributions/configurations. These issues can also appear in case of an automated build with DKMS or other similar tools.
Below, we provide some tips on how developers can verify the installation of their Linux module to the kernel without using DKMS.
When implementing a custom installer, a driver developer has to choose when and how their module should start, how to detect already installed modules, and how to verify if modules are signed properly.
These decisions should be made even if you decide to use modprobe for adding or removing your module from the Linux kernel.
If youโre considering using insmod for inserting your module into the kernel, you should take care to protect against blacklisting. However, in this case, youโll need to implement the init system module from scratch.
In the cases of eager loading or a resident module, driver developers may choose run-level script instead of user-defined auto start scripts, which are typically used for software. With all the variety of initial Linux boot systems (INIT Sys-V scripts, upstart, systemd, and others), the best choice is to implement a custom init.d script and rely on installed utilities (such as update-rc.d or chkconfing) to handle per-runlevel links. Runlevel is the concept for operating systems with Sys-V style initialization describing which processes, daemons, and drivers should be loaded or started for each mode.
However, thereโs no standard that defines the link location, structure, or even the complete list of such links. Also, the utilities mentioned above have different package versions across distributions with different functionality. For example, an earlier version of update-rc.d on Mint 17 allows specifying the boot priority, but the same utility on Mint 18 does not have this option, relying on module loading dependencies alone.
Conclusion
Thanks to continuous development by the Linux community, great tools such as DKMS appear. With DKMS, Linux users can automatically build and manage kernel modules without needing to wait for delivery of a new driver package. In addition, driver developers can verify the installation of their modules at the development stage. There is also a wide range of useful tools for Linux driver developers, so weโll continue to share our experience on this topic. Linux driver development requires a comprehensive approach, and our team of driver developers is always at your disposal.
At Apriorit, we have professional kernel and driver development teams with expertise in Linux. Our engineers have rich experience and are always ready to assist you with projects of any complexity.
Have a Linux-based project in mind?
Receive efficient and reliable drivers and other software products by leveraging Aprioritโs 20+ years of experience in the industry.