Commit 2d514487faf188938a4ee4fb3464eeecfbdcf8eb

Authored by Kees Cook
Committed by James Morris
1 parent 1a2a4d06e1

security: Yama LSM

This adds the Yama Linux Security Module to collect DAC security
improvements (specifically just ptrace restrictions for now) that have
existed in various forms over the years and have been carried outside the
mainline kernel by other Linux distributions like Openwall and grsecurity.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 8 changed files with 411 additions and 0 deletions Side-by-side Diff

Documentation/security/00-INDEX
... ... @@ -6,6 +6,8 @@
6 6 - how to get started with the SELinux security enhancement.
7 7 Smack.txt
8 8 - documentation on the Smack Linux Security Module.
  9 +Yama.txt
  10 + - documentation on the Yama Linux Security Module.
9 11 apparmor.txt
10 12 - documentation on the AppArmor security extension.
11 13 credentials.txt
Documentation/security/Yama.txt
  1 +Yama is a Linux Security Module that collects a number of system-wide DAC
  2 +security protections that are not handled by the core kernel itself. To
  3 +select it at boot time, specify "security=yama" (though this will disable
  4 +any other LSM).
  5 +
  6 +Yama is controlled through sysctl in /proc/sys/kernel/yama:
  7 +
  8 +- ptrace_scope
  9 +
  10 +==============================================================
  11 +
  12 +ptrace_scope:
  13 +
  14 +As Linux grows in popularity, it will become a larger target for
  15 +malware. One particularly troubling weakness of the Linux process
  16 +interfaces is that a single user is able to examine the memory and
  17 +running state of any of their processes. For example, if one application
  18 +(e.g. Pidgin) was compromised, it would be possible for an attacker to
  19 +attach to other running processes (e.g. Firefox, SSH sessions, GPG agent,
  20 +etc) to extract additional credentials and continue to expand the scope
  21 +of their attack without resorting to user-assisted phishing.
  22 +
  23 +This is not a theoretical problem. SSH session hijacking
  24 +(http://www.storm.net.nz/projects/7) and arbitrary code injection
  25 +(http://c-skills.blogspot.com/2007/05/injectso.html) attacks already
  26 +exist and remain possible if ptrace is allowed to operate as before.
  27 +Since ptrace is not commonly used by non-developers and non-admins, system
  28 +builders should be allowed the option to disable this debugging system.
  29 +
  30 +For a solution, some applications use prctl(PR_SET_DUMPABLE, ...) to
  31 +specifically disallow such ptrace attachment (e.g. ssh-agent), but many
  32 +do not. A more general solution is to only allow ptrace directly from a
  33 +parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still
  34 +work), or with CAP_SYS_PTRACE (i.e. "gdb --pid=PID", and "strace -p PID"
  35 +still work as root).
  36 +
  37 +For software that has defined application-specific relationships
  38 +between a debugging process and its inferior (crash handlers, etc),
  39 +prctl(PR_SET_PTRACER, pid, ...) can be used. An inferior can declare which
  40 +other process (and its descendents) are allowed to call PTRACE_ATTACH
  41 +against it. Only one such declared debugging process can exists for
  42 +each inferior at a time. For example, this is used by KDE, Chromium, and
  43 +Firefox's crash handlers, and by Wine for allowing only Wine processes
  44 +to ptrace each other.
  45 +
  46 +0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other
  47 + process running under the same uid, as long as it is dumpable (i.e.
  48 + did not transition uids, start privileged, or have called
  49 + prctl(PR_SET_DUMPABLE...) already).
  50 +
  51 +1 - restricted ptrace: a process must have a predefined relationship
  52 + with the inferior it wants to call PTRACE_ATTACH on. By default,
  53 + this relationship is that of only its descendants when the above
  54 + classic criteria is also met. To change the relationship, an
  55 + inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
  56 + an allowed debugger PID to call PTRACE_ATTACH on the inferior.
  57 +
  58 +The original children-only logic was based on the restrictions in grsecurity.
  59 +
  60 +==============================================================
include/linux/prctl.h
... ... @@ -114,5 +114,11 @@
114 114 # define PR_SET_MM_START_BRK 6
115 115 # define PR_SET_MM_BRK 7
116 116  
  117 +/*
  118 + * Set specific pid that is allowed to ptrace the current task.
  119 + * A value of 0 mean "no process".
  120 + */
  121 +#define PR_SET_PTRACER 0x59616d61
  122 +
117 123 #endif /* _LINUX_PRCTL_H */
... ... @@ -187,6 +187,7 @@
187 187 source security/smack/Kconfig
188 188 source security/tomoyo/Kconfig
189 189 source security/apparmor/Kconfig
  190 +source security/yama/Kconfig
190 191  
191 192 source security/integrity/Kconfig
192 193  
... ... @@ -196,6 +197,7 @@
196 197 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
197 198 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
198 199 default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
  200 + default DEFAULT_SECURITY_YAMA if SECURITY_YAMA
199 201 default DEFAULT_SECURITY_DAC
200 202  
201 203 help
... ... @@ -214,6 +216,9 @@
214 216 config DEFAULT_SECURITY_APPARMOR
215 217 bool "AppArmor" if SECURITY_APPARMOR=y
216 218  
  219 + config DEFAULT_SECURITY_YAMA
  220 + bool "Yama" if SECURITY_YAMA=y
  221 +
217 222 config DEFAULT_SECURITY_DAC
218 223 bool "Unix Discretionary Access Controls"
219 224  
... ... @@ -225,6 +230,7 @@
225 230 default "smack" if DEFAULT_SECURITY_SMACK
226 231 default "tomoyo" if DEFAULT_SECURITY_TOMOYO
227 232 default "apparmor" if DEFAULT_SECURITY_APPARMOR
  233 + default "yama" if DEFAULT_SECURITY_YAMA
228 234 default "" if DEFAULT_SECURITY_DAC
229 235  
230 236 endmenu
... ... @@ -7,6 +7,7 @@
7 7 subdir-$(CONFIG_SECURITY_SMACK) += smack
8 8 subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
9 9 subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
  10 +subdir-$(CONFIG_SECURITY_YAMA) += yama
10 11  
11 12 # always enable default capabilities
12 13 obj-y += commoncap.o
... ... @@ -21,6 +22,7 @@
21 22 obj-$(CONFIG_AUDIT) += lsm_audit.o
22 23 obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
23 24 obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
  25 +obj-$(CONFIG_SECURITY_YAMA) += yama/built-in.o
24 26 obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
25 27  
26 28 # Object integrity file lists
security/yama/Kconfig
  1 +config SECURITY_YAMA
  2 + bool "Yama support"
  3 + depends on SECURITY
  4 + select SECURITYFS
  5 + select SECURITY_PATH
  6 + default n
  7 + help
  8 + This selects Yama, which extends DAC support with additional
  9 + system-wide security settings beyond regular Linux discretionary
  10 + access controls. Currently available is ptrace scope restriction.
  11 + Further information can be found in Documentation/security/Yama.txt.
  12 +
  13 + If you are unsure how to answer this question, answer N.
security/yama/Makefile
  1 +obj-$(CONFIG_SECURITY_YAMA) := yama.o
  2 +
  3 +yama-y := yama_lsm.o
security/yama/yama_lsm.c
  1 +/*
  2 + * Yama Linux Security Module
  3 + *
  4 + * Author: Kees Cook <keescook@chromium.org>
  5 + *
  6 + * Copyright (C) 2010 Canonical, Ltd.
  7 + * Copyright (C) 2011 The Chromium OS Authors.
  8 + *
  9 + * This program is free software; you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License version 2, as
  11 + * published by the Free Software Foundation.
  12 + *
  13 + */
  14 +
  15 +#include <linux/security.h>
  16 +#include <linux/sysctl.h>
  17 +#include <linux/ptrace.h>
  18 +#include <linux/prctl.h>
  19 +#include <linux/ratelimit.h>
  20 +
  21 +static int ptrace_scope = 1;
  22 +
  23 +/* describe a ptrace relationship for potential exception */
  24 +struct ptrace_relation {
  25 + struct task_struct *tracer;
  26 + struct task_struct *tracee;
  27 + struct list_head node;
  28 +};
  29 +
  30 +static LIST_HEAD(ptracer_relations);
  31 +static DEFINE_SPINLOCK(ptracer_relations_lock);
  32 +
  33 +/**
  34 + * yama_ptracer_add - add/replace an exception for this tracer/tracee pair
  35 + * @tracer: the task_struct of the process doing the ptrace
  36 + * @tracee: the task_struct of the process to be ptraced
  37 + *
  38 + * Each tracee can have, at most, one tracer registered. Each time this
  39 + * is called, the prior registered tracer will be replaced for the tracee.
  40 + *
  41 + * Returns 0 if relationship was added, -ve on error.
  42 + */
  43 +static int yama_ptracer_add(struct task_struct *tracer,
  44 + struct task_struct *tracee)
  45 +{
  46 + int rc = 0;
  47 + struct ptrace_relation *added;
  48 + struct ptrace_relation *entry, *relation = NULL;
  49 +
  50 + added = kmalloc(sizeof(*added), GFP_KERNEL);
  51 + if (!added)
  52 + return -ENOMEM;
  53 +
  54 + spin_lock_bh(&ptracer_relations_lock);
  55 + list_for_each_entry(entry, &ptracer_relations, node)
  56 + if (entry->tracee == tracee) {
  57 + relation = entry;
  58 + break;
  59 + }
  60 + if (!relation) {
  61 + relation = added;
  62 + relation->tracee = tracee;
  63 + list_add(&relation->node, &ptracer_relations);
  64 + }
  65 + relation->tracer = tracer;
  66 +
  67 + spin_unlock_bh(&ptracer_relations_lock);
  68 + if (added != relation)
  69 + kfree(added);
  70 +
  71 + return rc;
  72 +}
  73 +
  74 +/**
  75 + * yama_ptracer_del - remove exceptions related to the given tasks
  76 + * @tracer: remove any relation where tracer task matches
  77 + * @tracee: remove any relation where tracee task matches
  78 + */
  79 +static void yama_ptracer_del(struct task_struct *tracer,
  80 + struct task_struct *tracee)
  81 +{
  82 + struct ptrace_relation *relation, *safe;
  83 +
  84 + spin_lock_bh(&ptracer_relations_lock);
  85 + list_for_each_entry_safe(relation, safe, &ptracer_relations, node)
  86 + if (relation->tracee == tracee ||
  87 + relation->tracer == tracer) {
  88 + list_del(&relation->node);
  89 + kfree(relation);
  90 + }
  91 + spin_unlock_bh(&ptracer_relations_lock);
  92 +}
  93 +
  94 +/**
  95 + * yama_task_free - check for task_pid to remove from exception list
  96 + * @task: task being removed
  97 + */
  98 +static void yama_task_free(struct task_struct *task)
  99 +{
  100 + yama_ptracer_del(task, task);
  101 +}
  102 +
  103 +/**
  104 + * yama_task_prctl - check for Yama-specific prctl operations
  105 + * @option: operation
  106 + * @arg2: argument
  107 + * @arg3: argument
  108 + * @arg4: argument
  109 + * @arg5: argument
  110 + *
  111 + * Return 0 on success, -ve on error. -ENOSYS is returned when Yama
  112 + * does not handle the given option.
  113 + */
  114 +static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
  115 + unsigned long arg4, unsigned long arg5)
  116 +{
  117 + int rc;
  118 + struct task_struct *myself = current;
  119 +
  120 + rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
  121 + if (rc != -ENOSYS)
  122 + return rc;
  123 +
  124 + switch (option) {
  125 + case PR_SET_PTRACER:
  126 + /* Since a thread can call prctl(), find the group leader
  127 + * before calling _add() or _del() on it, since we want
  128 + * process-level granularity of control. The tracer group
  129 + * leader checking is handled later when walking the ancestry
  130 + * at the time of PTRACE_ATTACH check.
  131 + */
  132 + rcu_read_lock();
  133 + if (!thread_group_leader(myself))
  134 + myself = rcu_dereference(myself->group_leader);
  135 + get_task_struct(myself);
  136 + rcu_read_unlock();
  137 +
  138 + if (arg2 == 0) {
  139 + yama_ptracer_del(NULL, myself);
  140 + rc = 0;
  141 + } else {
  142 + struct task_struct *tracer;
  143 +
  144 + rcu_read_lock();
  145 + tracer = find_task_by_vpid(arg2);
  146 + if (tracer)
  147 + get_task_struct(tracer);
  148 + else
  149 + rc = -EINVAL;
  150 + rcu_read_unlock();
  151 +
  152 + if (tracer) {
  153 + rc = yama_ptracer_add(tracer, myself);
  154 + put_task_struct(tracer);
  155 + }
  156 + }
  157 +
  158 + put_task_struct(myself);
  159 + break;
  160 + }
  161 +
  162 + return rc;
  163 +}
  164 +
  165 +/**
  166 + * task_is_descendant - walk up a process family tree looking for a match
  167 + * @parent: the process to compare against while walking up from child
  168 + * @child: the process to start from while looking upwards for parent
  169 + *
  170 + * Returns 1 if child is a descendant of parent, 0 if not.
  171 + */
  172 +static int task_is_descendant(struct task_struct *parent,
  173 + struct task_struct *child)
  174 +{
  175 + int rc = 0;
  176 + struct task_struct *walker = child;
  177 +
  178 + if (!parent || !child)
  179 + return 0;
  180 +
  181 + rcu_read_lock();
  182 + if (!thread_group_leader(parent))
  183 + parent = rcu_dereference(parent->group_leader);
  184 + while (walker->pid > 0) {
  185 + if (!thread_group_leader(walker))
  186 + walker = rcu_dereference(walker->group_leader);
  187 + if (walker == parent) {
  188 + rc = 1;
  189 + break;
  190 + }
  191 + walker = rcu_dereference(walker->real_parent);
  192 + }
  193 + rcu_read_unlock();
  194 +
  195 + return rc;
  196 +}
  197 +
  198 +/**
  199 + * ptracer_exception_found - tracer registered as exception for this tracee
  200 + * @tracer: the task_struct of the process attempting ptrace
  201 + * @tracee: the task_struct of the process to be ptraced
  202 + *
  203 + * Returns 1 if tracer has is ptracer exception ancestor for tracee.
  204 + */
  205 +static int ptracer_exception_found(struct task_struct *tracer,
  206 + struct task_struct *tracee)
  207 +{
  208 + int rc = 0;
  209 + struct ptrace_relation *relation;
  210 + struct task_struct *parent = NULL;
  211 +
  212 + spin_lock_bh(&ptracer_relations_lock);
  213 + rcu_read_lock();
  214 + if (!thread_group_leader(tracee))
  215 + tracee = rcu_dereference(tracee->group_leader);
  216 + list_for_each_entry(relation, &ptracer_relations, node)
  217 + if (relation->tracee == tracee) {
  218 + parent = relation->tracer;
  219 + break;
  220 + }
  221 +
  222 + if (task_is_descendant(parent, tracer))
  223 + rc = 1;
  224 + rcu_read_unlock();
  225 + spin_unlock_bh(&ptracer_relations_lock);
  226 +
  227 + return rc;
  228 +}
  229 +
  230 +/**
  231 + * yama_ptrace_access_check - validate PTRACE_ATTACH calls
  232 + * @child: task that current task is attempting to ptrace
  233 + * @mode: ptrace attach mode
  234 + *
  235 + * Returns 0 if following the ptrace is allowed, -ve on error.
  236 + */
  237 +static int yama_ptrace_access_check(struct task_struct *child,
  238 + unsigned int mode)
  239 +{
  240 + int rc;
  241 +
  242 + /* If standard caps disallows it, so does Yama. We should
  243 + * only tighten restrictions further.
  244 + */
  245 + rc = cap_ptrace_access_check(child, mode);
  246 + if (rc)
  247 + return rc;
  248 +
  249 + /* require ptrace target be a child of ptracer on attach */
  250 + if (mode == PTRACE_MODE_ATTACH &&
  251 + ptrace_scope &&
  252 + !task_is_descendant(current, child) &&
  253 + !ptracer_exception_found(current, child) &&
  254 + !capable(CAP_SYS_PTRACE))
  255 + rc = -EPERM;
  256 +
  257 + if (rc) {
  258 + char name[sizeof(current->comm)];
  259 + printk_ratelimited(KERN_NOTICE "ptrace of non-child"
  260 + " pid %d was attempted by: %s (pid %d)\n",
  261 + child->pid,
  262 + get_task_comm(name, current),
  263 + current->pid);
  264 + }
  265 +
  266 + return rc;
  267 +}
  268 +
  269 +static struct security_operations yama_ops = {
  270 + .name = "yama",
  271 +
  272 + .ptrace_access_check = yama_ptrace_access_check,
  273 + .task_prctl = yama_task_prctl,
  274 + .task_free = yama_task_free,
  275 +};
  276 +
  277 +#ifdef CONFIG_SYSCTL
  278 +static int zero;
  279 +static int one = 1;
  280 +
  281 +struct ctl_path yama_sysctl_path[] = {
  282 + { .procname = "kernel", },
  283 + { .procname = "yama", },
  284 + { }
  285 +};
  286 +
  287 +static struct ctl_table yama_sysctl_table[] = {
  288 + {
  289 + .procname = "ptrace_scope",
  290 + .data = &ptrace_scope,
  291 + .maxlen = sizeof(int),
  292 + .mode = 0644,
  293 + .proc_handler = proc_dointvec_minmax,
  294 + .extra1 = &zero,
  295 + .extra2 = &one,
  296 + },
  297 + { }
  298 +};
  299 +#endif /* CONFIG_SYSCTL */
  300 +
  301 +static __init int yama_init(void)
  302 +{
  303 + if (!security_module_enable(&yama_ops))
  304 + return 0;
  305 +
  306 + printk(KERN_INFO "Yama: becoming mindful.\n");
  307 +
  308 + if (register_security(&yama_ops))
  309 + panic("Yama: kernel registration failed.\n");
  310 +
  311 +#ifdef CONFIG_SYSCTL
  312 + if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
  313 + panic("Yama: sysctl registration failed.\n");
  314 +#endif
  315 +
  316 + return 0;
  317 +}
  318 +
  319 +security_initcall(yama_init);