{
	"id": "f35ea69a-0a19-44fe-9c60-a6c4f762fc1c",
	"created_at": "2026-04-06T00:10:53.897969Z",
	"updated_at": "2026-04-10T03:24:17.806334Z",
	"deleted_at": null,
	"sha1_hash": "970bdf300d06a50f418198c81708f2cb1a283d86",
	"title": "How To Insert And Remove LKMs",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 86120,
	"plain_text": "How To Insert And Remove LKMs\r\nArchived: 2026-04-05 22:09:07 UTC\r\nThe basic programs for inserting and removing LKMs are insmod and rmmod. See their man pages for details.\r\nInserting an LKM is conceptually easy: Just type, as superuser, a command like\r\ninsmod serial.o\r\n(serial.o contains the device driver for serial ports (UARTs)).\r\nHowever, I would be misleading you if I said the command just works. It is very common, and rather maddening,\r\nfor the command to fail either with a message about a module/kernel version mismatch or a pile of unresolved\r\nsymbols.\r\nIf it does work, though, the way to prove to yourself that you know what you're doing is to look at\r\n/proc/modules as described in Section 5.5.\r\nNote that the examples in this section are from Linux 2.4. In Linux 2.6, the technical aspects of loading LKMs are\r\nconsiderably different, and the most visible manifestation of this is that the LKM file has a suffix of \".ko\" instead\r\nof \".o\". From the user point of view, it looks quite similar, though.\r\nNow lets look at a more difficult insertion. If you try\r\ninsmod msdos.o\r\nyou will probably get a raft of error messages like:\r\n msdos.o: unresolved symbol fat_date_unix2dos\r\n msdos.o: unresolved symbol fat_add_cluster1\r\n msdos.o: unresolved symbol fat_put_super\r\n ...\r\nThis is because msdos.o contains external symbol references to the symbols mentioned and there are no such\r\nsymbols exported by the kernel. To prove this, do a\r\ncat /proc/ksyms\r\nto list every symbol that is exported by the kernel (i.e. available for binding to LKMs). You will see that\r\n'fat_date_unix2dos' is nowhere in the list.\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 1 of 9\n\n(In Linux 2.6, there is no /proc/ksyms. Use /proc/kallsyms instead; the format is like the output of nm: look\r\nfor symbols labelled \"t\").\r\nHow do you get it into the list? By loading another LKM, one which defines those symbols and exports them. In\r\nthis case, it is the LKM in the file fat.o. So do\r\n insmod fat.o\r\nand then see that \"fat_date_unix2dos\" is in /proc/ksyms. Now redo the\r\ninsmod msdos.o\r\nand it works. Look at /proc/modules and see that both LKMs are loaded and one depends on the other:\r\nmsdos 5632 0 (unused)\r\nfat 30400 0 [msdos]\r\nHow did I know fat.o was the module I was missing? Just a little ingenuity. A more robust way to address this\r\nproblem is to use depmod and modprobe instead of insmod, as discussed below.\r\nWhen your symbols look like \"fat_date_unix2dos_R83fb36a1\", the problem may be more complex than just\r\ngetting prerequisite LKMs loaded. See Section 6.\r\nWhen the error message is \"kernel/module version mismatch,\" see Section 6.\r\nOften, you need to pass parameters to the LKM when you insert it. For example, a device driver wants to know\r\nthe address and IRQ of the device it is supposed to drive. Or the network driver wants to know how much\r\ndiagnostic tracing you want it to do. Here is an example of that:\r\ninsmod ne.o io=0x300 irq=11\r\nHere, I am loading the device driver for my NE2000-like Ethernet adapter and telling it to drive the Ethernet\r\nadapter at IO address 0x300, which generates interrupts on IRQ 11.\r\nThere are no standard parameters for LKMs and very few conventions. Each LKM author decides what\r\nparameters insmod will take for his LKM. Hence, you will find them documented in the documentation of the\r\nLKM. This HOWTO also compiles a lot of LKM parameter information in Section 15. For general information\r\nabout LKM parameters, see Section 8.\r\nTo remove an LKM from the kernel, the command is like\r\nrmmod ne\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 2 of 9\n\nThere is a command lsmod to list the currently loaded LKMs, but all it does is dump the contents of\r\n/proc/modules, with column headings, so you may just want to go to the horse's mouth and forget about lsmod.\r\n5.1. Could Not Find Kernel Version...\r\nA common error is to try to insert an object file which is not an LKM. For example, you configure your kernel to\r\nhave the USB core module bound into the base kernel instead of generated as an LKM. In that case, you end up\r\nwith a file usbcore.o, which looks pretty much the same as the usbcore.o you would get if you built it as an\r\nLKM. But you can't insmod that file.\r\nSo do you get an error message telling you that you should have configured the kernel to make USB core function\r\nan LKM? Of course not. This is Unix, and explanatory error messages are seen as a sign of weakness. The error\r\nmessage is\r\n$ insmod usbcore.o\r\nusbcore.o: couldn't find the kernel version this module was compiled for\r\nWhat insmod is telling you is that it looked in usbcore.o for a piece of information any legitimate LKM would\r\nhave -- the kernel version with which the LKM was intended to be used -- and it didn't find it. We know now that\r\nthe reason it didn't find it is that the file isn't an LKM. See Section 10.2 for information on how you can see what\r\ninsmod is seeing and confirm that the file is not in fact an LKM.\r\nIf this is a module you created yourself with the intention of it being an LKM, the next question you have is: Why\r\nisn't an LKM? The most usual cause of this is that you did not include linux/module.h at the top of your source\r\ncode and/or did not define the MODULE\u003e macro. MODULE is intended to be set via the compile command (-DMODULE)\r\nand determine whether the compilation produces an LKM or an object file for binding into the base kernel. If your\r\nmodule is like most modern modules and can be built only as an LKM, then you should just define it in your\r\nsource code (#define MODULE) before you include include/module.h.\r\n5.2. What Happens When An LKM Loads\r\nSo you've successfully loaded an LKM, and verified that via /proc/modules. But how do you know it's working?\r\nThat's up to the LKM, and varies according to what kind of LKM it is, but here are some of the more common\r\nactions of an LKM upon being loaded.\r\nThe first thing a device driver LKM does after loading (which is what the module would do at boot time if it were\r\nbound into the base kernel) is usually to search the system for a device it knows how to drive. Just how it does this\r\nsearch varies from one driver to the next, and can usually be controlled by module parameters. But in any case, if\r\nthe driver doesn't find any device it is capable of driving, it causes the load to fail. Otherwise, the driver registers\r\nitself as the driver for a particular major number and you can start using the device it found via a device special\r\nfile that specifies that major number. It may also register itself as the handler for the interrupt level that the device\r\nuses. It may also send setup commands to the device, so you may see lights blink or something like that.\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 3 of 9\n\nYou can see that a device driver has registered itself in the file /proc/devices. You can see that the device driver\r\nis handling the device's interrupts in /proc/interrupts.\r\nA nice device driver issues kernel messages telling what devices it found and is prepared to drive. (Kernel\r\nmessages in most systems end up on the console and in the file /var/log/messages. You can also display recent\r\nones with the dmesg program). Some drivers, however, are silent. A nice device driver also gives you (in kernel\r\nmessages) some details of its search when it fails to find a device, but many just fail the load without explanation,\r\nand what you get is a list of guesses from insmod as to what the problem might have been.\r\nA network device (interface) driver works similarly, except that the LKM registers a device name of its choosing\r\n(e.g. eth0) rather than a major number. You can see the currently registered network device names in\r\n/proc/net/dev\r\nA filesystem driver, upon loading, registers itself as the driver for a filesystem type of a certain name. For\r\nexample, the msdos driver registers itself as the driver for the filesystem type named msdos. (LKM authors\r\ntypically name the LKM the same as the filesystem type it will drive).\r\n5.3. Intelligent Loading Of LKMs - Modprobe\r\nOnce you have module loading and unloading figured out using insmod and rmmod, you can let the system do\r\nmore of the work for you by using the higher level program modprobe. See the modprobe man page for details.\r\nThe main thing that modprobe does is automatically load the prerequisites of an LKM you request. It does this\r\nwith the help of a file that you create with depmod and keep on your system.\r\nExample:\r\nmodprobe msdos\r\nThis performs an insmod of msdos.o, but before that does an insmod of fat.o, since you have to have fat.o\r\nloaded before you can load msdos.o.\r\nThe other major thing modprobe does for you is to find the object module containing the LKM given just the\r\nname of the LKM. For example, modprobe msdos might load /lib/2.4.2-2/fs/msdos.o. In fact, modprobe's\r\nargument may be a totally symbolic name that you have associated with some actual module. For example,\r\nmodprobe eth0 loads the appropriate network device driver to create and drive your eth0 device, assuming you\r\nset that up properly in modules.conf. Check out the man pages for modprobe and the configuration file\r\nmodules.conf (usually /etc/modules.conf) for details on the search rules modprobe uses.\r\nmodprobe is especially important because it is by default the program that the kernel module loader uses to load\r\nan LKM on demand. So if you use automatic module loading, you will need to set up modules.conf properly or\r\nthings will not work. See Section 5.4.\r\ndepmod scans your LKM object files (typically all the .o files in the appropriate /lib/modules subdirectory)\r\nand figures out which LKMs prerequire (refer to symbols in) other LKMs. It generates a dependency file\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 4 of 9\n\n(typically named modules.dep), which you normally keep in /lib/modules for use by modprobe.\r\nYou can use modprobe to remove stacks of LKMs as well.\r\nVia the LKM configuration file (typically /etc/modules.conf), you can fine tune the dependencies and do other\r\nfancy things to control LKM selections. And you can specify programs to run when you insert and remove LKMs,\r\nfor example to initialize a device driver.\r\nIf you are maintaining one system and memory is not in short supply, it is probably easier to avoid modprobe and\r\nthe various files and directories it needs, and just do raw insmods in a startup script.\r\n5.4. Automatic LKM Loading and Unloading\r\n5.4.1. Automatic Loading\r\nYou can cause an LKM to be loaded automatically when the kernel first needs it. You do this with either the kernel\r\nmodule loader, which is part of the Linux kernel, or the older version of it, a kerneld daemon.\r\nAs an example, let's say you run a program that executes an open system call for a file in an MS-DOS filesystem.\r\nBut you don't have a filesystem driver for the MS-DOS filesystem either bound into your base kernel or loaded as\r\nan LKM. So the kernel does not know how to access the file you're opening on the disk.\r\nThe kernel recognizes that it has no filesystem driver for MS-DOS, but that one of the two automatic module\r\nloading facilities are available and uses it to cause the LKM to be loaded. The kernel then proceeds with the open.\r\nAutomatic kernel module loading is really not worth the complexity in most modern systems. It may make sense\r\nin a very small memory system, because you can keep parts of the kernel in memory only when you need them.\r\nBut the amount of memory these modules uses is so cheap today that you will normally be a lot better off just\r\nloading all the modules you might need via startup scripts and leaving them loaded.\r\nRed Hat Linux uses automatic module loading via the kernel module loader.\r\nBoth the kernel module loader and kerneld use modprobe, ergo insmod, to insert LKMs. See Section 5.3.\r\n5.4.1.1. Kernel Module Loader\r\nThere is some documentation of the kernel module loader in the file Documentation/kmod.txt in the Linux 2.4\r\nsource tree. This section is more complete and accurate than that file. You can also look at its source code in\r\nkernel/kmod.c.\r\nThe kernel module loader is an optional part of the Linux kernel. You get it if you select the CONFIG_KMOD\r\nfeature when you configure the kernel at build time.\r\nWhen a kernel that has the kernel module loader needs an LKM, it creates a user process (owned by the superuser,\r\nthough) that executes modprobe to load the LKM, then exits. By default, it finds modprobe as /sbin/modprobe,\r\nbut you can set up any program you like as modprobe by writing its file name to /proc/sys/kernel/modprobe.\r\nFor example:\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 5 of 9\n\n# echo \"sbin/mymodprobe\" \u003e/proc/sys/kernel/modprobe\r\nThe kernel module loader passes the following arguments to the modprobe: Argument Zero is the full file name\r\nof modprobe. The regular arguments are -s, -k, and the name of the LKM that the kernel wants. -s is the user-hostile form of --syslog; -k is the cryptic way to say --autoclean. I.e. messages from modprobe will go to\r\nsyslog and the loaded LKM will have the \"autoclean\" flag set.\r\nThe most important part of the modprobe invocation is, of course, the module name. Note that the \"module\r\nname\" argument to modprobe is not necessarily a real module name. It is often a symbolic name representing the\r\nrole that module plays and you use an alias statement in modules.conf to tell what LKM gets loaded. For\r\nexample, if your Ethernet adapter requires the 3c59x LKM, you would have probably need the line\r\nalias eth0 3c59x\r\nin /etc/modules.conf. Here is what the kernel module loader uses for a module name in some of the more\r\npopular cases (there are about 20 cases in which the kernel calls on the kernel module loader to load a module):\r\nWhen you try access a device and no device driver has registered to serve that device's major number, the\r\nkernel requests the module by the name block-major-N or char-major-N where N is the major number in\r\ndecimal without leading zeroes.\r\nWhen you try to access a network interface (maybe by running ifconfig against it) and no network device\r\ndriver has registered to serve an interface by that name, the kernel requests the module named the same as\r\nthe interface name (e.g. eth0). This applies to drivers for non-physical interfaces such as ppp0 as well.\r\nWhen you try to access a socket in a protocol family which no protocol driver has registered to drive, the\r\nkernel requests the module named net-pf-N, where N is the protocol family number (in decimal without\r\nleading zeroes).\r\nWhen you try to NFS export a directory or otherwise access the NFS server via the NFS system call, the\r\nkernel requests the module named nfsd.\r\nThe ATA device driver (named ide) loads the relevant drivers for classes of ATA devices by the names:\r\nide-disk, ide-cd, ide-floppy, ide-tape, and ide-scsi.\r\nThe kernel module loader runs modprobe with the following environment variables (only): HOME=/;\r\nTERM=linux; PATH=/sbin:/usr/sbin:/bin:/usr/bin.\r\nThe kernel module loader was new in Linux 2.2 and was designed to take the place of kerneld. It does not,\r\nhowever, have all the features of kerneld.\r\nIn Linux 2.2, the kernel module loader creates the above mentioned process directly. In Linux 2.4, the kernel\r\nmodule loader submits the module loading work to Keventd and it runs as a child process of Keventd.\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 6 of 9\n\nThe kernel module loader is a pretty strange beast. It violates layering as Unix programmers generally understand\r\nit and consequently is inflexible, hard to understand, and not robust. Many system designers would bristle just at\r\nthe fact that it has the PATH hardcoded. You may prefer to use kerneld instead, or not bother with automatic\r\nloading of LKMs at all.\r\n5.4.1.2. Kerneld\r\nkerneld is explained at length in the Kerneld mini-HOWTO, available from the Linux Documentation Project.\r\nkerneld is a user process, which runs the kerneld program from the modutils package. kerneld sets up an IPC\r\nmessage channel with the kernel. When the kernel needs an LKM, it sends a message on that channel to kerneld\r\nand kerneld runs modprobe to load the LKM, then sends a message back to the kernel to say that it is done.\r\n5.4.2. Automatic Unloading - Autoclean\r\n5.4.2.1. The Autoclean Flag\r\nEach loaded LKM has an autoclean flag which can be set or unset. You control this flag with parameters to the\r\ninit_module system call. Assuming you do that via insmod, you use the --autoclean option.\r\nYou can see the state of the autoclean flag in /proc/modules. Any LKM that has the flag set has the legend\r\nautoclean next to it.\r\n5.4.2.2. Removing The Autoclean LKMs\r\nThe purpose of the autoclean flag is to let you automatically remove LKMs that haven't been used in a while\r\n(typically 1 minute). So by using automatic module loading and unloading, you can keep loaded only parts of the\r\nkernel that are presently needed, and save memory.\r\nThis is less important than it once was, with memory being much cheaper. If you don't need to save memory, you\r\nshouldn't bother with the complexity of module loader processes. Just load everything you might need via an\r\ninitialization script and keep it loaded.\r\nThere is a form of the delete_module system call that says, \"remove all LKMs that have the autoclean flag set\r\nand haven't been used in a while.\" Kerneld typically calls this once per minute. You can call it explicitly with an\r\nrmmod --all command.\r\nAs the kernel module loader does not do any removing of LKMs, if you use that you might want to have a cron\r\njob that does a rmmod --all periodically.\r\n5.5. /proc/modules\r\nTo see the presently loaded LKMs, do\r\ncat /proc/modules\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 7 of 9\n\nYou see a line like\r\nserial 24484 0\r\nThe left column is the name of the LKM, which is normally the name of the object file from which you loaded it,\r\nminus the \".o\" suffix. You can, however, choose any name you like with an option on insmod.\r\nThe \"24484\" is the size in bytes of the LKM in memory.\r\nThe \"0\" is the use count. It tells how many things presently depend on the LKM being loaded. Typical \"things\" are\r\nopen devices or mounted fileystems. It is important because you cannot remove an LKM unless the use count is\r\nzero. The LKM itself maintains this count, but the module manager uses it to decide whether to permit an unload.\r\nThere is an exception to the above description of the use count. You may see -1 in the use count column. What that\r\nmeans is that this LKM does not use use counts to determine when it is OK to unload. Instead, the LKM has\r\nregistered a subroutine that the module manager can call that will return an indication of whether or not it is OK to\r\nunload the LKM. In this case, the LKM ought to provide you with some custom interface, and some\r\ndocumentation, to determine when the LKM is free to be unloaded.\r\nDo not confuse use count with \"dependencies\", which are described below.\r\nHere is another example, with more information:\r\nlp 5280 0 (unused)\r\nparport_pc 7552 1\r\nparport 7600 1 [lp parport_pc]\r\nThe stuff in square brackets (\"[lp parport_pc]\") describes dependencies. Here, the modules lp and parport_pc\r\nboth refer to addresses within module parport (via external symbols that parport exports). So lp and\r\nparport_pc are \"dependent\" on (and are \"dependencies of\") parport.\r\nYou cannot unload an LKM that has dependencies. But you can remove those dependencies by unloading the\r\ndependent LKMs.\r\nThe \"(unused)\" legend means the LKM has never been used, i.e. it has never been in a state where it could not be\r\nunloaded. The kernel tracks this information for one simple reason: to assist in automatic LKM unloading policy.\r\nIn a system where LKMs are loaded and unloaded automatically (see Section 5.4), you don't want to automatically\r\nload an LKM and then, before the guy who needed it loaded has a chance to use it, unload it because it is not in\r\nuse.\r\nHere is something you won't normally see:\r\nmydriver 8154 0 (deleted)\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 8 of 9\n\nThis is an LKM that is in \"deleted\" state. It's something of a misnomer -- what it means is that the LKM is in the\r\nprocess of being unloaded. You can no longer load LKMs that depend on it, but it's still present in the system.\r\nUnloading an LKM is usually close to instantaneous, so if you see this status, you probably have a broken LKM.\r\nIts cleanup routine probably got into an infinite loop or stall or crashed (causing a kernel oops). If that's the case,\r\nthe only way to clear this status is to reboot.\r\nThere are similar statuses \"initializing\" and \"uninitialized\".\r\nThe legend \"(autoclean)\" refers to the autoclean flag, discussed in Section 5.4.\r\n5.6. Where Are My LKM Files On My System?\r\nThe LKM world is flexible enough that the files you need to load could live just about anywhere on your system,\r\nbut there is a convention that most systems follow: The LKM .o files are in the directory /lib/modules, divided\r\ninto subdirectories. There is one subdirectory for each version of the kernel, since LKMs are specific to a kernel\r\n(see Section 6). Each subdirectory contains a complete set of LKMs.\r\nThe subdirectory name is the value you get from the uname --release command, for example 2.2.19. Section 6.3\r\ntells how you control that value.\r\nWhen you build Linux, a standard make modules and make modules_install should install all the LKMs that are\r\npart of Linux in the proper release subdirectory.\r\nIf you build a lot of kernels, another organization may be more helpful: keep the LKMs together with the base\r\nkernel and other kernel-related files in a subdirectory of /boot. The only drawback of this is that you cannot have\r\n/boot reside on a tiny disk partition. In some systems, /boot is on a special tiny \"boot partition\" and contains only\r\nenough files to get the system up to the point that it can mount other filesystems.\r\nSource: https://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nhttps://tldp.org/HOWTO/Module-HOWTO/x197.html\r\nPage 9 of 9",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://tldp.org/HOWTO/Module-HOWTO/x197.html"
	],
	"report_names": [
		"x197.html"
	],
	"threat_actors": [
		{
			"id": "eb3f4e4d-2573-494d-9739-1be5141cf7b2",
			"created_at": "2022-10-25T16:07:24.471018Z",
			"updated_at": "2026-04-10T02:00:05.002374Z",
			"deleted_at": null,
			"main_name": "Cron",
			"aliases": [],
			"source_name": "ETDA:Cron",
			"tools": [
				"Catelites",
				"Catelites Bot",
				"CronBot",
				"TinyZBot"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434253,
	"ts_updated_at": 1775791457,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/970bdf300d06a50f418198c81708f2cb1a283d86.pdf",
		"text": "https://archive.orkl.eu/970bdf300d06a50f418198c81708f2cb1a283d86.txt",
		"img": "https://archive.orkl.eu/970bdf300d06a50f418198c81708f2cb1a283d86.jpg"
	}
}