If this is a device on which you can use ioctl() to configure, why is
it not stored under sys/dev and why is it not included in kernel config
with pseudo-device directive (and corresponding files.kern changes)?
The module should be MODULE_CLASS_DRIVER. And there should be a
sys/module/fault/Makefile to build the module, along with changes to
sys/module/Makefile (to descend into the fault directory) and to
src/distrib/sets/lists/modules/mi (for new files). The module init
code should also have appropriate config_{init,fini}_component()
calls for inserting the device into the autoconfig database.
Finally, it would be nice if it were possible to unload the module,
although I understand why it might be difficult to ensure that it is
safe to remove.
On Sat, 8 Feb 2020, Maxime Villard wrote:
[I am not subscribed to this list, so if you want to answer, make sure to CC
me]
In order to explore error branches, and to test the kernel's ability to cope
with failures, it is often necessary to hard-trigger such failures.
Here is an implementation [1] for fault(4), a driver that allows to trigger
failures in the kernel. A similar driver exists in Linux.
The fault_inject() function decides whether to return true or false,
depending
on parameters configurable by userland via ioctls on /dev/fault. The caller
of
this function should then error out depending on the return value. Typically:
whatever_subsystem()
{
...
if (fault_inject())
return NULL; // means failure
...
return non_null; // means success
}
Several modes can be available, I have implemented one for now, the N-th
mode:
every N-th call to fault_inject (N being configurable) will make it return
true.
Several scopes are available: global (ie system-wide), or calling LWP.
Examples:
- mode=NTH scope=GLOBAL: every N-th call to fault_inject() in the whole
kernel
will return true, regardless of the LWP.
- mode=NTH scope=LWP: every N-th call to fault_inject() made by the LWP that
enabled the mode will return true. For the other LWPs, fault_inject()
always
returns false.
fault_inject() can be introduced in any place of interest. For now I added it
in pool_cache_get():
if (flags & PR_NOWAIT) {
if (fault_inject())
return NULL;
}
Running ATF with kASan+LOCKDEBUG+fault with {N=32 scope=GLOBAL} already gives
an instant crash:
kernel diagnostic assertion
"radix_tree_empty_tree_p(&pmap->pm_pvtree)"
failed: file ".../sys/arch/x86/x86/pmap.c"
Looks like radixtree.c doesn't handle allocation failures very well
somewhere.
fault(4) seems like the kind of feature that would be useful for
stress-testing
and fuzzing. As you can see in the diff, its code is extremely simple.
Maxime
[1] https://m00nbsd.net/garbage/fault/fault.diff
!DSPAM:5e3e9212102679617345149!
+--------------------+--------------------------+-----------------------+
| Paul Goyette | PGP Key fingerprint: | E-mail addresses: |
| (Retired) | FA29 0E3B 35AF E8AE 6651 | p...@whooppee.com |
| Software Developer | 0786 F758 55DE 53BA 7731 | pgoye...@netbsd.org |
+--------------------+--------------------------+-----------------------+