diff options
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 63f131fc42e..03fc6a81ae3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -25,7 +25,7 @@  #include <linux/init.h>  #include <linux/kernel.h> -#include <linux/ptrace.h> +#include <linux/tracehook.h>  #include <linux/errno.h>  #include <linux/sched.h>  #include <linux/security.h> @@ -998,8 +998,12 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)  	int rc;  	rc = selinux_get_mnt_opts(sb, &opts); -	if (rc) +	if (rc) { +		/* before policy load we may get EINVAL, don't show anything */ +		if (rc == -EINVAL) +			rc = 0;  		return rc; +	}  	selinux_write_opts(m, &opts); @@ -1734,24 +1738,34 @@ static inline u32 file_to_av(struct file *file)  /* Hook functions begin here. */ -static int selinux_ptrace(struct task_struct *parent, -			  struct task_struct *child, -			  unsigned int mode) +static int selinux_ptrace_may_access(struct task_struct *child, +				     unsigned int mode)  {  	int rc; -	rc = secondary_ops->ptrace(parent, child, mode); +	rc = secondary_ops->ptrace_may_access(child, mode);  	if (rc)  		return rc;  	if (mode == PTRACE_MODE_READ) { -		struct task_security_struct *tsec = parent->security; +		struct task_security_struct *tsec = current->security;  		struct task_security_struct *csec = child->security;  		return avc_has_perm(tsec->sid, csec->sid,  				    SECCLASS_FILE, FILE__READ, NULL);  	} -	return task_has_perm(parent, child, PROCESS__PTRACE); +	return task_has_perm(current, child, PROCESS__PTRACE); +} + +static int selinux_ptrace_traceme(struct task_struct *parent) +{ +	int rc; + +	rc = secondary_ops->ptrace_traceme(parent); +	if (rc) +		return rc; + +	return task_has_perm(parent, current, PROCESS__PTRACE);  }  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)  	return __vm_enough_memory(mm, pages, cap_sys_admin);  } -/** - * task_tracer_task - return the task that is tracing the given task - * @task:		task to consider - * - * Returns NULL if noone is tracing @task, or the &struct task_struct - * pointer to its tracer. - * - * Must be called under rcu_read_lock(). - */ -static struct task_struct *task_tracer_task(struct task_struct *task) -{ -	if (task->ptrace & PT_PTRACED) -		return rcu_dereference(task->parent); -	return NULL; -} -  /* binprm security operations */  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)  			u32 ptsid = 0;  			rcu_read_lock(); -			tracer = task_tracer_task(current); +			tracer = tracehook_tracer_task(current);  			if (likely(tracer != NULL)) {  				sec = tracer->security;  				ptsid = sec->sid; @@ -2640,12 +2638,11 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na  	return dentry_has_perm(current, NULL, dentry, FILE__READ);  } -static int selinux_inode_permission(struct inode *inode, int mask, -				    struct nameidata *nd) +static int selinux_inode_permission(struct inode *inode, int mask)  {  	int rc; -	rc = secondary_ops->inode_permission(inode, mask, nd); +	rc = secondary_ops->inode_permission(inode, mask);  	if (rc)  		return rc; @@ -5247,7 +5244,7 @@ static int selinux_setprocattr(struct task_struct *p,  		   Otherwise, leave SID unchanged and fail. */  		task_lock(p);  		rcu_read_lock(); -		tracer = task_tracer_task(p); +		tracer = tracehook_tracer_task(p);  		if (tracer != NULL) {  			struct task_security_struct *ptsec = tracer->security;  			u32 ptsid = ptsec->sid; @@ -5359,7 +5356,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)  static struct security_operations selinux_ops = {  	.name =				"selinux", -	.ptrace =			selinux_ptrace, +	.ptrace_may_access =		selinux_ptrace_may_access, +	.ptrace_traceme =		selinux_ptrace_traceme,  	.capget =			selinux_capget,  	.capset_check =			selinux_capset_check,  	.capset_set =			selinux_capset_set, @@ -5670,27 +5668,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {  static int __init selinux_nf_ip_init(void)  {  	int err = 0; -	u32 iter;  	if (!selinux_enabled)  		goto out;  	printk(KERN_DEBUG "SELinux:  Registering netfilter hooks\n"); -	for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) { -		err = nf_register_hook(&selinux_ipv4_ops[iter]); -		if (err) -			panic("SELinux: nf_register_hook for IPv4: error %d\n", -			      err); -	} +	err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); +	if (err) +		panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -	for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) { -		err = nf_register_hook(&selinux_ipv6_ops[iter]); -		if (err) -			panic("SELinux: nf_register_hook for IPv6: error %d\n", -			      err); -	} +	err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); +	if (err) +		panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);  #endif	/* IPV6 */  out: @@ -5702,15 +5693,11 @@ __initcall(selinux_nf_ip_init);  #ifdef CONFIG_SECURITY_SELINUX_DISABLE  static void selinux_nf_ip_exit(void)  { -	u32 iter; -  	printk(KERN_DEBUG "SELinux:  Unregistering netfilter hooks\n"); -	for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) -		nf_unregister_hook(&selinux_ipv4_ops[iter]); +	nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -	for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) -		nf_unregister_hook(&selinux_ipv6_ops[iter]); +	nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));  #endif	/* IPV6 */  }  #endif  | 
