LCOV - code coverage report
Current view: top level - security/landlock - ptrace.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 26 26 100.0 %
Date: 2021-04-22 12:43:58 Functions: 5 5 100.0 %

          Line data    Source code
       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             :  */
      32          30 : static bool domain_scope_le(const struct landlock_ruleset *const parent,
      33             :                 const struct landlock_ruleset *const child)
      34             : {
      35          30 :         const struct landlock_hierarchy *walker;
      36             : 
      37          30 :         if (!parent)
      38             :                 return true;
      39          30 :         if (!child)
      40             :                 return false;
      41          50 :         for (walker = child->hierarchy; walker; walker = walker->parent) {
      42          35 :                 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             : 
      50          30 : static bool task_is_scoped(const struct task_struct *const parent,
      51             :                 const struct task_struct *const child)
      52             : {
      53          30 :         bool is_scoped;
      54          30 :         const struct landlock_ruleset *dom_parent, *dom_child;
      55             : 
      56          30 :         rcu_read_lock();
      57          30 :         dom_parent = landlock_get_task_domain(parent);
      58          30 :         dom_child = landlock_get_task_domain(child);
      59          30 :         is_scoped = domain_scope_le(dom_parent, dom_child);
      60          30 :         rcu_read_unlock();
      61          30 :         return is_scoped;
      62             : }
      63             : 
      64         236 : static 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         236 :         if (!landlocked(parent))
      69             :                 return 0;
      70          30 :         if (task_is_scoped(parent, child))
      71          10 :                 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             :  */
      88         228 : static int hook_ptrace_access_check(struct task_struct *const child,
      89             :                 const unsigned int mode)
      90             : {
      91         228 :         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             :  */
     106           8 : static int hook_ptrace_traceme(struct task_struct *const parent)
     107             : {
     108           8 :         return task_ptrace(parent, current);
     109             : }
     110             : 
     111             : static 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           1 : __init void landlock_add_ptrace_hooks(void)
     117             : {
     118           1 :         security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
     119             :                         LANDLOCK_NAME);
     120           1 : }

Generated by: LCOV version 1.14