Linux kernel #
This list includes basic checks for Linux kernel drivers and modules.
- Check that all uses of data coming from the userspace are validated.
- Look for the
__usertag in the code. Not necessarily all userspace data is marked with the tag, but it is a good start. - Uses of
copy_from_user(to, from, size)should be validated:- The length should be validated correctly.
- There should be no uninitialized
toaddresses. - The low-level
__copy_from_userfunction should be used with theaccess_okidentifier.
- Look for the
- Check that uses of
copy_to_user(to, from, size)are validated.frommemory should be initialized (including the struct’s padding).
- Review uses of
user_access_{begin,end}.- These calls make kernel code disable/enable SMAP. Any code between these calls must be reviewed carefully.
- Review other userspace-to-kernel methods.
- At least the following functions should be reviewed:
get_user,strncpy_from_user,copy_struct_from_user,access_process_vm, andget_user_pages. - Review uses of explicitly unsafe functions such as
__put_userandunsafe_put_userwith extra care.
- At least the following functions should be reviewed:
- Check for instances in which the kernel fetches or copies memory from userspace twice instead of once, which results in TOCTOU (or double fetch) issues.
- This often happens when pre- or post-syscall hooks are involved.
- Review the codebase for pointer leaks.
- For example, use of the
%pformat string may leak kernel addresses. The mitigation for this particular issue is to usekptr_restrict. Developers should use the%pKor%pxformat strings.
- For example, use of the
- Check that file descriptors passed to userspace (with
fd_install, for example) are not used by the kernel anymore.- Userspace can call
closeordup2on the descriptor to make it point to a different file, and the kernel would then use a different file structure than the expected one, which may lead to issues like use after free.
- Userspace can call
- Check for uses of
strlen_userandstrnlen_user(which are used only in old kernels). These functions return the length including the nullbyte, which is different behavior from the userspacestrlenfunction and may be confusing. - Examine uses of
strncpy_from_user, as they may not null-terminate the destination string (same behavior as stdlibstrncpy). - Check that reference counting
is implemented correctly (
fget/fput,sock_hold/sock_put,get_pid_task/get_task_struct/put_task_struct,{get,put}_pid,d_find_alias/dget/dput, etc.).- There are no double decrements (causing use-after-free conditions).
- There are no missing increments (causing use-after-free conditions).
- There are no double increments (causing dangling objects).
- There are no missing decrements (causing dangling objects).
- The correct type is used for custom refcounters (
refcount_tversusatomic_t). - Return values of refcount-taking functions like
try_module_getare checked.
- Check that mutex locking is implemented correctly (
mutex_lock,spin_lock). - Check that the
__ro_after_initattribute is used for init-once variables. - Examine dynamic allocations to ensure they are correct.
- The right version of free is always used (e.g.,
kmalloc-kfreeversusvmalloc-vfree). - The return value is checked against
NULL. - Zeroing functions are used instead of allocation and
memset. - Oops is not possible between a stack-based allocation (
vmalloc) and corresponding free.
- The right version of free is always used (e.g.,
- Check that if a global initialization function (like
genl_register_familyandinit_module) allocates memory, the corresponding deinitialization function frees the memory. - For code that modifies protection of kernel memory mappings, check that any read-only pages, like syscall tables, stay read-only after the modification.
- Check that all interfaces (procfs entries, sysfs files, device files, ioctl and netlink operations, etc.) that allow administrative operations to be performed or sensitive data to be obtained (via pointers, configuration, etc.) require root user and relevant
capabilities.
- Low-privilege users can become root (users with UID 0) in their own namespace (e.g., inside a Docker container). Missing capability checks could allow root-owned procfs files to be accessed or kernel pointers to be leaked.
- Ensure capability checks for the correct process(es) are performed.
- For example, there should be capability checks not only of the calling process but also of the process that created a resource. See CVE-2023-2002 for more information.
- Check that custom filesystems (defined by the
file_system_typestruct) and files (defined by thefile_operationsstruct) have theownerfield set toTHIS_MODULE. - Use kernel-specific static analysis.
- The main tool is Coccinelle. Use it with rules from the Linux repo and the Coccinelle website (they must be downloaded manually).