/** * domain_scope_le - Checks domain ordering for scoped ptrace * * @parent: Parent domain. * @child: Potential child of @parent. * * Checks if the @parent domain is less or equal to (i.e. an ancestor, which * means a subset of) the @child domain.
*/ staticbool domain_scope_le(conststruct landlock_ruleset *const parent, conststruct landlock_ruleset *const child)
{ conststruct landlock_hierarchy *walker;
/* Quick return for non-landlocked tasks. */ if (!parent) returntrue;
if (!child) returnfalse;
for (walker = child->hierarchy; walker; walker = walker->parent) { if (walker == parent->hierarchy) /* @parent is in the scoped hierarchy of @child. */ returntrue;
}
/* There is no relationship between @parent and @child. */ returnfalse;
}
/** * hook_ptrace_access_check - Determines whether the current process may access * another * * @child: Process to be accessed. * @mode: Mode of attachment. * * If the current task has Landlock rules, then the child must have at least * the same rules. Else denied. * * Determines whether a process may access another, returning 0 if permission * granted, -errno if denied.
*/ staticint hook_ptrace_access_check(struct task_struct *const child, constunsignedint mode)
{ conststruct landlock_cred_security *parent_subject; conststruct landlock_ruleset *child_dom; int err;
/* Quick return for non-landlocked tasks. */
parent_subject = landlock_cred(current_cred()); if (!parent_subject) return 0;
/* * For the ptrace_access_check case, we log the current/parent domain * and the child task.
*/ if (!(mode & PTRACE_MODE_NOAUDIT))
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. * * Determines whether the nominated task is permitted to trace the current * process, returning 0 if permission is granted, -errno if denied.
*/ staticint hook_ptrace_traceme(struct task_struct *const parent)
{ conststruct landlock_cred_security *parent_subject; conststruct landlock_ruleset *child_dom; int err;
/* * 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 - Checks if the client domain is scoped in the same * domain as the server. * * @client: IPC sender domain. * @server: IPC receiver domain. * @scope: The scope restriction criteria. * * Returns: True if the @client domain is scoped to access the @server, * unless the @server is also scoped in the same domain as @client.
*/ staticbool domain_is_scoped(conststruct landlock_ruleset *const client, conststruct landlock_ruleset *const server,
access_mask_t scope)
{ int client_layer, server_layer; conststruct landlock_hierarchy *client_walker, *server_walker;
/* Quick return if client has no domain */ if (WARN_ON_ONCE(!client)) returnfalse;
client_layer = client->num_layers - 1;
client_walker = client->hierarchy; /* * client_layer must be a signed integer with greater capacity * than client->num_layers to ensure the following loop stops.
*/
BUILD_BUG_ON(sizeof(client_layer) > sizeof(client->num_layers));
server_layer = server ? (server->num_layers - 1) : -1;
server_walker = server ? server->hierarchy : NULL;
/* * Walks client's parent domains down to the same hierarchy level * as the server's domain, and checks that none of these client's * parent domains are scoped.
*/ for (; client_layer > server_layer; client_layer--) { if (landlock_get_scope_mask(client, client_layer) & scope) returntrue;
client_walker = client_walker->parent;
} /* * Walks server's parent domains down to the same hierarchy level as * the client's domain.
*/ for (; server_layer > client_layer; server_layer--)
server_walker = server_walker->parent;
for (; client_layer >= 0; client_layer--) { if (landlock_get_scope_mask(client, client_layer) & scope) { /* * Client and server are at the same level in the * hierarchy. If the client is scoped, the request is * only allowed if this domain is also a server's * ancestor.
*/ return server_walker != client_walker;
}
client_walker = client_walker->parent;
server_walker = server_walker->parent;
} returnfalse;
}
if (!cred) { /* * Always allow sending signals between threads of the same process. * This is required for process credential changes by the Native POSIX * Threads Library and implemented by the set*id(2) wrappers and * libcap(3) with tgkill(2). See nptl(7) and libpsx(3). * * This exception is similar to the __ptrace_may_access() one.
*/ if (same_thread_group(p, current)) return 0;
/* Not dealing with USB IO. */
cred = current_cred();
}
/* Lock already held by send_sigio() and send_sigurg(). */
lockdep_assert_held(&fown->lock);
subject = &landlock_file(fown->file)->fown_subject;
/* * Quick return for unowned socket. * * subject->domain has already been filtered when saved by * hook_file_set_fowner(), so there is no need to call * landlock_get_applicable_subject() here.
*/ if (!subject->domain) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.