Skip to content
FreeBSDDeep Dive Published Updated 7 min readViews unavailable

FreeBSD KLD Modules: Runtime Loading, Dependencies, and Safe Unload

Manage FreeBSD loadable kernel modules with kldload, kldstat, and kldunload; distinguish runtime tests from boot loading and diagnose busy or mismatched KLDs.

FreeBSD’s dynamic kernel linker lets the running kernel load and unload supported kernel objects, or KLDs, without rebuilding and rebooting the entire system. This is useful when testing an optional driver, enabling a filesystem, or diagnosing whether a feature is already present. It is not a general safety boundary: a kernel module executes in kernel context, can affect every process, and may not be compatible with the running kernel. Treat runtime module operations as kernel changes with a rollback and console plan.

The three everyday tools answer different questions. kldload requests that a module file be linked into the kernel. kldstat reports dynamically linked files and modules. kldunload asks the kernel linker to remove a loadable object. None of them substitutes for determining whether the feature is built into the kernel, whether a device is attached, or whether a consumer still references the module.

Determine whether loading is necessary

A driver compiled directly into the kernel is not represented as an independently loaded .ko file. Therefore, absence from kldstat does not prove that a feature is unavailable. Check the kernel configuration, boot messages, device enumeration, the module’s manual page, and any relevant sysctl or status utility. For a driver, use pciconf, usbconfig, dmesg, or the subsystem’s own status command to verify the actual device state.

For a module intended to load dynamically, confirm that a matching file exists under the running kernel’s module directories and that its name matches the module identifier. The kernel module path is available from sysctl kern.module_path. Avoid copying a .ko built for another FreeBSD release, architecture, or kernel build into /boot/kernel. Kernel interfaces change, and a mismatched binary may fail to load or destabilize the system rather than report a friendly error.

Record the current kernel and userland release, kernel configuration, module path, module file timestamp, and checksum for non-base modules before a test. If the module comes from a package or local build, record its source revision and build options. A module that loads successfully is not automatically the module you meant to test; verify the path shown by kldstat and ensure that no stale duplicate appears earlier in the search path.

Load a module for a bounded test

For a module that is known to be present and appropriate for this kernel, use its documented module name:

sysctl kern.module_path
ls -l /boot/kernel/if_bridge.ko
kldload if_bridge
kldstat -h -m if_bridge
dmesg | tail -n 40

if_bridge is an example of a module name, not an instruction to enable bridging on a production network. First confirm that the file exists and understand the device or service impact. Some modules have dependencies and can cause the linker to load dependent objects. A successful command proves only that the kernel linker accepted the request; use the subsystem’s own status and a controlled functional test to verify behavior.

kldstat -m asks for a module by its module name, while -n filters by the KLD filename. The verbose listing can show module records nested inside a file. An object can therefore have a filename that differs from one of the module names it contains. When the output is ambiguous, compare both the file path and module name rather than grepping an unstructured full listing.

Capture kernel messages immediately after a load attempt. A refusal may describe unresolved symbols, an unsupported module version, a dependency failure, or an initialization error. Do not suppress those errors with quiet options during diagnosis. Repeating kldload after a failure is not a fix unless the root cause was transient and understood.

Understand references and unload constraints

Kernel modules are often busy because a driver owns an attached device, a filesystem has active mounts, or another module depends on it. kldstat’s reference information can help identify dependencies, but it does not tell you every application-level consequence of unloading. Consult the subsystem documentation, stop users through their normal shutdown path, detach devices only when safe, and unmount filesystems cleanly before attempting unload.

For a test driver with no active consumers, a normal unload looks like:

kldstat -h -m if_bridge
kldunload if_bridge
kldstat -m if_bridge

Use the actual module selected for the test. If kldunload returns EBUSY or reports a dependency, stop and determine what still references the object. Never force an unload merely to make the inventory look clean. Removing code that owns live devices or callbacks can corrupt kernel state or cause a panic. Some modules are intentionally not unloadable, and built-in kernel code cannot be removed through kldunload.

After an unload, verify that the expected device or filesystem behavior has disappeared and that logs contain no unexpected errors. For a driver, also confirm that the device was safely detached before removal. For a filesystem module, inspect mounts and open references before unloading. Keep an alternate console if the test affects storage, networking, or boot-critical hardware.

Choose the correct persistence stage

A successful kldload affects the running kernel; it does not persist automatically across reboot. FreeBSD offers separate configuration stages. Modules required by the loader or before root filesystems mount generally belong in /boot/loader.conf, using the module’s documented load variable when one exists. Modules needed later in normal startup can be listed in the kld_list rc.conf variable. They are not interchangeable: rc startup happens later than loader processing, so it cannot provide a driver needed to discover or mount the root device.

For a non-root, late-starting module, a persistent setting can be added with sysrc after a successful test:

sysrc kld_list+=if_bridge
sysrc kld_list

Use the module appropriate to the host and preserve existing kld_list entries. Before reboot, inspect the resulting rc.conf line, verify that the module is not already specified in loader.conf or another startup script, and ensure the module file will remain installed after updates. Test the next boot with console access and confirm the module is loaded at the intended stage.

Loader directives should follow the specific module manual. For example, a filesystem or storage driver may need to be available before mounting root, while a network feature that is created only after the network interfaces exist might be loaded through rc. The exact dependency order matters. An early load can alter hardware probing, while a late load can make a service start before its interface exists.

Diagnose common loading failures

“File not found” is often a missing module package, wrong module name, or module path problem. “Exec format error” and unresolved symbol messages suggest a module built for an incompatible kernel or missing dependency. A duplicate module loaded from a custom directory can be mistaken for the base-system module. Compare kldstat’s pathname with the expected file and rebuild external modules against the exact running kernel when necessary.

If kldload succeeds but no device appears, inspect dmesg, driver hints, firmware, bus enumeration, and the module’s own manual. A driver can load while no matching hardware is present. Conversely, a driver might be statically built into the kernel and already active despite no separate entry in kldstat. Avoid using kldload as a proxy for hardware detection.

If a module reload is required after changing its file, remember that replacing a pathname on disk does not replace the code already linked into the running kernel. The module must be safely unloaded and loaded again, or the system must be rebooted according to the component’s supported procedure. If it is busy, do not delete its file or overwrite it blindly; schedule a maintenance window and understand all references first.

Operational checklist

Before a load, verify the feature is not already built in or active, identify the exact module file, confirm ABI compatibility, read its manual, and define a functional test and rollback. During the test, capture kldstat and dmesg before and after, then test the subsystem’s behavior. Before unload, drain consumers and accept only a normal successful unload. Afterward, verify devices, mounts, and system logs.

Before making a test persistent, decide whether the module is needed during loader processing or only during normal rc startup. Record the reason, owner, expected kernel versions, and rollback command. After a FreeBSD upgrade or custom kernel rebuild, recheck external modules rather than assuming yesterday’s binary is valid. The operational goal is not merely to see a module name in kldstat; it is to ensure the intended code, at the intended boot stage, supports the expected workload without destabilizing the host.

Related:

Sources:

Comments