CodeVetter · Repo Unpack · Data flow
torvalds/linux
Data enters through arch entry code (syscalls, interrupts, faults), is validated at each layer boundary, and flows through generic frameworks — VFS for files, socket layer for network, the block layer for storage, page-fault machinery for memory. Ownership is layered: user buffers are copied at syscall edges (access_ok, copy_struct_from_user), VFS resolves paths through the dentry/inode caches into struct file, LSM hooks interpose at every security-relevant hop, and the scheduler/RCU control when shared state may be mutated or reclaimed.
- Boot parameter flow: arch code fills boot_command_line; start_kernel calls setup_command_line then parse_early_param (walking __setup_start..__setup_end obs_kernel_param entries via do_early_param) and parse_args over the __param section; unknown options after '--' become init's argv via set_init_arg.
- open(2) data flow: sys_openat -> do_sys_open -> do_sys_openat2 (build_open_flags) -> do_file_open -> path_openat, which calls path_init, loops link_path_walk + open_last_lookups, then do_open; the resulting struct file is installed as an fd via FD_ADD.
- Path lookup runs lock-free RCU mode first (LOOKUP_RCU) and escalates: path_openat retries ref-walked on -ECHILD and again with LOOKUP_REVAL on -ESTALE; -EOPENSTALE from a filesystem is translated to -ECHILD/-ESTALE to trigger the retry ladder.
- Permission checking during lookup: inode_permission() -> do_inode_permission() applies POSIX mode/ACL checks, then devcgroup_inode_permission (device cgroup) and finally security_inode_permission (LSM) — three stacked authorization layers per path component.
- read(2) data flow: sys_read -> ksys_read looks up the fd's struct file, vfs_read validates FMODE_READ/FMODE_CAN_READ and access_ok on the user buffer, calls rw_verify_area, then f_op->read or new_sync_read(f_op->read_iter); on success fsnotify_access() and add_rchar/inc_syscr update accounting.
- clone/fork data flow: sys_clone3 -> clone3_args_valid -> kernel_clone normalizes flags (CLONE_EMPTY_MNTNS implies CLONE_NEWNS; CLONE_PIDFD vs CLONE_PARENT_SETTID exclusion), copy_process duplicates the task (dup_task_struct -> sched_fork -> copy_thread), then wake_up_new_task enqueues the child and optional PTRACE_EVENT_* reports fire.
- Page-fault data flow: arch fault handler -> handle_mm_fault checks arch_vma_access_permitted, calls mem_cgroup_enter_user_fault for user faults, routes to hugetlb_fault or __handle_mm_fault -> handle_pte_fault -> do_anonymous_page (anon) or do_fault -> __do_fault (vm_ops->fault for file-backed); VM_DROPPABLE VMAs get non-fatal OOM handling.
- Module-load data flow: finit_module reads the fd's ELF image, may_init_module enforces CAP_SYS_MODULE/modules_disabled, load_module calls module_sig_check, elf_validity_ehdr (magic/type/machine validation) and check_modinfo (vermagic, livepatch, retpoline), then do_init_module runs the module's init function.
- Socket creation flow: sys_socket -> __sys_socket_create -> __sock_create checks the protocol family, calls security_socket_create before allocation and security_socket_post_create after the family's create op runs; __sys_socket_file wraps the socket in a file/fd for the syscall ABI.
- io_uring submission flow: io_uring_enter -> io_submit_sqes pulls SQEs from the shared ring, io_issue_sqe reads io_issue_defs[req->opcode] for per-op flags and calls the opcode's issue handler; completion state is written back to the shared CQ ring.
- Context-switch flow: schedule() -> __schedule() takes rq->lock, updates rq clock, calls pick_next_task() (class order: stop -> deadline -> rt -> fair/ext -> idle), then context_switch() swaps the mm and register state; preemption is driven by TIF_NEED_RESCHED set in sched_tick.
- Usermode-helper flow: call_usermodehelper_exec_async runs inside a user_mode_thread, intersects the new cred's capabilities with usermodehelper_bset/usermodehelper_inheritable, then kernel_execve's the helper binary (e.g. modprobe, hotplug) — a kernel-to-userspace privilege boundary.