mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
landlock: Add ptrace restrictions
Using ptrace(2) and related debug features on a target process can lead to a privilege escalation. Indeed, ptrace(2) can be used by an attacker to impersonate another task and to remain undetected while performing malicious activities. Thanks to ptrace_may_access(), various part of the kernel can check if a tracer is more privileged than a tracee. A landlocked process has fewer privileges than a non-landlocked process and must then be subject to additional restrictions when manipulating processes. To be allowed to use ptrace(2) and related syscalls on a target process, a landlocked process must have a subset of the target process's rules (i.e. the tracee must be in a sub-domain of the tracer). Cc: James Morris <jmorris@namei.org> Signed-off-by: Mickaël Salaün <mic@linux.microsoft.com> Reviewed-by: Jann Horn <jannh@google.com> Acked-by: Serge Hallyn <serge@hallyn.com> Reviewed-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/r/20210422154123.13086-5-mic@digikod.net Signed-off-by: James Morris <jamorris@linux.microsoft.com>
This commit is contained in:
committed by
James Morris
parent
385975dca5
commit
afe81f7541
@@ -1,4 +1,4 @@
|
|||||||
obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o
|
obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o
|
||||||
|
|
||||||
landlock-y := setup.o object.o ruleset.o \
|
landlock-y := setup.o object.o ruleset.o \
|
||||||
cred.o
|
cred.o ptrace.o
|
||||||
|
120
security/landlock/ptrace.c
Normal file
120
security/landlock/ptrace.c
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Landlock LSM - Ptrace hooks
|
||||||
|
*
|
||||||
|
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
|
||||||
|
* Copyright © 2019-2020 ANSSI
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm/current.h>
|
||||||
|
#include <linux/cred.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/lsm_hooks.h>
|
||||||
|
#include <linux/rcupdate.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "cred.h"
|
||||||
|
#include "ptrace.h"
|
||||||
|
#include "ruleset.h"
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static bool domain_scope_le(const struct landlock_ruleset *const parent,
|
||||||
|
const struct landlock_ruleset *const child)
|
||||||
|
{
|
||||||
|
const struct landlock_hierarchy *walker;
|
||||||
|
|
||||||
|
if (!parent)
|
||||||
|
return true;
|
||||||
|
if (!child)
|
||||||
|
return false;
|
||||||
|
for (walker = child->hierarchy; walker; walker = walker->parent) {
|
||||||
|
if (walker == parent->hierarchy)
|
||||||
|
/* @parent is in the scoped hierarchy of @child. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/* There is no relationship between @parent and @child. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool task_is_scoped(const struct task_struct *const parent,
|
||||||
|
const struct task_struct *const child)
|
||||||
|
{
|
||||||
|
bool is_scoped;
|
||||||
|
const struct landlock_ruleset *dom_parent, *dom_child;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
dom_parent = landlock_get_task_domain(parent);
|
||||||
|
dom_child = landlock_get_task_domain(child);
|
||||||
|
is_scoped = domain_scope_le(dom_parent, dom_child);
|
||||||
|
rcu_read_unlock();
|
||||||
|
return is_scoped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int task_ptrace(const struct task_struct *const parent,
|
||||||
|
const struct task_struct *const child)
|
||||||
|
{
|
||||||
|
/* Quick return for non-landlocked tasks. */
|
||||||
|
if (!landlocked(parent))
|
||||||
|
return 0;
|
||||||
|
if (task_is_scoped(parent, child))
|
||||||
|
return 0;
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static int hook_ptrace_access_check(struct task_struct *const child,
|
||||||
|
const unsigned int mode)
|
||||||
|
{
|
||||||
|
return task_ptrace(current, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static int hook_ptrace_traceme(struct task_struct *const parent)
|
||||||
|
{
|
||||||
|
return task_ptrace(parent, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
|
||||||
|
LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
|
||||||
|
LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
|
||||||
|
};
|
||||||
|
|
||||||
|
__init void landlock_add_ptrace_hooks(void)
|
||||||
|
{
|
||||||
|
security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
|
||||||
|
LANDLOCK_NAME);
|
||||||
|
}
|
14
security/landlock/ptrace.h
Normal file
14
security/landlock/ptrace.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Landlock LSM - Ptrace hooks
|
||||||
|
*
|
||||||
|
* Copyright © 2017-2019 Mickaël Salaün <mic@digikod.net>
|
||||||
|
* Copyright © 2019 ANSSI
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SECURITY_LANDLOCK_PTRACE_H
|
||||||
|
#define _SECURITY_LANDLOCK_PTRACE_H
|
||||||
|
|
||||||
|
__init void landlock_add_ptrace_hooks(void);
|
||||||
|
|
||||||
|
#endif /* _SECURITY_LANDLOCK_PTRACE_H */
|
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "cred.h"
|
#include "cred.h"
|
||||||
|
#include "ptrace.h"
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
|
struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
|
||||||
@@ -20,6 +21,7 @@ struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
|
|||||||
static int __init landlock_init(void)
|
static int __init landlock_init(void)
|
||||||
{
|
{
|
||||||
landlock_add_cred_hooks();
|
landlock_add_cred_hooks();
|
||||||
|
landlock_add_ptrace_hooks();
|
||||||
pr_info("Up and running.\n");
|
pr_info("Up and running.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user