7c3591add94e1af62bd4e91e46a041e5aad927f9
[linux-flexiantxendom0-natty.git] / security / yama / yama_lsm.c
1 /*
2  * Yama Linux Security Module
3  *
4  * Author: Kees Cook <kees.cook@canonical.com>
5  *
6  * Copyright (C) 2010 Canonical, Ltd.
7  *
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.
11  *
12  */
13
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>
19
20 static int ptrace_scope = 1;
21 static int protected_sticky_symlinks = 1;
22 static int protected_nonaccess_hardlinks = 1;
23
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;
29 };
30
31 static LIST_HEAD(ptracer_relations);
32 static DEFINE_SPINLOCK(ptracer_relations_lock);
33
34 /**
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
38  *
39  * Returns 0 if relationship was added, -ve on error.
40  */
41 static int yama_ptracer_add(struct task_struct *tracer,
42                             struct task_struct *tracee)
43 {
44         int rc = 0;
45         struct ptrace_relation *added;
46         struct ptrace_relation *entry, *relation = NULL;
47
48         added = kmalloc(sizeof(*added), GFP_KERNEL);
49         spin_lock(&ptracer_relations_lock);
50         list_for_each_entry(entry, &ptracer_relations, node)
51                 if (entry->tracee == tracee) {
52                         relation = entry;
53                         break;
54                 }
55         if (!relation) {
56                 relation = added;
57                 if (!relation) {
58                         rc = -ENOMEM;
59                         goto unlock_out;
60                 }
61                 relation->tracee = tracee;
62                 list_add(&relation->node, &ptracer_relations);
63         }
64         relation->tracer = tracer;
65
66 unlock_out:
67         spin_unlock(&ptracer_relations_lock);
68         if (added && 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;
83         struct list_head *list, *safe;
84
85         spin_lock(&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);
91                         kfree(relation);
92                 }
93         }
94         spin_unlock(&ptracer_relations_lock);
95 }
96
97 /**
98  * yama_task_free - check for task_pid to remove from exception list
99  * @task: task being removed
100  */
101 void yama_task_free(struct task_struct *task)
102 {
103         yama_ptracer_del(task, task);
104 }
105
106 /**
107  * yama_task_prctl - check for Yama-specific prctl operations
108  * @option: operation
109  * @arg2: argument
110  * @arg3: argument
111  * @arg4: argument
112  * @arg5: argument
113  *
114  * Return 0 on success, -ve on error.  -ENOSYS is returned when Yama
115  * does not handle the given option.
116  */
117 int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
118                            unsigned long arg4, unsigned long arg5)
119 {
120         int rc;
121
122         rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
123         if (rc != -ENOSYS)
124                 return rc;
125
126         switch (option) {
127         case PR_SET_PTRACER:
128                 if (arg2 == 0) {
129                         yama_ptracer_del(NULL, current);
130                         rc = 0;
131                 }
132                 else {
133                         struct task_struct *tracer;
134                         struct task_struct *myself = current;
135
136                         rcu_read_lock();
137                         if (!thread_group_leader(myself))
138                                 myself = myself->group_leader;
139                         get_task_struct(myself);
140                         tracer = find_task_by_vpid(arg2);
141                         if (tracer)
142                                 get_task_struct(tracer);
143                         else
144                                 rc = -EINVAL;
145                         rcu_read_unlock();
146
147                         if (tracer) {
148                                 rc = yama_ptracer_add(tracer, myself);
149                                 put_task_struct(tracer);
150                         }
151                         put_task_struct(myself);
152                 }
153                 break;
154         }
155
156         return rc;
157 }
158
159 /**
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
163  *
164  * Returns 1 if child is a descendant of parent, 0 if not.
165  */
166 static int task_is_descendant(struct task_struct *parent,
167                               struct task_struct *child)
168 {
169         int rc = 0;
170         struct task_struct *walker = child;
171
172         if (!parent || !child)
173                 return 0;
174
175         rcu_read_lock();
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) {
183                         rc = 1;
184                         break;
185                 }
186                 walker = walker->real_parent;
187         }
188         read_unlock(&tasklist_lock);
189         rcu_read_unlock();
190
191         return rc;
192 }
193
194 /**
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
198  *
199  * Returns 1 if tracer has is ptracer exception ancestor for tracee.
200  */
201 static int ptracer_exception_found(struct task_struct *tracer,
202                                    struct task_struct *tracee)
203 {
204         int rc = 0;
205         struct ptrace_relation *relation;
206         struct task_struct *parent = NULL;
207
208         spin_lock(&ptracer_relations_lock);
209
210         rcu_read_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;
217                         break;
218                 }
219         read_unlock(&tasklist_lock);
220         rcu_read_unlock();
221
222         if (task_is_descendant(parent, tracer))
223                 rc = 1;
224         spin_unlock(&ptracer_relations_lock);
225
226         return rc;
227 }
228
229 /**
230  * yama_ptrace_access_check - validate PTRACE_ATTACH calls
231  * @child: task that current task is attempting to PTRACE
232  * @mode: ptrace attach mode
233  *
234  * Returns 0 if following the ptrace is allowed, -ve on error.
235  */
236 int yama_ptrace_access_check(struct task_struct *child,
237                                     unsigned int mode)
238 {
239         int rc;
240
241         /* If standard caps disallows it, so does Yama.  We should
242          * only tighten restrictions further.
243          */
244         rc = cap_ptrace_access_check(child, mode);
245         if (rc)
246                 return rc;
247
248         /* require ptrace target be a child of ptracer on attach */
249         if (mode == PTRACE_MODE_ATTACH &&
250             ptrace_scope &&
251             !capable(CAP_SYS_PTRACE) &&
252             !task_is_descendant(current, child) &&
253             !ptracer_exception_found(current, child))
254                 rc = -EPERM;
255
256         if (rc) {
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",
260                         child->pid,
261                         get_task_comm(name, current),
262                         current->pid);
263         }
264
265         return rc;
266 }
267
268 /**
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
272  *
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.
281  *
282  * Returns 0 if following the symlink is allowed, -ve on error.
283  */
284 int yama_inode_follow_link(struct dentry *dentry,
285                                   struct nameidata *nameidata)
286 {
287         int rc = 0;
288         const struct inode *parent;
289         const struct inode *inode;
290         const struct cred *cred;
291
292         if (!protected_sticky_symlinks)
293                 return 0;
294
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))
298                 return 0;
299
300         /* owner and follower match? */
301         cred = current_cred();
302         if (cred->fsuid == inode->i_uid)
303                 return 0;
304
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) {
310                 rc = -EACCES;
311         }
312         spin_unlock(&dentry->d_lock);
313
314         if (rc) {
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);
321         }
322
323         return rc;
324 }
325
326 /**
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
331  *
332  * Block hardlink when all of:
333  *  - fsuid does not match inode
334  *  - not CAP_FOWNER
335  *  - and at least one of:
336  *    - inode is not a regular file
337  *    - inode is setuid
338  *    - inode is setgid and group-exec
339  *    - access failure for read and write
340  *
341  * Returns 0 if successful, -ve on error.
342  */
343 int yama_path_link(struct dentry *old_dentry, struct path *new_dir,
344                           struct dentry *new_dentry)
345 {
346         int rc = 0;
347         struct inode *inode = old_dentry->d_inode;
348         const int mode = inode->i_mode;
349         const struct cred *cred = current_cred();
350
351         if (!protected_nonaccess_hardlinks)
352                 return 0;
353
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),
363                         cred->fsuid);
364                 rc = -EPERM;
365         }
366
367         return rc;
368 }
369
370 static struct security_operations yama_ops = {
371         .name =                 "yama",
372
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,
378 };
379
380 #ifdef CONFIG_SYSCTL
381 static int zero;
382 static int one = 1;
383
384 struct ctl_path yama_sysctl_path[] = {
385         { .procname = "kernel", },
386         { .procname = "yama", },
387         { }
388 };
389
390 static struct ctl_table yama_sysctl_table[] = {
391         {
392                 .procname       = "protected_sticky_symlinks",
393                 .data           = &protected_sticky_symlinks,
394                 .maxlen         = sizeof(int),
395                 .mode           = 0644,
396                 .proc_handler   = proc_dointvec_minmax,
397                 .extra1         = &zero,
398                 .extra2         = &one,
399         },
400         {
401                 .procname       = "protected_nonaccess_hardlinks",
402                 .data           = &protected_nonaccess_hardlinks,
403                 .maxlen         = sizeof(int),
404                 .mode           = 0644,
405                 .proc_handler   = proc_dointvec_minmax,
406                 .extra1         = &zero,
407                 .extra2         = &one,
408         },
409         {
410                 .procname       = "ptrace_scope",
411                 .data           = &ptrace_scope,
412                 .maxlen         = sizeof(int),
413                 .mode           = 0644,
414                 .proc_handler   = proc_dointvec_minmax,
415                 .extra1         = &zero,
416                 .extra2         = &one,
417         },
418         { }
419 };
420 #endif /* CONFIG_SYSCTL */
421
422 static __init int yama_init(void)
423 {
424         printk(KERN_INFO "Yama: becoming mindful.\n");
425
426 #ifdef CONFIG_SYSCTL
427         if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
428                 panic("Yama: sysctl registration failed.\n");
429 #endif
430
431         if (!security_module_enable(&yama_ops))
432                 return 0;
433
434         if (register_security(&yama_ops))
435                 panic("Yama: kernel registration failed.\n");
436
437         return 0;
438 }
439
440 security_initcall(yama_init);