2 * Yama Linux Security Module
4 * Author: Kees Cook <kees.cook@canonical.com>
6 * Copyright (C) 2010 Canonical, Ltd.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2, as
10 * published by the Free Software Foundation.
14 #include <linux/security.h>
15 #include <linux/sysctl.h>
16 #include <linux/ptrace.h>
17 #include <linux/prctl.h>
18 #include <linux/ratelimit.h>
20 static int ptrace_scope = 1;
21 static int protected_sticky_symlinks = 1;
22 static int protected_nonaccess_hardlinks = 1;
24 /* describe a PTRACE relationship for potential exception */
25 struct ptrace_relation {
26 struct task_struct *tracer;
27 struct task_struct *tracee;
28 struct list_head node;
31 static LIST_HEAD(ptracer_relations);
32 static DEFINE_SPINLOCK(ptracer_relations_lock);
35 * yama_ptracer_add - add/replace an exception for this tracer/tracee pair
36 * @tracer: the task_struct of the process doing the PTRACE
37 * @tracee: the task_struct of the process to be PTRACEd
39 * Returns 0 if relationship was added, -ve on error.
41 static int yama_ptracer_add(struct task_struct *tracer,
42 struct task_struct *tracee)
45 struct ptrace_relation *added;
46 struct ptrace_relation *entry, *relation = NULL;
48 added = kmalloc(sizeof(*added), GFP_KERNEL);
49 spin_lock_bh(&ptracer_relations_lock);
50 list_for_each_entry(entry, &ptracer_relations, node)
51 if (entry->tracee == tracee) {
61 relation->tracee = tracee;
62 list_add(&relation->node, &ptracer_relations);
64 relation->tracer = tracer;
67 spin_unlock_bh(&ptracer_relations_lock);
68 if (added && added != relation)
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
79 static void yama_ptracer_del(struct task_struct *tracer,
80 struct task_struct *tracee)
82 struct ptrace_relation *relation;
83 struct list_head *list, *safe;
85 spin_lock_bh(&ptracer_relations_lock);
86 list_for_each_safe(list, safe, &ptracer_relations) {
87 relation = list_entry(list, struct ptrace_relation, node);
88 if (relation->tracee == tracee ||
89 relation->tracer == tracer) {
90 list_del(&relation->node);
94 spin_unlock_bh(&ptracer_relations_lock);
98 * yama_task_free - check for task_pid to remove from exception list
99 * @task: task being removed
101 void yama_task_free(struct task_struct *task)
103 yama_ptracer_del(task, task);
107 * yama_task_prctl - check for Yama-specific prctl operations
114 * Return 0 on success, -ve on error. -ENOSYS is returned when Yama
115 * does not handle the given option.
117 int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
118 unsigned long arg4, unsigned long arg5)
122 rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
129 yama_ptracer_del(NULL, current);
133 struct task_struct *tracer;
134 struct task_struct *myself = current;
137 if (!thread_group_leader(myself))
138 myself = myself->group_leader;
139 get_task_struct(myself);
140 tracer = find_task_by_vpid(arg2);
142 get_task_struct(tracer);
148 rc = yama_ptracer_add(tracer, myself);
149 put_task_struct(tracer);
151 put_task_struct(myself);
160 * task_is_descendant - walk up a process family tree looking for a match
161 * @parent: the process to compare against while walking up from child
162 * @child: the process to start from while looking upwards for parent
164 * Returns 1 if child is a descendant of parent, 0 if not.
166 static int task_is_descendant(struct task_struct *parent,
167 struct task_struct *child)
170 struct task_struct *walker = child;
172 if (!parent || !child)
176 read_lock(&tasklist_lock);
177 if (!thread_group_leader(parent))
178 parent = parent->group_leader;
179 while (walker->pid > 0) {
180 if (!thread_group_leader(walker))
181 walker = walker->group_leader;
182 if (walker == parent) {
186 walker = walker->real_parent;
188 read_unlock(&tasklist_lock);
195 * ptracer_exception_found - tracer registered as exception for this tracee
196 * @tracer: the task_struct of the process attempting PTRACE
197 * @tracee: the task_struct of the process to be PTRACEd
199 * Returns 1 if tracer has is ptracer exception ancestor for tracee.
201 static int ptracer_exception_found(struct task_struct *tracer,
202 struct task_struct *tracee)
205 struct ptrace_relation *relation;
206 struct task_struct *parent = NULL;
208 spin_lock_bh(&ptracer_relations_lock);
211 read_lock(&tasklist_lock);
212 if (!thread_group_leader(tracee))
213 tracee = tracee->group_leader;
214 list_for_each_entry(relation, &ptracer_relations, node)
215 if (relation->tracee == tracee) {
216 parent = relation->tracer;
219 read_unlock(&tasklist_lock);
222 if (task_is_descendant(parent, tracer))
224 spin_unlock_bh(&ptracer_relations_lock);
230 * yama_ptrace_access_check - validate PTRACE_ATTACH calls
231 * @child: task that current task is attempting to PTRACE
232 * @mode: ptrace attach mode
234 * Returns 0 if following the ptrace is allowed, -ve on error.
236 int yama_ptrace_access_check(struct task_struct *child,
241 /* If standard caps disallows it, so does Yama. We should
242 * only tighten restrictions further.
244 rc = cap_ptrace_access_check(child, mode);
248 /* require ptrace target be a child of ptracer on attach */
249 if (mode == PTRACE_MODE_ATTACH &&
251 !capable(CAP_SYS_PTRACE) &&
252 !task_is_descendant(current, child) &&
253 !ptracer_exception_found(current, child))
257 char name[sizeof(current->comm)];
258 printk_ratelimited(KERN_INFO "ptrace of non-child"
259 " pid %d was attempted by: %s (pid %d)\n",
261 get_task_comm(name, current),
269 * yama_inode_follow_link - check for symlinks in sticky world-writeable dirs
270 * @dentry: The inode/dentry of the symlink
271 * @nameidata: The path data of the symlink
273 * In the case of the protected_sticky_symlinks sysctl being enabled,
274 * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is
275 * in a sticky world-writable directory. This is to protect privileged
276 * processes from failing races against path names that may change out
277 * from under them by way of other users creating malicious symlinks.
278 * It will permit symlinks to only be followed when outside a sticky
279 * world-writable directory, or when the uid of the symlink and follower
280 * match, or when the directory owner matches the symlink's owner.
282 * Returns 0 if following the symlink is allowed, -ve on error.
284 int yama_inode_follow_link(struct dentry *dentry,
285 struct nameidata *nameidata)
288 const struct inode *parent;
289 const struct inode *inode;
290 const struct cred *cred;
292 if (!protected_sticky_symlinks)
295 /* if inode isn't a symlink, don't try to evaluate blocking it */
296 inode = dentry->d_inode;
297 if (!S_ISLNK(inode->i_mode))
300 /* owner and follower match? */
301 cred = current_cred();
302 if (cred->fsuid == inode->i_uid)
305 /* check parent directory mode and owner */
306 spin_lock(&dentry->d_lock);
307 parent = dentry->d_parent->d_inode;
308 if ((parent->i_mode & (S_ISVTX|S_IWOTH)) == (S_ISVTX|S_IWOTH) &&
309 parent->i_uid != inode->i_uid) {
312 spin_unlock(&dentry->d_lock);
315 char name[sizeof(current->comm)];
316 printk_ratelimited(KERN_NOTICE "non-matching-uid symlink "
317 "following attempted in sticky world-writable "
318 "directory by %s (fsuid %d != %d)\n",
319 get_task_comm(name, current),
320 cred->fsuid, inode->i_uid);
327 * yama_path_link - verify that hardlinking is allowed
328 * @old_dentry: the source inode/dentry to hardlink from
329 * @new_dir: target directory
330 * @new_dentry: the target inode/dentry to hardlink to
332 * Block hardlink when all of:
333 * - fsuid does not match inode
335 * - and at least one of:
336 * - inode is not a regular file
338 * - inode is setgid and group-exec
339 * - access failure for read and write
341 * Returns 0 if successful, -ve on error.
343 int yama_path_link(struct dentry *old_dentry, struct path *new_dir,
344 struct dentry *new_dentry)
347 struct inode *inode = old_dentry->d_inode;
348 const int mode = inode->i_mode;
349 const struct cred *cred = current_cred();
351 if (!protected_nonaccess_hardlinks)
354 if (cred->fsuid != inode->i_uid &&
355 (!S_ISREG(mode) || (mode & S_ISUID) ||
356 ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
357 (generic_permission(inode, MAY_READ | MAY_WRITE, 0, NULL))) &&
358 !capable(CAP_FOWNER)) {
359 char name[sizeof(current->comm)];
360 printk_ratelimited(KERN_INFO "non-accessible hardlink"
361 " creation was attempted by: %s (fsuid %d)\n",
362 get_task_comm(name, current),
370 static struct security_operations yama_ops = {
373 .ptrace_access_check = yama_ptrace_access_check,
374 .inode_follow_link = yama_inode_follow_link,
375 .path_link = yama_path_link,
376 .task_prctl = yama_task_prctl,
377 .task_free = yama_task_free,
384 struct ctl_path yama_sysctl_path[] = {
385 { .procname = "kernel", },
386 { .procname = "yama", },
390 static struct ctl_table yama_sysctl_table[] = {
392 .procname = "protected_sticky_symlinks",
393 .data = &protected_sticky_symlinks,
394 .maxlen = sizeof(int),
396 .proc_handler = proc_dointvec_minmax,
401 .procname = "protected_nonaccess_hardlinks",
402 .data = &protected_nonaccess_hardlinks,
403 .maxlen = sizeof(int),
405 .proc_handler = proc_dointvec_minmax,
410 .procname = "ptrace_scope",
411 .data = &ptrace_scope,
412 .maxlen = sizeof(int),
414 .proc_handler = proc_dointvec_minmax,
420 #endif /* CONFIG_SYSCTL */
422 static __init int yama_init(void)
424 printk(KERN_INFO "Yama: becoming mindful.\n");
427 if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
428 panic("Yama: sysctl registration failed.\n");
431 if (!security_module_enable(&yama_ops))
434 if (register_security(&yama_ops))
435 panic("Yama: kernel registration failed.\n");
440 security_initcall(yama_init);