.\" $NetBSD: module.9,v 1.54 2022/08/12 15:43:38 riastradh Exp $
.\"
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Andrew Doran.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd July 21, 2021
.Dt MODULE 9
.Os
.Sh NAME
.Nm module ,
.Nm module_load ,
.Nm module_autoload ,
.Nm module_unload ,
.Nm module_init_class ,
.Nm module_hold ,
.Nm module_rele ,
.Nm module_find_section ,
.Nm module_kernel ,
.Nm module_name ,
.Nm module_source ,
.Nm module_register_callbacks ,
.Nm module_unregister_callbacks ,
.Nm module_specific_key_create ,
.Nm module_specific_key_delete ,
.Nm module_getspecific ,
.Nm module_setspecific
.Nd kernel module loader
.Sh SYNOPSIS
.In sys/module.h
.Fn MODULE "class" "name" "required"
.Ft int
.Fn module_load "const char *name" "int flags" "prop_dictionary_t props" \
"modclass_t class"
.Ft int
.Fn module_autoload "const char *name" "modclass_t class"
.Ft int
.Fn module_unload "const char *name"
.Ft void
.Fn module_init_class "modclass_t class"
.Ft void
.Fn module_hold "module_t *module"
.Ft void
.Fn module_rele "module_t *module"
.Ft int
.Fn module_find_section "const char *" "void **" "size_t *"
.Ft "module_t *"
.Fn module_kernel "void"
.Ft "const char *"
.Fn module_name "struct module *module"
.Ft modsrc_t
.Fn module_source "struct module *module"
.Ft void
.Fn module_init "void"
.Ft void
.Fn module_start_unload_thread "void"
.Ft void
.Fn module_builtin_require_force "void"
.Ft void
.Fn module_load_vfs_init "void"
.Ft "void *"
.Fn module_register_callbacks "void (*)(struct module *)" \
"void (*unload)(struct module *)"
.Ft void
.Fn module_unregister_callbacks "void *"
.Ft specificdata_key_t
.Fn module_specific_key_create "specificdata_key_t *keyp" \
"specificdata_dtor_t dtor"
.Ft void
.Fn module_specific_key_delete "specificdata_key_t key"
.Ft "void *"
.Fn module_getspecific "module_t *mod" "specificdata_key_t key"
.Ft "void *"
.Fn module_setspecific "module_t *mod" "specificdata_key_t key" "void *data"
.Sh DESCRIPTION
Modules are sections of code that can be independently linked and selectively
loaded into or unloaded from a running kernel.
This provides a mechanism to update the module without having to relink
the kernel and reboot.
Modules can be loaded from within the kernel image, provided by the boot
loader, or loaded from the file system.
.Pp
The
.Nm
subsystem includes two data types:
.Bl -enum -offset indent
.It
The
.Vt module_t
type provides storage to describe a module.
.It
The
.Vt modinfo_t
type resides within
.Vt module_t
and contains module header info.
.El
.Pp
The module subsystem is protected by the global
.Va kernconfig_mutex .
.Sh FUNCTIONS
.Bl -tag -width abcd
.It Fn MODULE "class" "name" "required"
The
.Fn MODULE
macro creates and initializes a
.Vt modinfo_t
structure.
The
.Fa class
argument identifies the class of module, and must be one of the following
(note that
.Dv MODULE_CLASS_ANY
should not be used here):
.Bl -tag -width MODULE_CLASS_SECMODEL -offset indent
.It Dv MODULE_CLASS_VFS
The module provide a virtual file system - see
.Xr vfs 9
.It Dv MODULE_CLASS_DRIVER
The module is a device driver - see
.Xr driver 9
.It Dv MODULE_CLASS_EXEC
The module provides an alternate execution environment - see the various
.Dv COMPAT_xxx
options in
.Xr options 4
.It Dv MODULE_CLASS_SECMODEL
The module provides a security model - see
.Xr secmodel 9
.It Dv MODULE_CLASS_BUFQ
The module provides a buffer queue strategy - see
.Xr bufq 9
.It Dv MODULE_CLASS_MISC
The module provides miscellaneous kernel services
.El
.Pp
The
.Fa name
argument provides the name of the module.
Loaded modules, including those that are built-in to the kernel, must all
have unique names.
.Pp
The
.Fa required
argument is a quoted string containing a comma-separated list of module
names that are required by this module.
The list must not contain any white-space.
When a module is loaded, all of its required modules are auto-loaded and
initialized before the module itself is loaded.
Loading of required modules is a recursive operation.
.Pp
If there are no required modules, this argument should be specified as
.Dv NULL .
.Pp
In addition to the explicit arguments, the
.Fn MODULE
macro creates a reference to the module's
.Fn modcmd
function.
This function is defined as:
.Bl -tag -width modcmd -offset indent
.It Ft modcmd_t
.Fn xxx_modcmd "modcmd_t cmd" "void *data"
.El
.Pp
(where xxx is the name of the module, from the
.Dv MODULE
macro).
.Pp
The
.Fa cmd
argument requests one of the following operations:
.Bl -tag -width MODULE_CMD_AUTOUNLOAD -offset indent
.It Dv MODULE_CMD_INIT
Perform module-specific initialization when the module is loaded.
.It Dv MODULE_CMD_FINI
Perform module-specific clean-up before the module is unloaded.
.It Dv MODULE_CMD_AUTOUNLOAD
Notify the module that it is about to be unloaded.
.It Dv MODULE_CMD_STAT
Request the module to provide status information (not currently implemented).
.El
.Pp
All modules'
.Fn modcmd
functions must implement the
.Dv MODULE_CMD_INIT
and
.Dv MODULE_CMD_FINI
commands.
The other commands are optional,
and should return
.Er ENOTTY
if not implemented.
.Pp
For the
.Dv MODULE_CMD_INIT
command, the
.Fa data
argument is used to pass a pointer to the module's
.Xr prop_dictionary 3 .
For the
.Dv MODULE_CMD_STAT
command, the
.Fa data
argument points to a buffer where the status information should be placed.
.Pp
The __link_set mechanism is used to enable the
.Nm
subsystem to locate the
.Vt modinfo_t
structure.
.It Fn module_load "name" "flags" "props" "class"
Load a module, link it into the running kernel, and call the module's
.Fn modcmd
routine with a
.Fa cmd
argument of
.Dv MODULE_CMD_INIT .
If the specified module requires other modules, they are loaded first; if
any required module cannot be loaded or if any of their
.Fn modcmd
control routines returns a non-zero status, loading of this module and
the specific required module will fail.
The required modules are marked for automatic unloading.
Thus, if the loading of the module failed, the required modules will
be automatically unloaded after a short delay.
.Pp
The loader will look first for a built-in module with the specified
.Fa name
that has not been disabled (see
.Fn module_unload
below).
If a built-in module with that
.Fa name
is not found, the list of modules prepared by the boot loader is searched.
If the named module is still not found, an attempt is made to locate the
module within the file system, provided it has been mounted by the
initialization code.
.Pp
The
.Fa flags
argument can include:
.Bl -tag -width MODCTL_LOAD_FORCE -offset indent
.It Dv MODCTL_NO_PROP
When loading a module from the file system, do not attempt to locate a
corresponding prop_dictionary file.
.It Dv MODCTL_LOAD_FORCE
Force loading of disabled built-in modules and modules built for a
different version of the operating system.
.El
.Pp
The
.Fa props
argument points to an externalized property list which is passed to the
module's
.Fn modcmd
routine.
If a module is being loaded from the file system, and the
.Dv MODCTL_NO_PROP
flag is not set, the system searches for a file with the same name as the
module file, but with the suffix
.Dq Pa .plist .
If this file is found, the prop_dictionary it contains is loaded and
merged with the prop_dictionary from the
.Fa props
argument.
.Pp
The
.Fa class
argument can be any of:
.Pp
.Bl -tag -width MODULE_CLASS_SECMODEL -offset indent -compact
.It Dv MODULE_CLASS_ANY
.It Dv MODULE_CLASS_DRIVER
Device driver
.It Dv MODULE_CLASS_EXEC
Executable image handler
.It Dv MODULE_CLASS_MISC
Miscellaneous module
.It Dv MODULE_CLASS_SECMODEL
Security model (see
.Xr secmodel 9
for more details)
.It Dv MODULE_CLASS_VFS
Virtual file system
.El
.Pp
If the class is not
.Dv MODULE_CLASS_ANY ,
the class of the module being loaded
must match the requested
.Fa class .
Except when verifying a module's class when it is being loaded, module
classes other than
.Dv MODULE_CLASS_SECMODEL
are transparent to the module subsystem.
They are provided only for the benefit of the subsystem's clients.
Modules with class
.Dv MODULE_CLASS_SECMODEL
are automatically registered with
.Fn secmodel_register
after being successfully loaded, and automatically deregistered with
.Fn secmodel_deregister
when being unloaded.
.Pp
The
.Fn module_load
routine is primarily intended as the implementation of the
.Dv MODCTL_LOAD
option of the
.Xr modctl 2
system call.
.It Fn module_autoload "name" "class"
Auto-load a module, making it available for automatic unloading.
The
.Fa name
and
.Fa class
arguments are the same as for the
.Fn module_load
routine.
.Pp
The module subsystem uses a kernel thread to attempt to automatically
unload modules a short time (currently, 10 seconds) after being loaded by
.Fn module_autoload .
Before the module is unloaded by this thread, its
.Fn modcmd
is called with the
.Fa cmd
argument specified as
.Dv MODULE_CMD_AUTOUNLOAD .
A module can prevent itself from being unloaded by returning a non-zero
value.
Exception: If
.Li kern.module.autounload_unsafe
is set, a module that returns
.Er ENOTTY ,
meaning it does not understand the command, may still be autounloaded.
.Pp
The
.Fn module_autoload
function is intended for use by kernel components to locate and load optional
system components.
The function is also used to load modules that are required by other modules.
.Pp
The directory from which the module is loaded will be searched for a file
with the same name as the module file, but with the suffix
.Dq Pa .plist .
If this file is found, the prop_dictionary it contains will be loaded and
passed to the module's
.Fn modcmd
routine.
If this prop_dictionary contains a
.Dq Pa noautoload
property which is set to
.Dq Pa true
then the system will refuse to load the module.
.It Fn module_unload "name"
Unload a module.
If the module's reference count is non-zero, the function returns
.Er EBUSY .
Otherwise, the module's
.Fn modcmd
routine is called with a
.Fa cmd
argument of
.Dv MODULE_CMD_FINI .
If the
.Fn modcmd
routine returns with an error, then the error is returned to the caller
otherwise the module is unloaded.
.Pp
The reference counts of all modules that were required by this module are
decremented, but the required modules are not unloaded by the call to
.Fn module_unload .
Instead, the required modules may be unloaded by subsequent calls to
.Fn module_unload .
.Pp
Unloading a built-in module causes the module to be marked as disabled.
This prevents the module from being re-loaded, except by the
.Fn module_load
function with the
.Fa flags
argument set to
.Dv MODULE_FORCE_LOAD .
.Pp
The
.Fn module_unload
function may be called by the
.Xr modctl 2
system call, by the module subsystem's internal auto-unload thread, or by
other kernel facilities.
Generally, other kernel facilities should not be calling this function.
.It Fn module_init_class "class"
Load and initialize all available modules of the specified
.Fa class .
Any built-in modules that have not been disabled, and any modules provided
by the boot loader are loaded.
.It Fn module_hold "module"
Increment the reference count of a module.
A module cannot be unloaded if its reference count is non-zero.
.It Fn module_rele "module"
Decrement the reference count of a module.
.It Fn module_find_section "name" "addr" "size"
Find the start address and size of linker section
.Ar name
within a module.
The miniroot module uses this routine to find the address and size of the
embedded file system image.
This routine can only examine the linker data for the module that is
currently being initialized; it cannot examine data for any other module.
.It Fn module_kernel "void"
Returns a pointer to a
.Ft module_t
structure describing the kernel module.
.It Fn module_name module
Returns a pointer to the module's name.
.It Fn module_source module
Returns the source of the module, one of
.Dv MODULE_SOURCE_KERNEL ,
.Dv MODULE_SOURCE_BOOT ,
or
.Dv MODULE_SOURCE_FILESYS .
.It Fn module_init "void"
Initialize the module subsystem.
Creates and initializes various data structures, locates all built-in
modules, and establishes the sub-system's
.Xr sysctl 8
tree.
.Fn module_init
is called early in system initialization to facilitate use of security model
modules.
.It Fn module_start_unload_thread "void"
Create the thread that attempts to automatically unload modules that were
loaded via the
.Fn module_autoload
routine.
The function is called only once,
after the scheduler and timer functions are initialized.
.It Fn module_builtin_require_force "void"
Mark as "disabled" any built-in modules that have not been successfully
initialized.
Modules marked "disabled" can only be loaded if the
.Dv MODCTL_LOAD_FORCE
is specified.
.Fn module_builtin_require_force
is called near the end of system initialization, after the
.Xr init 8
process is created.
.It Fn module_load_vfs_init "void"
The module subsystem is initialized early, long before any file systems
are available.
After the root file system is mounted,
.Fn module_load_vfs_init "void"
is used to enable loading modules from the file system.
Until this routine is called, modules can only be loaded if they were
built-in to the kernel image or provided by the boot loader.
.It Fn module_register_callbacks "void (*load)(struct module *)" \
"void (*unload)(struct module *)"
Register a new set of callbacks.
The
.Fa load
callback is invoked after any module (including this module) is
successfully loaded; the
.Fa unload
callback is invoked before any module is unloaded.
Each load or unload event can result in multiple invocations of the
callback routines.
An opaque cookie is returned which can be passed to
.Fn module_unregister_callbacks .
.It Fn module_unregister_callbacks "void *opaque"
Unregister a set of callback routines previously registered with
.Fn module_register_callbacks .
The
.Fa opaque
argument should be the return value from the previous
.Fn module_register_callbacks
call.
.It Fn module_specific_key_create "specificdata_key_t *keyp" \
"specificdata_dtor_t dtor"
Creates a new specificdata_key for use within the
.Nm
domain.
The key identifier is returned in
.Fa keyp .
.It Fn module_specific_key_delete "specificdata_key_t key"
Deletes the specified specificdata_key
.Fa key
from the
.Nm
domain.
.It Fn module_getspecific "module_t *mod" "specificdata_key_t key"
Retrieves the value associated with
.Fa key
from module
.Fa mod .
.It Fn module_setspecific "module_t *mod" "specificdata_key_t key" "void *data"
Stores
.Fa data
as the value associated with
.Fa key
for module
.Fa mod .
.El
.Sh PROGRAMMING CONSIDERATIONS
The module subsystem is designed to be called recursively, but only within
a single LWP.
This permits one module's
.Fn modcmd
routine to load or unload other modules.
.Pp
Additional considerations:
.Bl -bullet -offset indent
.It
A module is not permitted to load or unload itself.
Attempts to load or unload a module from within its own
.Fn modcmd
routine will fail with
.Er EEXIST
or
.Er EBUSY ,
respectively.
.It
Although a module can be loaded by using either
.Fn module_load
or
.Fn module_autoload ,
it is not possible for the module's
.Fn modcmd
routine to distinguish between the two methods.
Any module which needs to ensure that it does not get auto-unloaded must
either handle the
.Dv MODULE_CMD_AUTOUNLOAD
command in its
.Fn modcmd
routine, or use
.Fn module_hold
to increment its reference count.
Note however that modules loaded manually with
.Xr modload 8
are never auto-unloaded.
.El
.Sh EXAMPLES
A set of example modules is available in the
.Pa src/sys/modules/examples
directory hierarchy.
.Sh CODE REFERENCES
The core of the kernel module implementation is in
.Pa sys/kern/kern_module.c
and
.Pa sys/kern/kern_module_vfs.c .
.Pp
The routines for linking the module are in
.Pa sys/kern/subr_kobj.c .
.Pp
The routines for reading a module from the file system are in
.Pa sys/kern/subr_kobj_vfs.c .
.Pp
The header file
.In sys/sys/module.h
describes the public interface.
.Pp
In addition, each architecture is expected to provide
.Fn kobj_machdep ,
.Fn kobj_reloc ,
and
.Fn module_init_md .
.Fn kobj_machdep
is for any machine dependent actions, such as flushing caches, that are
needed when a module is loaded or unloaded.
.Fn kobj_reloc
deals with resolution of relocatable symbols.
.Fn module_init_md
is for finding modules passed in by the boot loader.
.Sh SEE ALSO
.Xr modctl 2 ,
.Xr module 7 ,
.Xr specificdata 9 ,
.Xr intro 9lua
.Sh HISTORY
The kernel module subsystem first appeared in
.Nx 5.0 .
It replaces the
.Dq LKM
subsystem from earlier releases.
.Sh AUTHORS
.An -nosplit
The
.Nm
system was written by
.An Andrew Doran Aq Mt ad@NetBSD.org .
This manual page was written by
.An Paul Goyette Aq Mt pgoyette@NetBSD.org .