^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Yama Linux Security Module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Kees Cook <keescook@chromium.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2010 Canonical, Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2011 The Chromium OS Authors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/lsm_hooks.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/prctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/ratelimit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/string_helpers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/task_work.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define YAMA_SCOPE_DISABLED 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define YAMA_SCOPE_RELATIONAL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define YAMA_SCOPE_CAPABILITY 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define YAMA_SCOPE_NO_ATTACH 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int ptrace_scope = YAMA_SCOPE_RELATIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* describe a ptrace relationship for potential exception */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct ptrace_relation {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct task_struct *tracer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct task_struct *tracee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) bool invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct rcu_head rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static LIST_HEAD(ptracer_relations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static DEFINE_SPINLOCK(ptracer_relations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static void yama_relation_cleanup(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static DECLARE_WORK(yama_relation_work, yama_relation_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct access_report_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct callback_head work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const char *access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct task_struct *target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct task_struct *agent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void __report_access(struct callback_head *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct access_report_info *info =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) container_of(work, struct access_report_info, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char *target_cmd, *agent_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) target_cmd = kstrdup_quotable_cmdline(info->target, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) agent_cmd = kstrdup_quotable_cmdline(info->agent, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) pr_notice_ratelimited(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) "ptrace %s of \"%s\"[%d] was attempted by \"%s\"[%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) info->access, target_cmd, info->target->pid, agent_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) info->agent->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) kfree(agent_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) kfree(target_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) put_task_struct(info->agent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) put_task_struct(info->target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* defers execution because cmdline access can sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void report_access(const char *access, struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct task_struct *agent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct access_report_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) char agent_comm[sizeof(agent->comm)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) assert_spin_locked(&target->alloc_lock); /* for target->comm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (current->flags & PF_KTHREAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* I don't think kthreads call task_work_run() before exiting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Imagine angry ranting about procfs here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pr_notice_ratelimited(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "ptrace %s of \"%s\"[%d] was attempted by \"%s\"[%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) access, target->comm, target->pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) get_task_comm(agent_comm, agent), agent->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) info = kmalloc(sizeof(*info), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) init_task_work(&info->work, __report_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) get_task_struct(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) get_task_struct(agent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) info->access = access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) info->target = target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) info->agent = agent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (task_work_add(current, &info->work, TWA_RESUME) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return; /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) WARN(1, "report_access called from exiting task");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) put_task_struct(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) put_task_struct(agent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * yama_relation_cleanup - remove invalid entries from the relation list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void yama_relation_cleanup(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct ptrace_relation *relation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) spin_lock(&ptracer_relations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) list_for_each_entry_rcu(relation, &ptracer_relations, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (relation->invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) list_del_rcu(&relation->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) kfree_rcu(relation, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) spin_unlock(&ptracer_relations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * yama_ptracer_add - add/replace an exception for this tracer/tracee pair
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * @tracer: the task_struct of the process doing the ptrace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * @tracee: the task_struct of the process to be ptraced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Each tracee can have, at most, one tracer registered. Each time this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * is called, the prior registered tracer will be replaced for the tracee.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Returns 0 if relationship was added, -ve on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int yama_ptracer_add(struct task_struct *tracer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct task_struct *tracee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct ptrace_relation *relation, *added;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) added = kmalloc(sizeof(*added), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (!added)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) added->tracee = tracee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) added->tracer = tracer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) added->invalid = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) spin_lock(&ptracer_relations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) list_for_each_entry_rcu(relation, &ptracer_relations, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (relation->invalid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (relation->tracee == tracee) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) list_replace_rcu(&relation->node, &added->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) kfree_rcu(relation, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) list_add_rcu(&added->node, &ptracer_relations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) spin_unlock(&ptracer_relations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * yama_ptracer_del - remove exceptions related to the given tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @tracer: remove any relation where tracer task matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @tracee: remove any relation where tracee task matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void yama_ptracer_del(struct task_struct *tracer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct task_struct *tracee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct ptrace_relation *relation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) bool marked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) list_for_each_entry_rcu(relation, &ptracer_relations, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (relation->invalid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (relation->tracee == tracee ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) (tracer && relation->tracer == tracer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) relation->invalid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) marked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (marked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) schedule_work(&yama_relation_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * yama_task_free - check for task_pid to remove from exception list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * @task: task being removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static void yama_task_free(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) yama_ptracer_del(task, task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * yama_task_prctl - check for Yama-specific prctl operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @option: operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * @arg2: argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * @arg3: argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * @arg4: argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * @arg5: argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Return 0 on success, -ve on error. -ENOSYS is returned when Yama
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * does not handle the given option.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) unsigned long arg4, unsigned long arg5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int rc = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct task_struct *myself = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) switch (option) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) case PR_SET_PTRACER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Since a thread can call prctl(), find the group leader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * before calling _add() or _del() on it, since we want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * process-level granularity of control. The tracer group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * leader checking is handled later when walking the ancestry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * at the time of PTRACE_ATTACH check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!thread_group_leader(myself))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) myself = rcu_dereference(myself->group_leader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) get_task_struct(myself);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (arg2 == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) yama_ptracer_del(NULL, myself);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) } else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) rc = yama_ptracer_add(NULL, myself);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct task_struct *tracer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) tracer = find_get_task_by_vpid(arg2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (!tracer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) rc = yama_ptracer_add(tracer, myself);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) put_task_struct(tracer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) put_task_struct(myself);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * task_is_descendant - walk up a process family tree looking for a match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * @parent: the process to compare against while walking up from child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * @child: the process to start from while looking upwards for parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * Returns 1 if child is a descendant of parent, 0 if not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int task_is_descendant(struct task_struct *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct task_struct *walker = child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!parent || !child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (!thread_group_leader(parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) parent = rcu_dereference(parent->group_leader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) while (walker->pid > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!thread_group_leader(walker))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) walker = rcu_dereference(walker->group_leader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (walker == parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) walker = rcu_dereference(walker->real_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * ptracer_exception_found - tracer registered as exception for this tracee
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * @tracer: the task_struct of the process attempting ptrace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @tracee: the task_struct of the process to be ptraced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * Returns 1 if tracer has a ptracer exception ancestor for tracee.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int ptracer_exception_found(struct task_struct *tracer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct task_struct *tracee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct ptrace_relation *relation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct task_struct *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * If there's already an active tracing relationship, then make an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * exception for the sake of other accesses, like process_vm_rw().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) parent = ptrace_parent(tracee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (parent != NULL && same_thread_group(parent, tracer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* Look for a PR_SET_PTRACER relationship. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (!thread_group_leader(tracee))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) tracee = rcu_dereference(tracee->group_leader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) list_for_each_entry_rcu(relation, &ptracer_relations, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (relation->invalid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (relation->tracee == tracee) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) parent = relation->tracer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (found && (parent == NULL || task_is_descendant(parent, tracer)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * yama_ptrace_access_check - validate PTRACE_ATTACH calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @child: task that current task is attempting to ptrace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * @mode: ptrace attach mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * Returns 0 if following the ptrace is allowed, -ve on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int yama_ptrace_access_check(struct task_struct *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* require ptrace target be a child of ptracer on attach */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (mode & PTRACE_MODE_ATTACH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) switch (ptrace_scope) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case YAMA_SCOPE_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* No additional restrictions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case YAMA_SCOPE_RELATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (!pid_alive(child))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!rc && !task_is_descendant(current, child) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) !ptracer_exception_found(current, child) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) !ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case YAMA_SCOPE_CAPABILITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (!ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case YAMA_SCOPE_NO_ATTACH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (rc && (mode & PTRACE_MODE_NOAUDIT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) report_access("attach", child, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * yama_ptrace_traceme - validate PTRACE_TRACEME calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * @parent: task that will become the ptracer of the current task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * Returns 0 if following the ptrace is allowed, -ve on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static int yama_ptrace_traceme(struct task_struct *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Only disallow PTRACE_TRACEME on more aggressive settings. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) switch (ptrace_scope) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) case YAMA_SCOPE_CAPABILITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (!has_ns_capability(parent, current_user_ns(), CAP_SYS_PTRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) case YAMA_SCOPE_NO_ATTACH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) task_lock(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) report_access("traceme", current, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) task_unlock(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) LSM_HOOK_INIT(task_prctl, yama_task_prctl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) LSM_HOOK_INIT(task_free, yama_task_free),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #ifdef CONFIG_SYSCTL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static int yama_dointvec_minmax(struct ctl_table *table, int write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) void *buffer, size_t *lenp, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct ctl_table table_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (write && !capable(CAP_SYS_PTRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* Lock the max value if it ever gets set. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) table_copy = *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (*(int *)table_copy.data == *(int *)table_copy.extra2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) table_copy.extra1 = table_copy.extra2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return proc_dointvec_minmax(&table_copy, write, buffer, lenp, ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static int max_scope = YAMA_SCOPE_NO_ATTACH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static struct ctl_path yama_sysctl_path[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) { .procname = "kernel", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) { .procname = "yama", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static struct ctl_table yama_sysctl_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .procname = "ptrace_scope",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .data = &ptrace_scope,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .maxlen = sizeof(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .mode = 0644,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .proc_handler = yama_dointvec_minmax,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .extra1 = SYSCTL_ZERO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .extra2 = &max_scope,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static void __init yama_init_sysctl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) panic("Yama: sysctl registration failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static inline void yama_init_sysctl(void) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) #endif /* CONFIG_SYSCTL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int __init yama_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) pr_info("Yama: becoming mindful.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) yama_init_sysctl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) DEFINE_LSM(yama) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) .name = "yama",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) .init = yama_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) };