aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2008-05-19 08:32:49 -0400
committerJames Morris <jmorris@namei.org>2008-07-14 01:01:47 -0400
commit006ebb40d3d65338bd74abb03b945f8d60e362bd (patch)
treec548c678b54b307e1fb9acf94676fb7bfd849501 /security
parentfeb2a5b82d87fbdc01c00b7e9413e4b5f4c1f0c1 (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 'security')
-rw-r--r--security/commoncap.c3
-rw-r--r--security/dummy.c3
-rw-r--r--security/security.c5
-rw-r--r--security/selinux/hooks.c13
-rw-r--r--security/smack/smack_lsm.c5
5 files changed, 21 insertions, 8 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 33d343308413..0b6537a3672d 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -63,7 +63,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
63 return 0; 63 return 0;
64} 64}
65 65
66int cap_ptrace (struct task_struct *parent, struct task_struct *child) 66int cap_ptrace (struct task_struct *parent, struct task_struct *child,
67 unsigned int mode)
67{ 68{
68 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ 69 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
69 if (!cap_issubset(child->cap_permitted, parent->cap_permitted) && 70 if (!cap_issubset(child->cap_permitted, parent->cap_permitted) &&
diff --git a/security/dummy.c b/security/dummy.c
index b8916883b77f..1db712d99dc7 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -30,7 +30,8 @@
30#include <linux/prctl.h> 30#include <linux/prctl.h>
31#include <linux/securebits.h> 31#include <linux/securebits.h>
32 32
33static int dummy_ptrace (struct task_struct *parent, struct task_struct *child) 33static int dummy_ptrace (struct task_struct *parent, struct task_struct *child,
34 unsigned int mode)
34{ 35{
35 return 0; 36 return 0;
36} 37}
diff --git a/security/security.c b/security/security.c
index 59838a99b80e..c4507ce2a5a0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -161,9 +161,10 @@ int mod_reg_security(const char *name, struct security_operations *ops)
161 161
162/* Security operations */ 162/* Security operations */
163 163
164int security_ptrace(struct task_struct *parent, struct task_struct *child) 164int security_ptrace(struct task_struct *parent, struct task_struct *child,
165 unsigned int mode)
165{ 166{
166 return security_ops->ptrace(parent, child); 167 return security_ops->ptrace(parent, child, mode);
167} 168}
168 169
169int security_capget(struct task_struct *target, 170int security_capget(struct task_struct *target,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index eca70f42e678..4be156334b22 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1686,14 +1686,23 @@ static inline u32 file_to_av(struct file *file)
1686 1686
1687/* Hook functions begin here. */ 1687/* Hook functions begin here. */
1688 1688
1689static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) 1689static int selinux_ptrace(struct task_struct *parent,
1690 struct task_struct *child,
1691 unsigned int mode)
1690{ 1692{
1691 int rc; 1693 int rc;
1692 1694
1693 rc = secondary_ops->ptrace(parent, child); 1695 rc = secondary_ops->ptrace(parent, child, mode);
1694 if (rc) 1696 if (rc)
1695 return rc; 1697 return rc;
1696 1698
1699 if (mode == PTRACE_MODE_READ) {
1700 struct task_security_struct *tsec = parent->security;
1701 struct task_security_struct *csec = child->security;
1702 return avc_has_perm(tsec->sid, csec->sid,
1703 SECCLASS_FILE, FILE__READ, NULL);
1704 }
1705
1697 return task_has_perm(parent, child, PROCESS__PTRACE); 1706 return task_has_perm(parent, child, PROCESS__PTRACE);
1698} 1707}
1699 1708
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 4a09293efa00..3c7150b3493d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -95,11 +95,12 @@ struct inode_smack *new_inode_smack(char *smack)
95 * 95 *
96 * Do the capability checks, and require read and write. 96 * Do the capability checks, and require read and write.
97 */ 97 */
98static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp) 98static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp,
99 unsigned int mode)
99{ 100{
100 int rc; 101 int rc;
101 102
102 rc = cap_ptrace(ptp, ctp); 103 rc = cap_ptrace(ptp, ctp, mode);
103 if (rc != 0) 104 if (rc != 0)
104 return rc; 105 return rc;
105 106