diff options
author | David Howells <dhowells@redhat.com> | 2008-08-14 06:37:28 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-08-14 08:59:43 -0400 |
commit | 5cd9c58fbe9ec92b45b27e131719af4f2bd9eb40 (patch) | |
tree | 8573db001b4dc3c2ad97102dda42b841c40b5f6c /include | |
parent | 8d0968abd03ec6b407df117adc773562386702fa (diff) |
security: Fix setting of PF_SUPERPRIV by __capable()
Fix the setting of PF_SUPERPRIV by __capable() as it could corrupt the flags
the target process if that is not the current process and it is trying to
change its own flags in a different way at the same time.
__capable() is using neither atomic ops nor locking to protect t->flags. This
patch removes __capable() and introduces has_capability() that doesn't set
PF_SUPERPRIV on the process being queried.
This patch further splits security_ptrace() in two:
(1) security_ptrace_may_access(). This passes judgement on whether one
process may access another only (PTRACE_MODE_ATTACH for ptrace() and
PTRACE_MODE_READ for /proc), and takes a pointer to the child process.
current is the parent.
(2) security_ptrace_traceme(). This passes judgement on PTRACE_TRACEME only,
and takes only a pointer to the parent process. current is the child.
In Smack and commoncap, this uses has_capability() to determine whether
the parent will be permitted to use PTRACE_ATTACH if normal checks fail.
This does not set PF_SUPERPRIV.
Two of the instances of __capable() actually only act on current, and so have
been changed to calls to capable().
Of the places that were using __capable():
(1) The OOM killer calls __capable() thrice when weighing the killability of a
process. All of these now use has_capability().
(2) cap_ptrace() and smack_ptrace() were using __capable() to check to see
whether the parent was allowed to trace any process. As mentioned above,
these have been split. For PTRACE_ATTACH and /proc, capable() is now
used, and for PTRACE_TRACEME, has_capability() is used.
(3) cap_safe_nice() only ever saw current, so now uses capable().
(4) smack_setprocattr() rejected accesses to tasks other than current just
after calling __capable(), so the order of these two tests have been
switched and capable() is used instead.
(5) In smack_file_send_sigiotask(), we need to allow privileged processes to
receive SIGIO on files they're manipulating.
(6) In smack_task_wait(), we let a process wait for a privileged process,
whether or not the process doing the waiting is privileged.
I've tested this with the LTP SELinux and syscalls testscripts.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: Andrew G. Morgan <morgan@kernel.org>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/capability.h | 15 | ||||
-rw-r--r-- | include/linux/security.h | 39 |
2 files changed, 38 insertions, 16 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h index 02673846d205..9d1fe30b6f6c 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h | |||
@@ -503,8 +503,19 @@ extern const kernel_cap_t __cap_init_eff_set; | |||
503 | 503 | ||
504 | kernel_cap_t cap_set_effective(const kernel_cap_t pE_new); | 504 | kernel_cap_t cap_set_effective(const kernel_cap_t pE_new); |
505 | 505 | ||
506 | int capable(int cap); | 506 | /** |
507 | int __capable(struct task_struct *t, int cap); | 507 | * has_capability - Determine if a task has a superior capability available |
508 | * @t: The task in question | ||
509 | * @cap: The capability to be tested for | ||
510 | * | ||
511 | * Return true if the specified task has the given superior capability | ||
512 | * currently in effect, false if not. | ||
513 | * | ||
514 | * Note that this does not set PF_SUPERPRIV on the task. | ||
515 | */ | ||
516 | #define has_capability(t, cap) (security_capable((t), (cap)) == 0) | ||
517 | |||
518 | extern int capable(int cap); | ||
508 | 519 | ||
509 | #endif /* __KERNEL__ */ | 520 | #endif /* __KERNEL__ */ |
510 | 521 | ||
diff --git a/include/linux/security.h b/include/linux/security.h index fd96e7f8a6f9..2ee5ecfb2393 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -46,8 +46,8 @@ struct audit_krule; | |||
46 | */ | 46 | */ |
47 | extern int cap_capable(struct task_struct *tsk, int cap); | 47 | extern int cap_capable(struct task_struct *tsk, int cap); |
48 | extern int cap_settime(struct timespec *ts, struct timezone *tz); | 48 | extern int cap_settime(struct timespec *ts, struct timezone *tz); |
49 | extern int cap_ptrace(struct task_struct *parent, struct task_struct *child, | 49 | extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode); |
50 | unsigned int mode); | 50 | extern int cap_ptrace_traceme(struct task_struct *parent); |
51 | extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); | 51 | extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); |
52 | extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); | 52 | extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); |
53 | extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); | 53 | extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); |
@@ -1157,17 +1157,24 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1157 | * @alter contains the flag indicating whether changes are to be made. | 1157 | * @alter contains the flag indicating whether changes are to be made. |
1158 | * Return 0 if permission is granted. | 1158 | * Return 0 if permission is granted. |
1159 | * | 1159 | * |
1160 | * @ptrace: | 1160 | * @ptrace_may_access: |
1161 | * Check permission before allowing the @parent process to trace the | 1161 | * Check permission before allowing the current process to trace the |
1162 | * @child process. | 1162 | * @child process. |
1163 | * Security modules may also want to perform a process tracing check | 1163 | * Security modules may also want to perform a process tracing check |
1164 | * during an execve in the set_security or apply_creds hooks of | 1164 | * during an execve in the set_security or apply_creds hooks of |
1165 | * binprm_security_ops if the process is being traced and its security | 1165 | * binprm_security_ops if the process is being traced and its security |
1166 | * attributes would be changed by the execve. | 1166 | * attributes would be changed by the execve. |
1167 | * @parent contains the task_struct structure for parent process. | 1167 | * @child contains the task_struct structure for the target process. |
1168 | * @child contains the task_struct structure for child process. | ||
1169 | * @mode contains the PTRACE_MODE flags indicating the form of access. | 1168 | * @mode contains the PTRACE_MODE flags indicating the form of access. |
1170 | * Return 0 if permission is granted. | 1169 | * Return 0 if permission is granted. |
1170 | * @ptrace_traceme: | ||
1171 | * Check that the @parent process has sufficient permission to trace the | ||
1172 | * current process before allowing the current process to present itself | ||
1173 | * to the @parent process for tracing. | ||
1174 | * The parent process will still have to undergo the ptrace_may_access | ||
1175 | * checks before it is allowed to trace this one. | ||
1176 | * @parent contains the task_struct structure for debugger process. | ||
1177 | * Return 0 if permission is granted. | ||
1171 | * @capget: | 1178 | * @capget: |
1172 | * Get the @effective, @inheritable, and @permitted capability sets for | 1179 | * Get the @effective, @inheritable, and @permitted capability sets for |
1173 | * the @target process. The hook may also perform permission checking to | 1180 | * the @target process. The hook may also perform permission checking to |
@@ -1287,8 +1294,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1287 | struct security_operations { | 1294 | struct security_operations { |
1288 | char name[SECURITY_NAME_MAX + 1]; | 1295 | char name[SECURITY_NAME_MAX + 1]; |
1289 | 1296 | ||
1290 | int (*ptrace) (struct task_struct *parent, struct task_struct *child, | 1297 | int (*ptrace_may_access) (struct task_struct *child, unsigned int mode); |
1291 | unsigned int mode); | 1298 | int (*ptrace_traceme) (struct task_struct *parent); |
1292 | int (*capget) (struct task_struct *target, | 1299 | int (*capget) (struct task_struct *target, |
1293 | kernel_cap_t *effective, | 1300 | kernel_cap_t *effective, |
1294 | kernel_cap_t *inheritable, kernel_cap_t *permitted); | 1301 | kernel_cap_t *inheritable, kernel_cap_t *permitted); |
@@ -1560,8 +1567,8 @@ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *par | |||
1560 | extern void securityfs_remove(struct dentry *dentry); | 1567 | extern void securityfs_remove(struct dentry *dentry); |
1561 | 1568 | ||
1562 | /* Security operations */ | 1569 | /* Security operations */ |
1563 | int security_ptrace(struct task_struct *parent, struct task_struct *child, | 1570 | int security_ptrace_may_access(struct task_struct *child, unsigned int mode); |
1564 | unsigned int mode); | 1571 | int security_ptrace_traceme(struct task_struct *parent); |
1565 | int security_capget(struct task_struct *target, | 1572 | int security_capget(struct task_struct *target, |
1566 | kernel_cap_t *effective, | 1573 | kernel_cap_t *effective, |
1567 | kernel_cap_t *inheritable, | 1574 | kernel_cap_t *inheritable, |
@@ -1742,11 +1749,15 @@ static inline int security_init(void) | |||
1742 | return 0; | 1749 | return 0; |
1743 | } | 1750 | } |
1744 | 1751 | ||
1745 | static inline int security_ptrace(struct task_struct *parent, | 1752 | static inline int security_ptrace_may_access(struct task_struct *child, |
1746 | struct task_struct *child, | 1753 | unsigned int mode) |
1747 | unsigned int mode) | 1754 | { |
1755 | return cap_ptrace_may_access(child, mode); | ||
1756 | } | ||
1757 | |||
1758 | static inline int security_ptrace_traceme(struct task_struct *child) | ||
1748 | { | 1759 | { |
1749 | return cap_ptrace(parent, child, mode); | 1760 | return cap_ptrace_traceme(parent); |
1750 | } | 1761 | } |
1751 | 1762 | ||
1752 | static inline int security_capget(struct task_struct *target, | 1763 | static inline int security_capget(struct task_struct *target, |