CodeVetter · Repo Unpack · Extension points
torvalds/linux
The kernel is extension-by-design: initcall levels order boot-time registration, LSM hook tables add security policies, file_operations/inode_operations/super_operations vtables plug filesystems, struct device_driver + bus match functions plug drivers, register_filesystem adds filesystems, the syscall .tbl files add syscalls, module_init/module_exit wrap loadable code, eBPF program types (including sched_ext and bpf_struct_ops) let userspace extend behavior at runtime, and io_uring opcodes extend async I/O. Rust extensions go through the kernel crate + #[module] proc-macro.
- initcall levels are the primary boot-time extension mechanism: __define_initcall emits entries into named linker sections (early, core, postcore, arch, subsys, fs, device, late, plus *_sync variants) consumed by do_initcalls in order.
- New security modules plug in via the LSM framework: hook implementations are registered into lists declared in include/linux/lsm_hook_defs.h, dispatched by call_int_hook/call_void_hook in security/security.c, and initialized through the staged security_initcall_* initcalls in security/lsm_init.c.
- Filesystems extend via struct file_system_type registered with register_filesystem()/unregister_filesystem() in fs/filesystems.c, then implement super_operations/inode_operations/file_operations that VFS calls through f_op->read/write_iter/open.
- Drivers plug into the driver model: bus_type match functions pair devices with device_driver structs, and driver_probe_device -> really_probe invokes drv->probe plus sysfs integration (driver_sysfs_add).
- Loadable modules extend the kernel at runtime: module_init maps to device_initcall for built-ins or runs in do_init_module for loaded modules; check_modinfo enforces vermagic/license/livepatch metadata compatibility.
- eBPF is the runtime extension fabric: bpf(2) loads verified programs/maps (kernel/bpf/syscall.c), attachable to kprobes/tracepoints/LSM (bpf_lsm.c), and sched_ext (kernel/sched/ext/) exposes the CPU scheduler itself to BPF policies.
- New syscalls are added by a row in the per-arch .tbl files (e.g. arch/x86/entry/syscalls/syscall_64.tbl) plus a SYSCALL_DEFINE body; generated asm/syscalls_64.h feeds both the x64_sys_call switch and sys_call_table[].
- io_uring opcodes extend through the io_issue_defs[] table in io_uring/opdef.c: each IORING_OP_* entry declares prep/issue handlers and capability flags, with BUILD_BUG_ON/early-init validation that every opcode has both handlers.
- Rust modules are wired by the kernel crate + macros: rust/kernel/ exposes safe wrappers (driver.rs, device.rs, fs.rs) and rust/macros/module.rs generates module metadata; samples/rust/*.rs (rust_minimal.rs, rust_driver_i2c.rs, rust_driver_pci.rs, ...) are the canonical examples.
- Kconfig + Kbuild wiring is the build-time extension pattern: add a config FOO to a subsystem Kconfig (sourced via the top-level Kconfig chain) and gate objects with obj-$(CONFIG_FOO) in the directory Makefile.
- sysctl knobs are registered through kernel/sysctl.c tables, with subsystem-specific registrations such as mm/hugetlb_sysctl.c exposing runtime-tunable parameters under /proc/sys.
- kselftest suites extend by adding a directory under tools/testing/selftests and a TARGETS += entry in the top Makefile; each suite emits KTAP via kselftest/ktap_helpers.sh/ksft.py.