aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-13 05:05:51 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-13 05:05:51 -0400
commitaccba5f3965d6a9d1bf7c1e1a7995d17e9d521b6 (patch)
tree8fb40782e79472ed882ff2098d4dd295557278ee /security/selinux/hooks.c
parent6852fd9b86d05063c6ef49d2e12e061cc7f6a105 (diff)
parent4480f15b3306f43bbb0310d461142b4e897ca45b (diff)
Merge branch 'linus' into oprofile-v2
Conflicts: arch/x86/kernel/apic_32.c arch/x86/oprofile/nmi_int.c include/linux/pci_ids.h
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c147
1 files changed, 75 insertions, 72 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 63f131fc42e4..4a7374c12d9c 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>
@@ -957,7 +957,8 @@ out_err:
957 return rc; 957 return rc;
958} 958}
959 959
960void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) 960static void selinux_write_opts(struct seq_file *m,
961 struct security_mnt_opts *opts)
961{ 962{
962 int i; 963 int i;
963 char *prefix; 964 char *prefix;
@@ -998,8 +999,12 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
998 int rc; 999 int rc;
999 1000
1000 rc = selinux_get_mnt_opts(sb, &opts); 1001 rc = selinux_get_mnt_opts(sb, &opts);
1001 if (rc) 1002 if (rc) {
1003 /* before policy load we may get EINVAL, don't show anything */
1004 if (rc == -EINVAL)
1005 rc = 0;
1002 return rc; 1006 return rc;
1007 }
1003 1008
1004 selinux_write_opts(m, &opts); 1009 selinux_write_opts(m, &opts);
1005 1010
@@ -1286,7 +1291,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1286 /* Default to the fs superblock SID. */ 1291 /* Default to the fs superblock SID. */
1287 isec->sid = sbsec->sid; 1292 isec->sid = sbsec->sid;
1288 1293
1289 if (sbsec->proc) { 1294 if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
1290 struct proc_inode *proci = PROC_I(inode); 1295 struct proc_inode *proci = PROC_I(inode);
1291 if (proci->pde) { 1296 if (proci->pde) {
1292 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1297 isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1734,24 +1739,34 @@ static inline u32 file_to_av(struct file *file)
1734 1739
1735/* Hook functions begin here. */ 1740/* Hook functions begin here. */
1736 1741
1737static int selinux_ptrace(struct task_struct *parent, 1742static int selinux_ptrace_may_access(struct task_struct *child,
1738 struct task_struct *child, 1743 unsigned int mode)
1739 unsigned int mode)
1740{ 1744{
1741 int rc; 1745 int rc;
1742 1746
1743 rc = secondary_ops->ptrace(parent, child, mode); 1747 rc = secondary_ops->ptrace_may_access(child, mode);
1744 if (rc) 1748 if (rc)
1745 return rc; 1749 return rc;
1746 1750
1747 if (mode == PTRACE_MODE_READ) { 1751 if (mode == PTRACE_MODE_READ) {
1748 struct task_security_struct *tsec = parent->security; 1752 struct task_security_struct *tsec = current->security;
1749 struct task_security_struct *csec = child->security; 1753 struct task_security_struct *csec = child->security;
1750 return avc_has_perm(tsec->sid, csec->sid, 1754 return avc_has_perm(tsec->sid, csec->sid,
1751 SECCLASS_FILE, FILE__READ, NULL); 1755 SECCLASS_FILE, FILE__READ, NULL);
1752 } 1756 }
1753 1757
1754 return task_has_perm(parent, child, PROCESS__PTRACE); 1758 return task_has_perm(current, child, PROCESS__PTRACE);
1759}
1760
1761static int selinux_ptrace_traceme(struct task_struct *parent)
1762{
1763 int rc;
1764
1765 rc = secondary_ops->ptrace_traceme(parent);
1766 if (rc)
1767 return rc;
1768
1769 return task_has_perm(parent, current, PROCESS__PTRACE);
1755} 1770}
1756 1771
1757static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, 1772static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
@@ -1971,22 +1986,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1971 return __vm_enough_memory(mm, pages, cap_sys_admin); 1986 return __vm_enough_memory(mm, pages, cap_sys_admin);
1972} 1987}
1973 1988
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 */
1983static 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 */ 1989/* binprm security operations */
1991 1990
1992static int selinux_bprm_alloc_security(struct linux_binprm *bprm) 1991static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -2238,7 +2237,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2238 u32 ptsid = 0; 2237 u32 ptsid = 0;
2239 2238
2240 rcu_read_lock(); 2239 rcu_read_lock();
2241 tracer = task_tracer_task(current); 2240 tracer = tracehook_tracer_task(current);
2242 if (likely(tracer != NULL)) { 2241 if (likely(tracer != NULL)) {
2243 sec = tracer->security; 2242 sec = tracer->security;
2244 ptsid = sec->sid; 2243 ptsid = sec->sid;
@@ -2640,12 +2639,11 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
2640 return dentry_has_perm(current, NULL, dentry, FILE__READ); 2639 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2641} 2640}
2642 2641
2643static int selinux_inode_permission(struct inode *inode, int mask, 2642static int selinux_inode_permission(struct inode *inode, int mask)
2644 struct nameidata *nd)
2645{ 2643{
2646 int rc; 2644 int rc;
2647 2645
2648 rc = secondary_ops->inode_permission(inode, mask, nd); 2646 rc = secondary_ops->inode_permission(inode, mask);
2649 if (rc) 2647 if (rc)
2650 return rc; 2648 return rc;
2651 2649
@@ -3551,38 +3549,44 @@ out:
3551#endif /* IPV6 */ 3549#endif /* IPV6 */
3552 3550
3553static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3551static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3554 char **addrp, int src, u8 *proto) 3552 char **_addrp, int src, u8 *proto)
3555{ 3553{
3556 int ret = 0; 3554 char *addrp;
3555 int ret;
3557 3556
3558 switch (ad->u.net.family) { 3557 switch (ad->u.net.family) {
3559 case PF_INET: 3558 case PF_INET:
3560 ret = selinux_parse_skb_ipv4(skb, ad, proto); 3559 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3561 if (ret || !addrp) 3560 if (ret)
3562 break; 3561 goto parse_error;
3563 *addrp = (char *)(src ? &ad->u.net.v4info.saddr : 3562 addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3564 &ad->u.net.v4info.daddr); 3563 &ad->u.net.v4info.daddr);
3565 break; 3564 goto okay;
3566 3565
3567#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3566#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3568 case PF_INET6: 3567 case PF_INET6:
3569 ret = selinux_parse_skb_ipv6(skb, ad, proto); 3568 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3570 if (ret || !addrp) 3569 if (ret)
3571 break; 3570 goto parse_error;
3572 *addrp = (char *)(src ? &ad->u.net.v6info.saddr : 3571 addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3573 &ad->u.net.v6info.daddr); 3572 &ad->u.net.v6info.daddr);
3574 break; 3573 goto okay;
3575#endif /* IPV6 */ 3574#endif /* IPV6 */
3576 default: 3575 default:
3577 break; 3576 addrp = NULL;
3577 goto okay;
3578 } 3578 }
3579 3579
3580 if (unlikely(ret)) 3580parse_error:
3581 printk(KERN_WARNING 3581 printk(KERN_WARNING
3582 "SELinux: failure in selinux_parse_skb()," 3582 "SELinux: failure in selinux_parse_skb(),"
3583 " unable to parse packet\n"); 3583 " unable to parse packet\n");
3584
3585 return ret; 3584 return ret;
3585
3586okay:
3587 if (_addrp)
3588 *_addrp = addrp;
3589 return 0;
3586} 3590}
3587 3591
3588/** 3592/**
@@ -5222,8 +5226,12 @@ static int selinux_setprocattr(struct task_struct *p,
5222 5226
5223 if (sid == 0) 5227 if (sid == 0)
5224 return -EINVAL; 5228 return -EINVAL;
5225 5229 /*
5226 /* Only allow single threaded processes to change context */ 5230 * SELinux allows to change context in the following case only.
5231 * - Single threaded processes.
5232 * - Multi threaded processes intend to change its context into
5233 * more restricted domain (defined by TYPEBOUNDS statement).
5234 */
5227 if (atomic_read(&p->mm->mm_users) != 1) { 5235 if (atomic_read(&p->mm->mm_users) != 1) {
5228 struct task_struct *g, *t; 5236 struct task_struct *g, *t;
5229 struct mm_struct *mm = p->mm; 5237 struct mm_struct *mm = p->mm;
@@ -5231,11 +5239,16 @@ static int selinux_setprocattr(struct task_struct *p,
5231 do_each_thread(g, t) { 5239 do_each_thread(g, t) {
5232 if (t->mm == mm && t != p) { 5240 if (t->mm == mm && t != p) {
5233 read_unlock(&tasklist_lock); 5241 read_unlock(&tasklist_lock);
5234 return -EPERM; 5242 error = security_bounded_transition(tsec->sid, sid);
5243 if (!error)
5244 goto boundary_ok;
5245
5246 return error;
5235 } 5247 }
5236 } while_each_thread(g, t); 5248 } while_each_thread(g, t);
5237 read_unlock(&tasklist_lock); 5249 read_unlock(&tasklist_lock);
5238 } 5250 }
5251boundary_ok:
5239 5252
5240 /* Check permissions for the transition. */ 5253 /* Check permissions for the transition. */
5241 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, 5254 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
@@ -5247,7 +5260,7 @@ static int selinux_setprocattr(struct task_struct *p,
5247 Otherwise, leave SID unchanged and fail. */ 5260 Otherwise, leave SID unchanged and fail. */
5248 task_lock(p); 5261 task_lock(p);
5249 rcu_read_lock(); 5262 rcu_read_lock();
5250 tracer = task_tracer_task(p); 5263 tracer = tracehook_tracer_task(p);
5251 if (tracer != NULL) { 5264 if (tracer != NULL) {
5252 struct task_security_struct *ptsec = tracer->security; 5265 struct task_security_struct *ptsec = tracer->security;
5253 u32 ptsid = ptsec->sid; 5266 u32 ptsid = ptsec->sid;
@@ -5359,7 +5372,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
5359static struct security_operations selinux_ops = { 5372static struct security_operations selinux_ops = {
5360 .name = "selinux", 5373 .name = "selinux",
5361 5374
5362 .ptrace = selinux_ptrace, 5375 .ptrace_may_access = selinux_ptrace_may_access,
5376 .ptrace_traceme = selinux_ptrace_traceme,
5363 .capget = selinux_capget, 5377 .capget = selinux_capget,
5364 .capset_check = selinux_capset_check, 5378 .capset_check = selinux_capset_check,
5365 .capset_set = selinux_capset_set, 5379 .capset_set = selinux_capset_set,
@@ -5670,27 +5684,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
5670static int __init selinux_nf_ip_init(void) 5684static int __init selinux_nf_ip_init(void)
5671{ 5685{
5672 int err = 0; 5686 int err = 0;
5673 u32 iter;
5674 5687
5675 if (!selinux_enabled) 5688 if (!selinux_enabled)
5676 goto out; 5689 goto out;
5677 5690
5678 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 5691 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5679 5692
5680 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) { 5693 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5681 err = nf_register_hook(&selinux_ipv4_ops[iter]); 5694 if (err)
5682 if (err) 5695 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 5696
5687#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5697#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5688 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) { 5698 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5689 err = nf_register_hook(&selinux_ipv6_ops[iter]); 5699 if (err)
5690 if (err) 5700 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 */ 5701#endif /* IPV6 */
5695 5702
5696out: 5703out:
@@ -5702,15 +5709,11 @@ __initcall(selinux_nf_ip_init);
5702#ifdef CONFIG_SECURITY_SELINUX_DISABLE 5709#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5703static void selinux_nf_ip_exit(void) 5710static void selinux_nf_ip_exit(void)
5704{ 5711{
5705 u32 iter;
5706
5707 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 5712 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
5708 5713
5709 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) 5714 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) 5715#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5712 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) 5716 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5713 nf_unregister_hook(&selinux_ipv6_ops[iter]);
5714#endif /* IPV6 */ 5717#endif /* IPV6 */
5715} 5718}
5716#endif 5719#endif