diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2008-05-19 08:32:49 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-07-14 01:01:47 -0400 |
commit | 006ebb40d3d65338bd74abb03b945f8d60e362bd (patch) | |
tree | c548c678b54b307e1fb9acf94676fb7bfd849501 /fs/proc | |
parent | feb2a5b82d87fbdc01c00b7e9413e4b5f4c1f0c1 (diff) |
Security: split proc ptrace checking into read vs. attach
Enable security modules to distinguish reading of process state via
proc from full ptrace access by renaming ptrace_may_attach to
ptrace_may_access and adding a mode argument indicating whether only
read access or full attach access is requested. This allows security
modules to permit access to reading process state without granting
full ptrace access. The base DAC/capability checking remains unchanged.
Read access to /proc/pid/mem continues to apply a full ptrace attach
check since check_mem_permission() already requires the current task
to already be ptracing the target. The other ptrace checks within
proc for elements like environ, maps, and fds are changed to pass the
read mode instead of attach.
In the SELinux case, we model such reading of process state as a
reading of a proc file labeled with the target process' label. This
enables SELinux policy to permit such reading of process state without
permitting control or manipulation of the target process, as there are
a number of cases where programs probe for such information via proc
but do not need to be able to control the target (e.g. procps,
lsof, PolicyKit, ConsoleKit). At present we have to choose between
allowing full ptrace in policy (more permissive than required/desired)
or breaking functionality (or in some cases just silencing the denials
via dontaudit rules but this can hide genuine attacks).
This version of the patch incorporates comments from Casey Schaufler
(change/replace existing ptrace_may_attach interface, pass access
mode), and Chris Wright (provide greater consistency in the checking).
Note that like their predecessors __ptrace_may_attach and
ptrace_may_attach, the __ptrace_may_access and ptrace_may_access
interfaces use different return value conventions from each other (0
or -errno vs. 1 or 0). I retained this difference to avoid any
changes to the caller logic but made the difference clearer by
changing the latter interface to return a bool rather than an int and
by adding a comment about it to ptrace.h for any future callers.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/base.c | 9 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 6 | ||||
-rw-r--r-- | fs/proc/task_nommu.c | 2 |
3 files changed, 9 insertions, 8 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 3b455371e7ff..58c3e6a8e15e 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -233,7 +233,7 @@ static int check_mem_permission(struct task_struct *task) | |||
233 | */ | 233 | */ |
234 | if (task->parent == current && (task->ptrace & PT_PTRACED) && | 234 | if (task->parent == current && (task->ptrace & PT_PTRACED) && |
235 | task_is_stopped_or_traced(task) && | 235 | task_is_stopped_or_traced(task) && |
236 | ptrace_may_attach(task)) | 236 | ptrace_may_access(task, PTRACE_MODE_ATTACH)) |
237 | return 0; | 237 | return 0; |
238 | 238 | ||
239 | /* | 239 | /* |
@@ -251,7 +251,8 @@ struct mm_struct *mm_for_maps(struct task_struct *task) | |||
251 | task_lock(task); | 251 | task_lock(task); |
252 | if (task->mm != mm) | 252 | if (task->mm != mm) |
253 | goto out; | 253 | goto out; |
254 | if (task->mm != current->mm && __ptrace_may_attach(task) < 0) | 254 | if (task->mm != current->mm && |
255 | __ptrace_may_access(task, PTRACE_MODE_READ) < 0) | ||
255 | goto out; | 256 | goto out; |
256 | task_unlock(task); | 257 | task_unlock(task); |
257 | return mm; | 258 | return mm; |
@@ -518,7 +519,7 @@ static int proc_fd_access_allowed(struct inode *inode) | |||
518 | */ | 519 | */ |
519 | task = get_proc_task(inode); | 520 | task = get_proc_task(inode); |
520 | if (task) { | 521 | if (task) { |
521 | allowed = ptrace_may_attach(task); | 522 | allowed = ptrace_may_access(task, PTRACE_MODE_READ); |
522 | put_task_struct(task); | 523 | put_task_struct(task); |
523 | } | 524 | } |
524 | return allowed; | 525 | return allowed; |
@@ -904,7 +905,7 @@ static ssize_t environ_read(struct file *file, char __user *buf, | |||
904 | if (!task) | 905 | if (!task) |
905 | goto out_no_task; | 906 | goto out_no_task; |
906 | 907 | ||
907 | if (!ptrace_may_attach(task)) | 908 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) |
908 | goto out; | 909 | goto out; |
909 | 910 | ||
910 | ret = -ENOMEM; | 911 | ret = -ENOMEM; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index c492449f3b45..164bd9f9ede3 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -210,7 +210,7 @@ static int show_map(struct seq_file *m, void *v) | |||
210 | dev_t dev = 0; | 210 | dev_t dev = 0; |
211 | int len; | 211 | int len; |
212 | 212 | ||
213 | if (maps_protect && !ptrace_may_attach(task)) | 213 | if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) |
214 | return -EACCES; | 214 | return -EACCES; |
215 | 215 | ||
216 | if (file) { | 216 | if (file) { |
@@ -646,7 +646,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
646 | goto out; | 646 | goto out; |
647 | 647 | ||
648 | ret = -EACCES; | 648 | ret = -EACCES; |
649 | if (!ptrace_may_attach(task)) | 649 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) |
650 | goto out_task; | 650 | goto out_task; |
651 | 651 | ||
652 | ret = -EINVAL; | 652 | ret = -EINVAL; |
@@ -747,7 +747,7 @@ static int show_numa_map_checked(struct seq_file *m, void *v) | |||
747 | struct proc_maps_private *priv = m->private; | 747 | struct proc_maps_private *priv = m->private; |
748 | struct task_struct *task = priv->task; | 748 | struct task_struct *task = priv->task; |
749 | 749 | ||
750 | if (maps_protect && !ptrace_may_attach(task)) | 750 | if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) |
751 | return -EACCES; | 751 | return -EACCES; |
752 | 752 | ||
753 | return show_numa_map(m, v); | 753 | return show_numa_map(m, v); |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 4b4f9cc2f186..5d84e7121df8 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
@@ -113,7 +113,7 @@ static int show_map(struct seq_file *m, void *_vml) | |||
113 | struct proc_maps_private *priv = m->private; | 113 | struct proc_maps_private *priv = m->private; |
114 | struct task_struct *task = priv->task; | 114 | struct task_struct *task = priv->task; |
115 | 115 | ||
116 | if (maps_protect && !ptrace_may_attach(task)) | 116 | if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) |
117 | return -EACCES; | 117 | return -EACCES; |
118 | 118 | ||
119 | return nommu_vma_show(m, vml->vma); | 119 | return nommu_vma_show(m, vml->vma); |