security/landlock/task.c

Source file repositories/reference/linux-study-clean/security/landlock/task.c

File Facts

System
Linux kernel
Corpus path
security/landlock/task.c
Extension
.c
Size
12355 bytes
Lines
464
Domain
Core OS
Bucket
Security And Isolation
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

landlock_log_denial(parent_subject, &(struct landlock_request) {
			.type = LANDLOCK_REQUEST_PTRACE,
			.audit = {
				.type = LSM_AUDIT_DATA_TASK,
				.u.tsk = child,
			},
			.layer_plus_one = parent_subject->domain->num_layers,
		});

	return err;
}

/**
 * hook_ptrace_traceme - Determines whether another process may trace the
 *			 current one
 *
 * @parent: Task proposed to be the tracer.
 *
 * If the parent has Landlock rules, then the current task must have the same
 * or more rules.  Else denied.
 *
 * Return: 0 if permission is granted, -errno if denied.
 */
static int hook_ptrace_traceme(struct task_struct *const parent)
{
	const struct landlock_cred_security *parent_subject;
	const struct landlock_ruleset *child_dom;
	int err;

	child_dom = landlock_get_current_domain();

	guard(rcu)();
	parent_subject = landlock_cred(__task_cred(parent));
	err = domain_ptrace(parent_subject->domain, child_dom);

	if (!err)
		return 0;

	/*
	 * For the ptrace_traceme case, we log the domain which is the cause of
	 * the denial, which means the parent domain instead of the current
	 * domain.  This may look unusual because the ptrace_traceme action is a
	 * request to be traced, but the semantic is consistent with
	 * hook_ptrace_access_check().
	 */
	landlock_log_denial(parent_subject, &(struct landlock_request) {
		.type = LANDLOCK_REQUEST_PTRACE,
		.audit = {
			.type = LSM_AUDIT_DATA_TASK,
			.u.tsk = current,
		},
		.layer_plus_one = parent_subject->domain->num_layers,
	});
	return err;
}

/**
 * domain_is_scoped - Check if an interaction from a client/sender to a
 *		      server/receiver should be restricted based on scope controls.
 *
 * @client: IPC sender domain.
 * @server: IPC receiver domain.
 * @scope: The scope restriction criteria.
 *
 * Return: True if @server is in a different domain from @client and @client
 * is scoped to access @server (i.e. access should be denied), false otherwise.
 */
static bool domain_is_scoped(const struct landlock_ruleset *const client,
			     const struct landlock_ruleset *const server,
			     access_mask_t scope)
{
	int client_layer, server_layer;
	const struct landlock_hierarchy *client_walker, *server_walker;

	/* Quick return if client has no domain */
	if (WARN_ON_ONCE(!client))
		return false;

	client_layer = client->num_layers - 1;
	client_walker = client->hierarchy;
	/*
	 * client_layer must be able to represent all numbers from
	 * LANDLOCK_MAX_NUM_LAYERS - 1 to -1 for the loop below to terminate.
	 * (It must be large enough, and it must be signed.)
	 */
	BUILD_BUG_ON(!is_signed_type(typeof(client_layer)));
	BUILD_BUG_ON(LANDLOCK_MAX_NUM_LAYERS - 1 >
		     type_max(typeof(client_layer)));

	server_layer = server ? (server->num_layers - 1) : -1;

Annotation

Implementation Notes