linux/security/landlock/ptrace.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Landlock LSM - Ptrace hooks
   4 *
   5 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
   6 * Copyright © 2019-2020 ANSSI
   7 */
   8
   9#include <asm/current.h>
  10#include <linux/cred.h>
  11#include <linux/errno.h>
  12#include <linux/kernel.h>
  13#include <linux/lsm_hooks.h>
  14#include <linux/rcupdate.h>
  15#include <linux/sched.h>
  16
  17#include "common.h"
  18#include "cred.h"
  19#include "ptrace.h"
  20#include "ruleset.h"
  21#include "setup.h"
  22
  23/**
  24 * domain_scope_le - Checks domain ordering for scoped ptrace
  25 *
  26 * @parent: Parent domain.
  27 * @child: Potential child of @parent.
  28 *
  29 * Checks if the @parent domain is less or equal to (i.e. an ancestor, which
  30 * means a subset of) the @child domain.
  31 */
  32static bool domain_scope_le(const struct landlock_ruleset *const parent,
  33                const struct landlock_ruleset *const child)
  34{
  35        const struct landlock_hierarchy *walker;
  36
  37        if (!parent)
  38                return true;
  39        if (!child)
  40                return false;
  41        for (walker = child->hierarchy; walker; walker = walker->parent) {
  42                if (walker == parent->hierarchy)
  43                        /* @parent is in the scoped hierarchy of @child. */
  44                        return true;
  45        }
  46        /* There is no relationship between @parent and @child. */
  47        return false;
  48}
  49
  50static bool task_is_scoped(const struct task_struct *const parent,
  51                const struct task_struct *const child)
  52{
  53        bool is_scoped;
  54        const struct landlock_ruleset *dom_parent, *dom_child;
  55
  56        rcu_read_lock();
  57        dom_parent = landlock_get_task_domain(parent);
  58        dom_child = landlock_get_task_domain(child);
  59        is_scoped = domain_scope_le(dom_parent, dom_child);
  60        rcu_read_unlock();
  61        return is_scoped;
  62}
  63
  64static int task_ptrace(const struct task_struct *const parent,
  65                const struct task_struct *const child)
  66{
  67        /* Quick return for non-landlocked tasks. */
  68        if (!landlocked(parent))
  69                return 0;
  70        if (task_is_scoped(parent, child))
  71                return 0;
  72        return -EPERM;
  73}
  74
  75/**
  76 * hook_ptrace_access_check - Determines whether the current process may access
  77 *                            another
  78 *
  79 * @child: Process to be accessed.
  80 * @mode: Mode of attachment.
  81 *
  82 * If the current task has Landlock rules, then the child must have at least
  83 * the same rules.  Else denied.
  84 *
  85 * Determines whether a process may access another, returning 0 if permission
  86 * granted, -errno if denied.
  87 */
  88static int hook_ptrace_access_check(struct task_struct *const child,
  89                const unsigned int mode)
  90{
  91        return task_ptrace(current, child);
  92}
  93
  94/**
  95 * hook_ptrace_traceme - Determines whether another process may trace the
  96 *                       current one
  97 *
  98 * @parent: Task proposed to be the tracer.
  99 *
 100 * If the parent has Landlock rules, then the current task must have the same
 101 * or more rules.  Else denied.
 102 *
 103 * Determines whether the nominated task is permitted to trace the current
 104 * process, returning 0 if permission is granted, -errno if denied.
 105 */
 106static int hook_ptrace_traceme(struct task_struct *const parent)
 107{
 108        return task_ptrace(parent, current);
 109}
 110
 111static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
 112        LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
 113        LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
 114};
 115
 116__init void landlock_add_ptrace_hooks(void)
 117{
 118        security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
 119                        LANDLOCK_NAME);
 120}
 121