diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-24 03:56:20 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-24 03:56:20 -0400 |
commit | ebdd90a8cb2e3963f55499850f02ce6003558b55 (patch) | |
tree | d153f917ed41d257ddafa22f9cc2201bfddf8f9c /security/selinux/hooks.c | |
parent | 3c9339049df5cc3a468c11de6c4101a1ea8c3d83 (diff) | |
parent | 72d31053f62c4bc464c2783974926969614a8649 (diff) |
Merge commit 'v2.6.27-rc7' into x86/pebs
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 85 |
1 files changed, 36 insertions, 49 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 63f131fc42e4..03fc6a81ae32 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/ptrace.h> | 28 | #include <linux/tracehook.h> |
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/security.h> | 31 | #include <linux/security.h> |
@@ -998,8 +998,12 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) | |||
998 | int rc; | 998 | int rc; |
999 | 999 | ||
1000 | rc = selinux_get_mnt_opts(sb, &opts); | 1000 | rc = selinux_get_mnt_opts(sb, &opts); |
1001 | if (rc) | 1001 | if (rc) { |
1002 | /* before policy load we may get EINVAL, don't show anything */ | ||
1003 | if (rc == -EINVAL) | ||
1004 | rc = 0; | ||
1002 | return rc; | 1005 | return rc; |
1006 | } | ||
1003 | 1007 | ||
1004 | selinux_write_opts(m, &opts); | 1008 | selinux_write_opts(m, &opts); |
1005 | 1009 | ||
@@ -1734,24 +1738,34 @@ static inline u32 file_to_av(struct file *file) | |||
1734 | 1738 | ||
1735 | /* Hook functions begin here. */ | 1739 | /* Hook functions begin here. */ |
1736 | 1740 | ||
1737 | static int selinux_ptrace(struct task_struct *parent, | 1741 | static int selinux_ptrace_may_access(struct task_struct *child, |
1738 | struct task_struct *child, | 1742 | unsigned int mode) |
1739 | unsigned int mode) | ||
1740 | { | 1743 | { |
1741 | int rc; | 1744 | int rc; |
1742 | 1745 | ||
1743 | rc = secondary_ops->ptrace(parent, child, mode); | 1746 | rc = secondary_ops->ptrace_may_access(child, mode); |
1744 | if (rc) | 1747 | if (rc) |
1745 | return rc; | 1748 | return rc; |
1746 | 1749 | ||
1747 | if (mode == PTRACE_MODE_READ) { | 1750 | if (mode == PTRACE_MODE_READ) { |
1748 | struct task_security_struct *tsec = parent->security; | 1751 | struct task_security_struct *tsec = current->security; |
1749 | struct task_security_struct *csec = child->security; | 1752 | struct task_security_struct *csec = child->security; |
1750 | return avc_has_perm(tsec->sid, csec->sid, | 1753 | return avc_has_perm(tsec->sid, csec->sid, |
1751 | SECCLASS_FILE, FILE__READ, NULL); | 1754 | SECCLASS_FILE, FILE__READ, NULL); |
1752 | } | 1755 | } |
1753 | 1756 | ||
1754 | return task_has_perm(parent, child, PROCESS__PTRACE); | 1757 | return task_has_perm(current, child, PROCESS__PTRACE); |
1758 | } | ||
1759 | |||
1760 | static int selinux_ptrace_traceme(struct task_struct *parent) | ||
1761 | { | ||
1762 | int rc; | ||
1763 | |||
1764 | rc = secondary_ops->ptrace_traceme(parent); | ||
1765 | if (rc) | ||
1766 | return rc; | ||
1767 | |||
1768 | return task_has_perm(parent, current, PROCESS__PTRACE); | ||
1755 | } | 1769 | } |
1756 | 1770 | ||
1757 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | 1771 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, |
@@ -1971,22 +1985,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
1971 | return __vm_enough_memory(mm, pages, cap_sys_admin); | 1985 | return __vm_enough_memory(mm, pages, cap_sys_admin); |
1972 | } | 1986 | } |
1973 | 1987 | ||
1974 | /** | ||
1975 | * task_tracer_task - return the task that is tracing the given task | ||
1976 | * @task: task to consider | ||
1977 | * | ||
1978 | * Returns NULL if noone is tracing @task, or the &struct task_struct | ||
1979 | * pointer to its tracer. | ||
1980 | * | ||
1981 | * Must be called under rcu_read_lock(). | ||
1982 | */ | ||
1983 | static struct task_struct *task_tracer_task(struct task_struct *task) | ||
1984 | { | ||
1985 | if (task->ptrace & PT_PTRACED) | ||
1986 | return rcu_dereference(task->parent); | ||
1987 | return NULL; | ||
1988 | } | ||
1989 | |||
1990 | /* binprm security operations */ | 1988 | /* binprm security operations */ |
1991 | 1989 | ||
1992 | static int selinux_bprm_alloc_security(struct linux_binprm *bprm) | 1990 | static int selinux_bprm_alloc_security(struct linux_binprm *bprm) |
@@ -2238,7 +2236,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | |||
2238 | u32 ptsid = 0; | 2236 | u32 ptsid = 0; |
2239 | 2237 | ||
2240 | rcu_read_lock(); | 2238 | rcu_read_lock(); |
2241 | tracer = task_tracer_task(current); | 2239 | tracer = tracehook_tracer_task(current); |
2242 | if (likely(tracer != NULL)) { | 2240 | if (likely(tracer != NULL)) { |
2243 | sec = tracer->security; | 2241 | sec = tracer->security; |
2244 | ptsid = sec->sid; | 2242 | ptsid = sec->sid; |
@@ -2640,12 +2638,11 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2640 | return dentry_has_perm(current, NULL, dentry, FILE__READ); | 2638 | return dentry_has_perm(current, NULL, dentry, FILE__READ); |
2641 | } | 2639 | } |
2642 | 2640 | ||
2643 | static int selinux_inode_permission(struct inode *inode, int mask, | 2641 | static int selinux_inode_permission(struct inode *inode, int mask) |
2644 | struct nameidata *nd) | ||
2645 | { | 2642 | { |
2646 | int rc; | 2643 | int rc; |
2647 | 2644 | ||
2648 | rc = secondary_ops->inode_permission(inode, mask, nd); | 2645 | rc = secondary_ops->inode_permission(inode, mask); |
2649 | if (rc) | 2646 | if (rc) |
2650 | return rc; | 2647 | return rc; |
2651 | 2648 | ||
@@ -5247,7 +5244,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5247 | Otherwise, leave SID unchanged and fail. */ | 5244 | Otherwise, leave SID unchanged and fail. */ |
5248 | task_lock(p); | 5245 | task_lock(p); |
5249 | rcu_read_lock(); | 5246 | rcu_read_lock(); |
5250 | tracer = task_tracer_task(p); | 5247 | tracer = tracehook_tracer_task(p); |
5251 | if (tracer != NULL) { | 5248 | if (tracer != NULL) { |
5252 | struct task_security_struct *ptsec = tracer->security; | 5249 | struct task_security_struct *ptsec = tracer->security; |
5253 | u32 ptsid = ptsec->sid; | 5250 | u32 ptsid = ptsec->sid; |
@@ -5359,7 +5356,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5359 | static struct security_operations selinux_ops = { | 5356 | static struct security_operations selinux_ops = { |
5360 | .name = "selinux", | 5357 | .name = "selinux", |
5361 | 5358 | ||
5362 | .ptrace = selinux_ptrace, | 5359 | .ptrace_may_access = selinux_ptrace_may_access, |
5360 | .ptrace_traceme = selinux_ptrace_traceme, | ||
5363 | .capget = selinux_capget, | 5361 | .capget = selinux_capget, |
5364 | .capset_check = selinux_capset_check, | 5362 | .capset_check = selinux_capset_check, |
5365 | .capset_set = selinux_capset_set, | 5363 | .capset_set = selinux_capset_set, |
@@ -5670,27 +5668,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = { | |||
5670 | static int __init selinux_nf_ip_init(void) | 5668 | static int __init selinux_nf_ip_init(void) |
5671 | { | 5669 | { |
5672 | int err = 0; | 5670 | int err = 0; |
5673 | u32 iter; | ||
5674 | 5671 | ||
5675 | if (!selinux_enabled) | 5672 | if (!selinux_enabled) |
5676 | goto out; | 5673 | goto out; |
5677 | 5674 | ||
5678 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); | 5675 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); |
5679 | 5676 | ||
5680 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) { | 5677 | err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); |
5681 | err = nf_register_hook(&selinux_ipv4_ops[iter]); | 5678 | if (err) |
5682 | if (err) | 5679 | panic("SELinux: nf_register_hooks for IPv4: error %d\n", err); |
5683 | panic("SELinux: nf_register_hook for IPv4: error %d\n", | ||
5684 | err); | ||
5685 | } | ||
5686 | 5680 | ||
5687 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5681 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
5688 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) { | 5682 | err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); |
5689 | err = nf_register_hook(&selinux_ipv6_ops[iter]); | 5683 | if (err) |
5690 | if (err) | 5684 | panic("SELinux: nf_register_hooks for IPv6: error %d\n", err); |
5691 | panic("SELinux: nf_register_hook for IPv6: error %d\n", | ||
5692 | err); | ||
5693 | } | ||
5694 | #endif /* IPV6 */ | 5685 | #endif /* IPV6 */ |
5695 | 5686 | ||
5696 | out: | 5687 | out: |
@@ -5702,15 +5693,11 @@ __initcall(selinux_nf_ip_init); | |||
5702 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 5693 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
5703 | static void selinux_nf_ip_exit(void) | 5694 | static void selinux_nf_ip_exit(void) |
5704 | { | 5695 | { |
5705 | u32 iter; | ||
5706 | |||
5707 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); | 5696 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); |
5708 | 5697 | ||
5709 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) | 5698 | nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); |
5710 | nf_unregister_hook(&selinux_ipv4_ops[iter]); | ||
5711 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5699 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
5712 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) | 5700 | nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); |
5713 | nf_unregister_hook(&selinux_ipv6_ops[iter]); | ||
5714 | #endif /* IPV6 */ | 5701 | #endif /* IPV6 */ |
5715 | } | 5702 | } |
5716 | #endif | 5703 | #endif |