mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2025-04-19 20:58:31 +09:00
landlock: Prepare to use credential instead of domain for fowner
This cosmetic change is needed for audit support, specifically to be able to filter according to cross-execution boundaries. struct landlock_file_security's size stay the same for now but it will increase with struct landlock_cred_security's size. Only save Landlock domain in hook_file_set_fowner() if the current domain has LANDLOCK_SCOPE_SIGNAL, which was previously done for each hook_file_send_sigiotask() calls. This should improve a bit performance. Replace hardcoded LANDLOCK_SCOPE_SIGNAL with the signal_scope.scope variable. Use scoped guards for RCU read-side critical sections. Cc: Günther Noack <gnoack@google.com> Link: https://lore.kernel.org/r/20250320190717.2287696-8-mic@digikod.net Signed-off-by: Mickaël Salaün <mic@digikod.net>
This commit is contained in:
parent
8d20efa9dc
commit
79625f1b3a
@ -1670,15 +1670,23 @@ static bool control_current_fowner(struct fown_struct *const fown)
|
||||
static void hook_file_set_fowner(struct file *file)
|
||||
{
|
||||
struct landlock_ruleset *prev_dom;
|
||||
struct landlock_ruleset *new_dom = NULL;
|
||||
struct landlock_cred_security fown_subject = {};
|
||||
|
||||
if (control_current_fowner(file_f_owner(file))) {
|
||||
new_dom = landlock_get_current_domain();
|
||||
landlock_get_ruleset(new_dom);
|
||||
static const struct access_masks signal_scope = {
|
||||
.scope = LANDLOCK_SCOPE_SIGNAL,
|
||||
};
|
||||
const struct landlock_cred_security *new_subject =
|
||||
landlock_get_applicable_subject(current_cred(),
|
||||
signal_scope, NULL);
|
||||
if (new_subject) {
|
||||
landlock_get_ruleset(new_subject->domain);
|
||||
fown_subject = *new_subject;
|
||||
}
|
||||
}
|
||||
|
||||
prev_dom = landlock_file(file)->fown_domain;
|
||||
landlock_file(file)->fown_domain = new_dom;
|
||||
prev_dom = landlock_file(file)->fown_subject.domain;
|
||||
landlock_file(file)->fown_subject = fown_subject;
|
||||
|
||||
/* May be called in an RCU read-side critical section. */
|
||||
landlock_put_ruleset_deferred(prev_dom);
|
||||
@ -1686,7 +1694,7 @@ static void hook_file_set_fowner(struct file *file)
|
||||
|
||||
static void hook_file_free_security(struct file *file)
|
||||
{
|
||||
landlock_put_ruleset_deferred(landlock_file(file)->fown_domain);
|
||||
landlock_put_ruleset_deferred(landlock_file(file)->fown_subject.domain);
|
||||
}
|
||||
|
||||
static struct security_hook_list landlock_hooks[] __ro_after_init = {
|
||||
|
@ -1,9 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Landlock LSM - Filesystem management and hooks
|
||||
* Landlock - Filesystem management and hooks
|
||||
*
|
||||
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
|
||||
* Copyright © 2018-2020 ANSSI
|
||||
* Copyright © 2024-2025 Microsoft Corporation
|
||||
*/
|
||||
|
||||
#ifndef _SECURITY_LANDLOCK_FS_H
|
||||
@ -14,6 +15,7 @@
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
#include "access.h"
|
||||
#include "cred.h"
|
||||
#include "ruleset.h"
|
||||
#include "setup.h"
|
||||
|
||||
@ -54,12 +56,13 @@ struct landlock_file_security {
|
||||
*/
|
||||
access_mask_t allowed_access;
|
||||
/**
|
||||
* @fown_domain: Domain of the task that set the PID that may receive a
|
||||
* signal e.g., SIGURG when writing MSG_OOB to the related socket.
|
||||
* This pointer is protected by the related file->f_owner->lock, as for
|
||||
* fown_struct's members: pid, uid, and euid.
|
||||
* @fown_subject: Landlock credential of the task that set the PID that
|
||||
* may receive a signal e.g., SIGURG when writing MSG_OOB to the
|
||||
* related socket. This pointer is protected by the related
|
||||
* file->f_owner->lock, as for fown_struct's members: pid, uid, and
|
||||
* euid.
|
||||
*/
|
||||
struct landlock_ruleset *fown_domain;
|
||||
struct landlock_cred_security fown_subject;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -302,22 +302,29 @@ static int hook_task_kill(struct task_struct *const p,
|
||||
static int hook_file_send_sigiotask(struct task_struct *tsk,
|
||||
struct fown_struct *fown, int signum)
|
||||
{
|
||||
const struct landlock_ruleset *dom;
|
||||
const struct landlock_cred_security *subject;
|
||||
bool is_scoped = false;
|
||||
|
||||
/* Lock already held by send_sigio() and send_sigurg(). */
|
||||
lockdep_assert_held(&fown->lock);
|
||||
dom = landlock_get_applicable_domain(
|
||||
landlock_file(fown->file)->fown_domain, signal_scope);
|
||||
subject = &landlock_file(fown->file)->fown_subject;
|
||||
|
||||
/* Quick return for unowned socket. */
|
||||
if (!dom)
|
||||
/*
|
||||
* 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;
|
||||
|
||||
rcu_read_lock();
|
||||
is_scoped = domain_is_scoped(dom, landlock_get_task_domain(tsk),
|
||||
LANDLOCK_SCOPE_SIGNAL);
|
||||
rcu_read_unlock();
|
||||
scoped_guard(rcu)
|
||||
{
|
||||
is_scoped = domain_is_scoped(subject->domain,
|
||||
landlock_get_task_domain(tsk),
|
||||
signal_scope.scope);
|
||||
}
|
||||
if (is_scoped)
|
||||
return -EPERM;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user