kernel/livepatch/transition.c

Source file repositories/reference/linux-study-clean/kernel/livepatch/transition.c

File Facts

System
Linux kernel
Corpus path
kernel/livepatch/transition.c
Extension
.c
Size
20868 bytes
Lines
732
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

/* Called from copy_process() during fork */
void klp_copy_process(struct task_struct *child)
{

	/*
	 * The parent process may have gone through a KLP transition since
	 * the thread flag was copied in setup_thread_stack earlier. Bring
	 * the task flag up to date with the parent here.
	 *
	 * The operation is serialized against all klp_*_transition()
	 * operations by the tasklist_lock. The only exceptions are
	 * klp_update_patch_state(current) and __klp_sched_try_switch(), but we
	 * cannot race with them because we are current.
	 */
	if (test_tsk_thread_flag(current, TIF_PATCH_PENDING))
		set_tsk_thread_flag(child, TIF_PATCH_PENDING);
	else
		clear_tsk_thread_flag(child, TIF_PATCH_PENDING);

	child->patch_state = current->patch_state;
}

/*
 * Drop TIF_PATCH_PENDING of all tasks on admin's request. This forces an
 * existing transition to finish.
 *
 * NOTE: klp_update_patch_state(task) requires the task to be inactive or
 * 'current'. This is not the case here and the consistency model could be
 * broken. Administrator, who is the only one to execute the
 * klp_force_transitions(), has to be aware of this.
 */
void klp_force_transition(void)
{
	struct klp_patch *patch;
	struct task_struct *g, *task;
	unsigned int cpu;

	pr_warn("forcing remaining tasks to the patched state\n");

	read_lock(&tasklist_lock);
	for_each_process_thread(g, task)
		klp_update_patch_state(task);
	read_unlock(&tasklist_lock);

	for_each_possible_cpu(cpu)
		klp_update_patch_state(idle_task(cpu));

	/* Set forced flag for patches being removed. */
	if (klp_target_state == KLP_TRANSITION_UNPATCHED)
		klp_transition_patch->forced = true;
	else if (klp_transition_patch->replace) {
		klp_for_each_patch(patch) {
			if (patch != klp_transition_patch)
				patch->forced = true;
		}
	}
}

Annotation

Implementation Notes