aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c9
-rw-r--r--fs/proc/task_mmu.c6
-rw-r--r--fs/proc/task_nommu.c2
-rw-r--r--include/linux/ptrace.h8
-rw-r--r--include/linux/security.h16
-rw-r--r--kernel/ptrace.c15
-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
11 files changed, 55 insertions, 30 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);
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index f98501ba557e..c6f5f9dd0cee 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -95,8 +95,12 @@ extern void __ptrace_link(struct task_struct *child,
95 struct task_struct *new_parent); 95 struct task_struct *new_parent);
96extern void __ptrace_unlink(struct task_struct *child); 96extern void __ptrace_unlink(struct task_struct *child);
97extern void ptrace_untrace(struct task_struct *child); 97extern void ptrace_untrace(struct task_struct *child);
98extern int ptrace_may_attach(struct task_struct *task); 98#define PTRACE_MODE_READ 1
99extern int __ptrace_may_attach(struct task_struct *task); 99#define PTRACE_MODE_ATTACH 2
100/* Returns 0 on success, -errno on denial. */
101extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
102/* Returns true on success, false on denial. */
103extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
100 104
101static inline int ptrace_reparented(struct task_struct *child) 105static inline int ptrace_reparented(struct task_struct *child)
102{ 106{
diff --git a/include/linux/security.h b/include/linux/security.h
index 50737c70e78e..62bd80cb7f87 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -46,7 +46,8 @@ struct audit_krule;
46 */ 46 */
47extern int cap_capable(struct task_struct *tsk, int cap); 47extern int cap_capable(struct task_struct *tsk, int cap);
48extern int cap_settime(struct timespec *ts, struct timezone *tz); 48extern int cap_settime(struct timespec *ts, struct timezone *tz);
49extern int cap_ptrace(struct task_struct *parent, struct task_struct *child); 49extern int cap_ptrace(struct task_struct *parent, struct task_struct *child,
50 unsigned int mode);
50extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); 51extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
51extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); 52extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
52extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); 53extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -1170,6 +1171,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
1170 * attributes would be changed by the execve. 1171 * attributes would be changed by the execve.
1171 * @parent contains the task_struct structure for parent process. 1172 * @parent contains the task_struct structure for parent process.
1172 * @child contains the task_struct structure for child process. 1173 * @child contains the task_struct structure for child process.
1174 * @mode contains the PTRACE_MODE flags indicating the form of access.
1173 * Return 0 if permission is granted. 1175 * Return 0 if permission is granted.
1174 * @capget: 1176 * @capget:
1175 * Get the @effective, @inheritable, and @permitted capability sets for 1177 * Get the @effective, @inheritable, and @permitted capability sets for
@@ -1295,7 +1297,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
1295struct security_operations { 1297struct security_operations {
1296 char name[SECURITY_NAME_MAX + 1]; 1298 char name[SECURITY_NAME_MAX + 1];
1297 1299
1298 int (*ptrace) (struct task_struct *parent, struct task_struct *child); 1300 int (*ptrace) (struct task_struct *parent, struct task_struct *child,
1301 unsigned int mode);
1299 int (*capget) (struct task_struct *target, 1302 int (*capget) (struct task_struct *target,
1300 kernel_cap_t *effective, 1303 kernel_cap_t *effective,
1301 kernel_cap_t *inheritable, kernel_cap_t *permitted); 1304 kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -1573,7 +1576,8 @@ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *par
1573extern void securityfs_remove(struct dentry *dentry); 1576extern void securityfs_remove(struct dentry *dentry);
1574 1577
1575/* Security operations */ 1578/* Security operations */
1576int security_ptrace(struct task_struct *parent, struct task_struct *child); 1579int security_ptrace(struct task_struct *parent, struct task_struct *child,
1580 unsigned int mode);
1577int security_capget(struct task_struct *target, 1581int security_capget(struct task_struct *target,
1578 kernel_cap_t *effective, 1582 kernel_cap_t *effective,
1579 kernel_cap_t *inheritable, 1583 kernel_cap_t *inheritable,
@@ -1755,9 +1759,11 @@ static inline int security_init(void)
1755 return 0; 1759 return 0;
1756} 1760}
1757 1761
1758static inline int security_ptrace(struct task_struct *parent, struct task_struct *child) 1762static inline int security_ptrace(struct task_struct *parent,
1763 struct task_struct *child,
1764 unsigned int mode)
1759{ 1765{
1760 return cap_ptrace(parent, child); 1766 return cap_ptrace(parent, child, mode);
1761} 1767}
1762 1768
1763static inline int security_capget(struct task_struct *target, 1769static inline int security_capget(struct task_struct *target,
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 6c19e94fd0a5..e337390fce01 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -121,7 +121,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
121 return ret; 121 return ret;
122} 122}
123 123
124int __ptrace_may_attach(struct task_struct *task) 124int __ptrace_may_access(struct task_struct *task, unsigned int mode)
125{ 125{
126 /* May we inspect the given task? 126 /* May we inspect the given task?
127 * This check is used both for attaching with ptrace 127 * This check is used both for attaching with ptrace
@@ -148,16 +148,16 @@ int __ptrace_may_attach(struct task_struct *task)
148 if (!dumpable && !capable(CAP_SYS_PTRACE)) 148 if (!dumpable && !capable(CAP_SYS_PTRACE))
149 return -EPERM; 149 return -EPERM;
150 150
151 return security_ptrace(current, task); 151 return security_ptrace(current, task, mode);
152} 152}
153 153
154int ptrace_may_attach(struct task_struct *task) 154bool ptrace_may_access(struct task_struct *task, unsigned int mode)
155{ 155{
156 int err; 156 int err;
157 task_lock(task); 157 task_lock(task);
158 err = __ptrace_may_attach(task); 158 err = __ptrace_may_access(task, mode);
159 task_unlock(task); 159 task_unlock(task);
160 return !err; 160 return (!err ? true : false);
161} 161}
162 162
163int ptrace_attach(struct task_struct *task) 163int ptrace_attach(struct task_struct *task)
@@ -195,7 +195,7 @@ repeat:
195 /* the same process cannot be attached many times */ 195 /* the same process cannot be attached many times */
196 if (task->ptrace & PT_PTRACED) 196 if (task->ptrace & PT_PTRACED)
197 goto bad; 197 goto bad;
198 retval = __ptrace_may_attach(task); 198 retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
199 if (retval) 199 if (retval)
200 goto bad; 200 goto bad;
201 201
@@ -494,7 +494,8 @@ int ptrace_traceme(void)
494 */ 494 */
495 task_lock(current); 495 task_lock(current);
496 if (!(current->ptrace & PT_PTRACED)) { 496 if (!(current->ptrace & PT_PTRACED)) {
497 ret = security_ptrace(current->parent, current); 497 ret = security_ptrace(current->parent, current,
498 PTRACE_MODE_ATTACH);
498 /* 499 /*
499 * Set the ptrace bit in the process ptrace flags. 500 * Set the ptrace bit in the process ptrace flags.
500 */ 501 */
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