diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 1030 | 
1 files changed, 750 insertions, 280 deletions
| diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8644d864e3c1..4cafe6a19167 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -67,6 +67,8 @@  #include <linux/tcp.h>  #include <linux/udp.h>  #include <linux/dccp.h> +#include <linux/sctp.h> +#include <net/sctp/structs.h>  #include <linux/quota.h>  #include <linux/un.h>		/* for Unix socket types */  #include <net/af_unix.h>	/* for Unix socket types */ @@ -98,20 +100,24 @@  #include "audit.h"  #include "avc_ss.h" +struct selinux_state selinux_state; +  /* SECMARK reference count */  static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);  #ifdef CONFIG_SECURITY_SELINUX_DEVELOP -int selinux_enforcing; +static int selinux_enforcing_boot;  static int __init enforcing_setup(char *str)  {  	unsigned long enforcing;  	if (!kstrtoul(str, 0, &enforcing)) -		selinux_enforcing = enforcing ? 1 : 0; +		selinux_enforcing_boot = enforcing ? 1 : 0;  	return 1;  }  __setup("enforcing=", enforcing_setup); +#else +#define selinux_enforcing_boot 1  #endif  #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM @@ -129,6 +135,19 @@ __setup("selinux=", selinux_enabled_setup);  int selinux_enabled = 1;  #endif +static unsigned int selinux_checkreqprot_boot = +	CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; + +static int __init checkreqprot_setup(char *str) +{ +	unsigned long checkreqprot; + +	if (!kstrtoul(str, 0, &checkreqprot)) +		selinux_checkreqprot_boot = checkreqprot ? 1 : 0; +	return 1; +} +__setup("checkreqprot=", checkreqprot_setup); +  static struct kmem_cache *sel_inode_cache;  static struct kmem_cache *file_security_cache; @@ -145,7 +164,8 @@ static struct kmem_cache *file_security_cache;   */  static int selinux_secmark_enabled(void)  { -	return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount)); +	return (selinux_policycap_alwaysnetwork() || +		atomic_read(&selinux_secmark_refcount));  }  /** @@ -160,7 +180,8 @@ static int selinux_secmark_enabled(void)   */  static int selinux_peerlbl_enabled(void)  { -	return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled()); +	return (selinux_policycap_alwaysnetwork() || +		netlbl_enabled() || selinux_xfrm_enabled());  }  static int selinux_netcache_avc_callback(u32 event) @@ -264,7 +285,8 @@ static int __inode_security_revalidate(struct inode *inode,  	might_sleep_if(may_sleep); -	if (ss_initialized && isec->initialized != LABEL_INITIALIZED) { +	if (selinux_state.initialized && +	    isec->initialized != LABEL_INITIALIZED) {  		if (!may_sleep)  			return -ECHILD; @@ -446,12 +468,14 @@ static int may_context_mount_sb_relabel(u32 sid,  	const struct task_security_struct *tsec = cred->security;  	int rc; -	rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, +	rc = avc_has_perm(&selinux_state, +			  tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,  			  FILESYSTEM__RELABELFROM, NULL);  	if (rc)  		return rc; -	rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, +	rc = avc_has_perm(&selinux_state, +			  tsec->sid, sid, SECCLASS_FILESYSTEM,  			  FILESYSTEM__RELABELTO, NULL);  	return rc;  } @@ -462,12 +486,14 @@ static int may_context_mount_inode_relabel(u32 sid,  {  	const struct task_security_struct *tsec = cred->security;  	int rc; -	rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, +	rc = avc_has_perm(&selinux_state, +			  tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,  			  FILESYSTEM__RELABELFROM, NULL);  	if (rc)  		return rc; -	rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, +	rc = avc_has_perm(&selinux_state, +			  sid, sbsec->sid, SECCLASS_FILESYSTEM,  			  FILESYSTEM__ASSOCIATE, NULL);  	return rc;  } @@ -486,7 +512,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)  		!strcmp(sb->s_type->name, "debugfs") ||  		!strcmp(sb->s_type->name, "tracefs") ||  		!strcmp(sb->s_type->name, "rootfs") || -		(selinux_policycap_cgroupseclabel && +		(selinux_policycap_cgroupseclabel() &&  		 (!strcmp(sb->s_type->name, "cgroup") ||  		  !strcmp(sb->s_type->name, "cgroup2")));  } @@ -586,7 +612,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb,  	if (!(sbsec->flags & SE_SBINITIALIZED))  		return -EINVAL; -	if (!ss_initialized) +	if (!selinux_state.initialized)  		return -EINVAL;  	/* make sure we always check enough bits to cover the mask */ @@ -617,21 +643,25 @@ static int selinux_get_mnt_opts(const struct super_block *sb,  	i = 0;  	if (sbsec->flags & FSCONTEXT_MNT) { -		rc = security_sid_to_context(sbsec->sid, &context, &len); +		rc = security_sid_to_context(&selinux_state, sbsec->sid, +					     &context, &len);  		if (rc)  			goto out_free;  		opts->mnt_opts[i] = context;  		opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;  	}  	if (sbsec->flags & CONTEXT_MNT) { -		rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); +		rc = security_sid_to_context(&selinux_state, +					     sbsec->mntpoint_sid, +					     &context, &len);  		if (rc)  			goto out_free;  		opts->mnt_opts[i] = context;  		opts->mnt_opts_flags[i++] = CONTEXT_MNT;  	}  	if (sbsec->flags & DEFCONTEXT_MNT) { -		rc = security_sid_to_context(sbsec->def_sid, &context, &len); +		rc = security_sid_to_context(&selinux_state, sbsec->def_sid, +					     &context, &len);  		if (rc)  			goto out_free;  		opts->mnt_opts[i] = context; @@ -641,7 +671,8 @@ static int selinux_get_mnt_opts(const struct super_block *sb,  		struct dentry *root = sbsec->sb->s_root;  		struct inode_security_struct *isec = backing_inode_security(root); -		rc = security_sid_to_context(isec->sid, &context, &len); +		rc = security_sid_to_context(&selinux_state, isec->sid, +					     &context, &len);  		if (rc)  			goto out_free;  		opts->mnt_opts[i] = context; @@ -704,7 +735,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,  	mutex_lock(&sbsec->lock); -	if (!ss_initialized) { +	if (!selinux_state.initialized) {  		if (!num_opts) {  			/* Defer initialization until selinux_complete_init,  			   after the initial policy is loaded and the security @@ -750,7 +781,9 @@ static int selinux_set_mnt_opts(struct super_block *sb,  		if (flags[i] == SBLABEL_MNT)  			continue; -		rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL); +		rc = security_context_str_to_sid(&selinux_state, +						 mount_options[i], &sid, +						 GFP_KERNEL);  		if (rc) {  			printk(KERN_WARNING "SELinux: security_context_str_to_sid"  			       "(%s) failed for (dev %s, type %s) errno=%d\n", @@ -826,7 +859,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,  		 * Determine the labeling behavior to use for this  		 * filesystem type.  		 */ -		rc = security_fs_use(sb); +		rc = security_fs_use(&selinux_state, sb);  		if (rc) {  			printk(KERN_WARNING  				"%s: security_fs_use(%s) returned %d\n", @@ -851,7 +884,9 @@ static int selinux_set_mnt_opts(struct super_block *sb,  		}  		if (sbsec->behavior == SECURITY_FS_USE_XATTR) {  			sbsec->behavior = SECURITY_FS_USE_MNTPOINT; -			rc = security_transition_sid(current_sid(), current_sid(), +			rc = security_transition_sid(&selinux_state, +						     current_sid(), +						     current_sid(),  						     SECCLASS_FILE, NULL,  						     &sbsec->mntpoint_sid);  			if (rc) @@ -987,7 +1022,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,  	 * if the parent was able to be mounted it clearly had no special lsm  	 * mount options.  thus we can safely deal with this superblock later  	 */ -	if (!ss_initialized) +	if (!selinux_state.initialized)  		return 0;  	/* @@ -1014,7 +1049,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,  	if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&  		!(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) { -		rc = security_fs_use(newsb); +		rc = security_fs_use(&selinux_state, newsb);  		if (rc)  			goto out;  	} @@ -1297,7 +1332,7 @@ static inline int default_protocol_dgram(int protocol)  static inline u16 socket_type_to_security_class(int family, int type, int protocol)  { -	int extsockclass = selinux_policycap_extsockclass; +	int extsockclass = selinux_policycap_extsockclass();  	switch (family) {  	case PF_UNIX: @@ -1471,7 +1506,8 @@ static int selinux_genfs_get_sid(struct dentry *dentry,  				path++;  			}  		} -		rc = security_genfs_sid(sb->s_type->name, path, tclass, sid); +		rc = security_genfs_sid(&selinux_state, sb->s_type->name, +					path, tclass, sid);  	}  	free_page((unsigned long)buffer);  	return rc; @@ -1589,7 +1625,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent  			sid = sbsec->def_sid;  			rc = 0;  		} else { -			rc = security_context_to_sid_default(context, rc, &sid, +			rc = security_context_to_sid_default(&selinux_state, +							     context, rc, &sid,  							     sbsec->def_sid,  							     GFP_NOFS);  			if (rc) { @@ -1622,7 +1659,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent  		sid = sbsec->sid;  		/* Try to obtain a transition SID. */ -		rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid); +		rc = security_transition_sid(&selinux_state, task_sid, sid, +					     sclass, NULL, &sid);  		if (rc)  			goto out;  		break; @@ -1740,9 +1778,11 @@ static int cred_has_capability(const struct cred *cred,  		return -EINVAL;  	} -	rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); +	rc = avc_has_perm_noaudit(&selinux_state, +				  sid, sid, sclass, av, 0, &avd);  	if (audit == SECURITY_CAP_AUDIT) { -		int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); +		int rc2 = avc_audit(&selinux_state, +				    sid, sid, sclass, av, &avd, rc, &ad, 0);  		if (rc2)  			return rc2;  	} @@ -1768,7 +1808,8 @@ static int inode_has_perm(const struct cred *cred,  	sid = cred_sid(cred);  	isec = inode->i_security; -	return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); +	return avc_has_perm(&selinux_state, +			    sid, isec->sid, isec->sclass, perms, adp);  }  /* Same as inode_has_perm, but pass explicit audit data containing @@ -1841,7 +1882,8 @@ static int file_has_perm(const struct cred *cred,  	ad.u.file = file;  	if (sid != fsec->sid) { -		rc = avc_has_perm(sid, fsec->sid, +		rc = avc_has_perm(&selinux_state, +				  sid, fsec->sid,  				  SECCLASS_FD,  				  FD__USE,  				  &ad); @@ -1883,7 +1925,8 @@ selinux_determine_inode_label(const struct task_security_struct *tsec,  		*_new_isid = tsec->create_sid;  	} else {  		const struct inode_security_struct *dsec = inode_security(dir); -		return security_transition_sid(tsec->sid, dsec->sid, tclass, +		return security_transition_sid(&selinux_state, tsec->sid, +					       dsec->sid, tclass,  					       name, _new_isid);  	} @@ -1910,7 +1953,8 @@ static int may_create(struct inode *dir,  	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = dentry; -	rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, +	rc = avc_has_perm(&selinux_state, +			  sid, dsec->sid, SECCLASS_DIR,  			  DIR__ADD_NAME | DIR__SEARCH,  			  &ad);  	if (rc) @@ -1921,11 +1965,13 @@ static int may_create(struct inode *dir,  	if (rc)  		return rc; -	rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); +	rc = avc_has_perm(&selinux_state, +			  sid, newsid, tclass, FILE__CREATE, &ad);  	if (rc)  		return rc; -	return avc_has_perm(newsid, sbsec->sid, +	return avc_has_perm(&selinux_state, +			    newsid, sbsec->sid,  			    SECCLASS_FILESYSTEM,  			    FILESYSTEM__ASSOCIATE, &ad);  } @@ -1954,7 +2000,8 @@ static int may_link(struct inode *dir,  	av = DIR__SEARCH;  	av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); -	rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad); +	rc = avc_has_perm(&selinux_state, +			  sid, dsec->sid, SECCLASS_DIR, av, &ad);  	if (rc)  		return rc; @@ -1974,7 +2021,8 @@ static int may_link(struct inode *dir,  		return 0;  	} -	rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad); +	rc = avc_has_perm(&selinux_state, +			  sid, isec->sid, isec->sclass, av, &ad);  	return rc;  } @@ -1998,16 +2046,19 @@ static inline int may_rename(struct inode *old_dir,  	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = old_dentry; -	rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, +	rc = avc_has_perm(&selinux_state, +			  sid, old_dsec->sid, SECCLASS_DIR,  			  DIR__REMOVE_NAME | DIR__SEARCH, &ad);  	if (rc)  		return rc; -	rc = avc_has_perm(sid, old_isec->sid, +	rc = avc_has_perm(&selinux_state, +			  sid, old_isec->sid,  			  old_isec->sclass, FILE__RENAME, &ad);  	if (rc)  		return rc;  	if (old_is_dir && new_dir != old_dir) { -		rc = avc_has_perm(sid, old_isec->sid, +		rc = avc_has_perm(&selinux_state, +				  sid, old_isec->sid,  				  old_isec->sclass, DIR__REPARENT, &ad);  		if (rc)  			return rc; @@ -2017,13 +2068,15 @@ static inline int may_rename(struct inode *old_dir,  	av = DIR__ADD_NAME | DIR__SEARCH;  	if (d_is_positive(new_dentry))  		av |= DIR__REMOVE_NAME; -	rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad); +	rc = avc_has_perm(&selinux_state, +			  sid, new_dsec->sid, SECCLASS_DIR, av, &ad);  	if (rc)  		return rc;  	if (d_is_positive(new_dentry)) {  		new_isec = backing_inode_security(new_dentry);  		new_is_dir = d_is_dir(new_dentry); -		rc = avc_has_perm(sid, new_isec->sid, +		rc = avc_has_perm(&selinux_state, +				  sid, new_isec->sid,  				  new_isec->sclass,  				  (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);  		if (rc) @@ -2043,7 +2096,8 @@ static int superblock_has_perm(const struct cred *cred,  	u32 sid = cred_sid(cred);  	sbsec = sb->s_security; -	return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); +	return avc_has_perm(&selinux_state, +			    sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);  }  /* Convert a Linux mode and permission mask to an access vector. */ @@ -2106,7 +2160,8 @@ static inline u32 open_file_to_av(struct file *file)  	u32 av = file_to_av(file);  	struct inode *inode = file_inode(file); -	if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC) +	if (selinux_policycap_openperm() && +	    inode->i_sb->s_magic != SOCKFS_MAGIC)  		av |= FILE__OPEN;  	return av; @@ -2119,7 +2174,8 @@ static int selinux_binder_set_context_mgr(struct task_struct *mgr)  	u32 mysid = current_sid();  	u32 mgrsid = task_sid(mgr); -	return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, +	return avc_has_perm(&selinux_state, +			    mysid, mgrsid, SECCLASS_BINDER,  			    BINDER__SET_CONTEXT_MGR, NULL);  } @@ -2132,13 +2188,15 @@ static int selinux_binder_transaction(struct task_struct *from,  	int rc;  	if (mysid != fromsid) { -		rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, +		rc = avc_has_perm(&selinux_state, +				  mysid, fromsid, SECCLASS_BINDER,  				  BINDER__IMPERSONATE, NULL);  		if (rc)  			return rc;  	} -	return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, +	return avc_has_perm(&selinux_state, +			    fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,  			    NULL);  } @@ -2148,7 +2206,8 @@ static int selinux_binder_transfer_binder(struct task_struct *from,  	u32 fromsid = task_sid(from);  	u32 tosid = task_sid(to); -	return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, +	return avc_has_perm(&selinux_state, +			    fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,  			    NULL);  } @@ -2167,7 +2226,8 @@ static int selinux_binder_transfer_file(struct task_struct *from,  	ad.u.path = file->f_path;  	if (sid != fsec->sid) { -		rc = avc_has_perm(sid, fsec->sid, +		rc = avc_has_perm(&selinux_state, +				  sid, fsec->sid,  				  SECCLASS_FD,  				  FD__USE,  				  &ad); @@ -2185,7 +2245,8 @@ static int selinux_binder_transfer_file(struct task_struct *from,  		return 0;  	isec = backing_inode_security(dentry); -	return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), +	return avc_has_perm(&selinux_state, +			    sid, isec->sid, isec->sclass, file_to_av(file),  			    &ad);  } @@ -2196,21 +2257,25 @@ static int selinux_ptrace_access_check(struct task_struct *child,  	u32 csid = task_sid(child);  	if (mode & PTRACE_MODE_READ) -		return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); +		return avc_has_perm(&selinux_state, +				    sid, csid, SECCLASS_FILE, FILE__READ, NULL); -	return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); +	return avc_has_perm(&selinux_state, +			    sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);  }  static int selinux_ptrace_traceme(struct task_struct *parent)  { -	return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    task_sid(parent), current_sid(), SECCLASS_PROCESS,  			    PROCESS__PTRACE, NULL);  }  static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,  			  kernel_cap_t *inheritable, kernel_cap_t *permitted)  { -	return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(target), SECCLASS_PROCESS,  			    PROCESS__GETCAP, NULL);  } @@ -2219,7 +2284,8 @@ static int selinux_capset(struct cred *new, const struct cred *old,  			  const kernel_cap_t *inheritable,  			  const kernel_cap_t *permitted)  { -	return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    cred_sid(old), cred_sid(new), SECCLASS_PROCESS,  			    PROCESS__SETCAP, NULL);  } @@ -2279,18 +2345,21 @@ static int selinux_syslog(int type)  	switch (type) {  	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */  	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */ -		return avc_has_perm(current_sid(), SECINITSID_KERNEL, +		return avc_has_perm(&selinux_state, +				    current_sid(), SECINITSID_KERNEL,  				    SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);  	case SYSLOG_ACTION_CONSOLE_OFF:	/* Disable logging to console */  	case SYSLOG_ACTION_CONSOLE_ON:	/* Enable logging to console */  	/* Set level of messages printed to console */  	case SYSLOG_ACTION_CONSOLE_LEVEL: -		return avc_has_perm(current_sid(), SECINITSID_KERNEL, +		return avc_has_perm(&selinux_state, +				    current_sid(), SECINITSID_KERNEL,  				    SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,  				    NULL);  	}  	/* All other syslog types */ -	return avc_has_perm(current_sid(), SECINITSID_KERNEL, +	return avc_has_perm(&selinux_state, +			    current_sid(), SECINITSID_KERNEL,  			    SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);  } @@ -2351,13 +2420,14 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,  	 * policy allows the corresponding permission between  	 * the old and new contexts.  	 */ -	if (selinux_policycap_nnp_nosuid_transition) { +	if (selinux_policycap_nnp_nosuid_transition()) {  		av = 0;  		if (nnp)  			av |= PROCESS2__NNP_TRANSITION;  		if (nosuid)  			av |= PROCESS2__NOSUID_TRANSITION; -		rc = avc_has_perm(old_tsec->sid, new_tsec->sid, +		rc = avc_has_perm(&selinux_state, +				  old_tsec->sid, new_tsec->sid,  				  SECCLASS_PROCESS2, av, NULL);  		if (!rc)  			return 0; @@ -2368,7 +2438,8 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,  	 * i.e. SIDs that are guaranteed to only be allowed a subset  	 * of the permissions of the current SID.  	 */ -	rc = security_bounded_transition(old_tsec->sid, new_tsec->sid); +	rc = security_bounded_transition(&selinux_state, old_tsec->sid, +					 new_tsec->sid);  	if (!rc)  		return 0; @@ -2420,8 +2491,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  			return rc;  	} else {  		/* Check for a default transition on this program. */ -		rc = security_transition_sid(old_tsec->sid, isec->sid, -					     SECCLASS_PROCESS, NULL, +		rc = security_transition_sid(&selinux_state, old_tsec->sid, +					     isec->sid, SECCLASS_PROCESS, NULL,  					     &new_tsec->sid);  		if (rc)  			return rc; @@ -2439,25 +2510,29 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  	ad.u.file = bprm->file;  	if (new_tsec->sid == old_tsec->sid) { -		rc = avc_has_perm(old_tsec->sid, isec->sid, +		rc = avc_has_perm(&selinux_state, +				  old_tsec->sid, isec->sid,  				  SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);  		if (rc)  			return rc;  	} else {  		/* Check permissions for the transition. */ -		rc = avc_has_perm(old_tsec->sid, new_tsec->sid, +		rc = avc_has_perm(&selinux_state, +				  old_tsec->sid, new_tsec->sid,  				  SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);  		if (rc)  			return rc; -		rc = avc_has_perm(new_tsec->sid, isec->sid, +		rc = avc_has_perm(&selinux_state, +				  new_tsec->sid, isec->sid,  				  SECCLASS_FILE, FILE__ENTRYPOINT, &ad);  		if (rc)  			return rc;  		/* Check for shared state */  		if (bprm->unsafe & LSM_UNSAFE_SHARE) { -			rc = avc_has_perm(old_tsec->sid, new_tsec->sid, +			rc = avc_has_perm(&selinux_state, +					  old_tsec->sid, new_tsec->sid,  					  SECCLASS_PROCESS, PROCESS__SHARE,  					  NULL);  			if (rc) @@ -2469,7 +2544,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  		if (bprm->unsafe & LSM_UNSAFE_PTRACE) {  			u32 ptsid = ptrace_parent_sid();  			if (ptsid != 0) { -				rc = avc_has_perm(ptsid, new_tsec->sid, +				rc = avc_has_perm(&selinux_state, +						  ptsid, new_tsec->sid,  						  SECCLASS_PROCESS,  						  PROCESS__PTRACE, NULL);  				if (rc) @@ -2483,7 +2559,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  		/* Enable secure mode for SIDs transitions unless  		   the noatsecure permission is granted between  		   the two SIDs, i.e. ahp returns 0. */ -		rc = avc_has_perm(old_tsec->sid, new_tsec->sid, +		rc = avc_has_perm(&selinux_state, +				  old_tsec->sid, new_tsec->sid,  				  SECCLASS_PROCESS, PROCESS__NOATSECURE,  				  NULL);  		bprm->secureexec |= !!rc; @@ -2575,7 +2652,8 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)  	 * higher than the default soft limit for cases where the default is  	 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.  	 */ -	rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, +	rc = avc_has_perm(&selinux_state, +			  new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,  			  PROCESS__RLIMITINH, NULL);  	if (rc) {  		/* protect against do_prlimit() */ @@ -2615,7 +2693,8 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)  	 * This must occur _after_ the task SID has been updated so that any  	 * kill done after the flush will be checked against the new SID.  	 */ -	rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); +	rc = avc_has_perm(&selinux_state, +			  osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);  	if (rc) {  		if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {  			memset(&itimer, 0, sizeof itimer); @@ -2779,7 +2858,9 @@ static int selinux_sb_remount(struct super_block *sb, void *data)  		if (flags[i] == SBLABEL_MNT)  			continue; -		rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL); +		rc = security_context_str_to_sid(&selinux_state, +						 mount_options[i], &sid, +						 GFP_KERNEL);  		if (rc) {  			printk(KERN_WARNING "SELinux: security_context_str_to_sid"  			       "(%s) failed for (dev %s, type %s) errno=%d\n", @@ -2904,7 +2985,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,  	if (rc)  		return rc; -	return security_sid_to_context(newsid, (char **)ctx, ctxlen); +	return security_sid_to_context(&selinux_state, newsid, (char **)ctx, +				       ctxlen);  }  static int selinux_dentry_create_files_as(struct dentry *dentry, int mode, @@ -2958,14 +3040,15 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,  		isec->initialized = LABEL_INITIALIZED;  	} -	if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT)) +	if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))  		return -EOPNOTSUPP;  	if (name)  		*name = XATTR_SELINUX_SUFFIX;  	if (value && len) { -		rc = security_sid_to_context_force(newsid, &context, &clen); +		rc = security_sid_to_context_force(&selinux_state, newsid, +						   &context, &clen);  		if (rc)  			return rc;  		*value = context; @@ -3040,7 +3123,8 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,  	if (IS_ERR(isec))  		return PTR_ERR(isec); -	return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad, +	return avc_has_perm_flags(&selinux_state, +				  sid, isec->sid, isec->sclass, FILE__READ, &ad,  				  rcu ? MAY_NOT_BLOCK : 0);  } @@ -3056,7 +3140,8 @@ static noinline int audit_inode_permission(struct inode *inode,  	ad.type = LSM_AUDIT_DATA_INODE;  	ad.u.inode = inode; -	rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms, +	rc = slow_avc_audit(&selinux_state, +			    current_sid(), isec->sid, isec->sclass, perms,  			    audited, denied, result, &ad, flags);  	if (rc)  		return rc; @@ -3094,7 +3179,8 @@ static int selinux_inode_permission(struct inode *inode, int mask)  	if (IS_ERR(isec))  		return PTR_ERR(isec); -	rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); +	rc = avc_has_perm_noaudit(&selinux_state, +				  sid, isec->sid, isec->sclass, perms, 0, &avd);  	audited = avc_audit_required(perms, &avd, rc,  				     from_access ? FILE__AUDIT_ACCESS : 0,  				     &denied); @@ -3126,7 +3212,7 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)  			ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))  		return dentry_has_perm(cred, dentry, FILE__SETATTR); -	if (selinux_policycap_openperm && +	if (selinux_policycap_openperm() &&  	    inode->i_sb->s_magic != SOCKFS_MAGIC &&  	    (ia_valid & ATTR_SIZE) &&  	    !(ia_valid & ATTR_FILE)) @@ -3183,12 +3269,14 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,  	ad.u.dentry = dentry;  	isec = backing_inode_security(dentry); -	rc = avc_has_perm(sid, isec->sid, isec->sclass, +	rc = avc_has_perm(&selinux_state, +			  sid, isec->sid, isec->sclass,  			  FILE__RELABELFROM, &ad);  	if (rc)  		return rc; -	rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); +	rc = security_context_to_sid(&selinux_state, value, size, &newsid, +				     GFP_KERNEL);  	if (rc == -EINVAL) {  		if (!has_cap_mac_admin(true)) {  			struct audit_buffer *ab; @@ -3213,22 +3301,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,  			return rc;  		} -		rc = security_context_to_sid_force(value, size, &newsid); +		rc = security_context_to_sid_force(&selinux_state, value, +						   size, &newsid);  	}  	if (rc)  		return rc; -	rc = avc_has_perm(sid, newsid, isec->sclass, +	rc = avc_has_perm(&selinux_state, +			  sid, newsid, isec->sclass,  			  FILE__RELABELTO, &ad);  	if (rc)  		return rc; -	rc = security_validate_transition(isec->sid, newsid, sid, -					  isec->sclass); +	rc = security_validate_transition(&selinux_state, isec->sid, newsid, +					  sid, isec->sclass);  	if (rc)  		return rc; -	return avc_has_perm(newsid, +	return avc_has_perm(&selinux_state, +			    newsid,  			    sbsec->sid,  			    SECCLASS_FILESYSTEM,  			    FILESYSTEM__ASSOCIATE, @@ -3249,7 +3340,8 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,  		return;  	} -	rc = security_context_to_sid_force(value, size, &newsid); +	rc = security_context_to_sid_force(&selinux_state, value, size, +					   &newsid);  	if (rc) {  		printk(KERN_ERR "SELinux:  unable to map context to SID"  		       "for (%s, %lu), rc=%d\n", @@ -3324,10 +3416,12 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void  	 */  	isec = inode_security(inode);  	if (has_cap_mac_admin(false)) -		error = security_sid_to_context_force(isec->sid, &context, +		error = security_sid_to_context_force(&selinux_state, +						      isec->sid, &context,  						      &size);  	else -		error = security_sid_to_context(isec->sid, &context, &size); +		error = security_sid_to_context(&selinux_state, isec->sid, +						&context, &size);  	if (error)  		return error;  	error = size; @@ -3353,7 +3447,8 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,  	if (!value || !size)  		return -EACCES; -	rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); +	rc = security_context_to_sid(&selinux_state, value, size, &newsid, +				     GFP_KERNEL);  	if (rc)  		return rc; @@ -3442,7 +3537,7 @@ static int selinux_file_permission(struct file *file, int mask)  	isec = inode_security(inode);  	if (sid == fsec->sid && fsec->isid == isec->sid && -	    fsec->pseqno == avc_policy_seqno()) +	    fsec->pseqno == avc_policy_seqno(&selinux_state))  		/* No change since file_open check. */  		return 0; @@ -3482,7 +3577,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,  	ad.u.op->path = file->f_path;  	if (ssid != fsec->sid) { -		rc = avc_has_perm(ssid, fsec->sid, +		rc = avc_has_perm(&selinux_state, +				  ssid, fsec->sid,  				SECCLASS_FD,  				FD__USE,  				&ad); @@ -3494,8 +3590,9 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,  		return 0;  	isec = inode_security(inode); -	rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, -			requested, driver, xperm, &ad); +	rc = avc_has_extended_perms(&selinux_state, +				    ssid, isec->sid, isec->sclass, +				    requested, driver, xperm, &ad);  out:  	return rc;  } @@ -3563,7 +3660,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared  		 * private file mapping that will also be writable.  		 * This has an additional check.  		 */ -		rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, +		rc = avc_has_perm(&selinux_state, +				  sid, sid, SECCLASS_PROCESS,  				  PROCESS__EXECMEM, NULL);  		if (rc)  			goto error; @@ -3593,7 +3691,8 @@ static int selinux_mmap_addr(unsigned long addr)  	if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {  		u32 sid = current_sid(); -		rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, +		rc = avc_has_perm(&selinux_state, +				  sid, sid, SECCLASS_MEMPROTECT,  				  MEMPROTECT__MMAP_ZERO, NULL);  	} @@ -3615,7 +3714,7 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot,  			return rc;  	} -	if (selinux_checkreqprot) +	if (selinux_state.checkreqprot)  		prot = reqprot;  	return file_map_prot_check(file, prot, @@ -3629,7 +3728,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,  	const struct cred *cred = current_cred();  	u32 sid = cred_sid(cred); -	if (selinux_checkreqprot) +	if (selinux_state.checkreqprot)  		prot = reqprot;  	if (default_noexec && @@ -3637,13 +3736,15 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,  		int rc = 0;  		if (vma->vm_start >= vma->vm_mm->start_brk &&  		    vma->vm_end <= vma->vm_mm->brk) { -			rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, +			rc = avc_has_perm(&selinux_state, +					  sid, sid, SECCLASS_PROCESS,  					  PROCESS__EXECHEAP, NULL);  		} else if (!vma->vm_file &&  			   ((vma->vm_start <= vma->vm_mm->start_stack &&  			     vma->vm_end >= vma->vm_mm->start_stack) ||  			    vma_is_stack_for_current(vma))) { -			rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, +			rc = avc_has_perm(&selinux_state, +					  sid, sid, SECCLASS_PROCESS,  					  PROCESS__EXECSTACK, NULL);  		} else if (vma->vm_file && vma->anon_vma) {  			/* @@ -3735,7 +3836,8 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,  	else  		perm = signal_to_av(signum); -	return avc_has_perm(fsec->fown_sid, sid, +	return avc_has_perm(&selinux_state, +			    fsec->fown_sid, sid,  			    SECCLASS_PROCESS, perm, NULL);  } @@ -3761,7 +3863,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred)  	 * struct as its SID.  	 */  	fsec->isid = isec->sid; -	fsec->pseqno = avc_policy_seqno(); +	fsec->pseqno = avc_policy_seqno(&selinux_state);  	/*  	 * Since the inode label or policy seqno may have changed  	 * between the selinux_inode_permission check and the saving @@ -3780,7 +3882,8 @@ static int selinux_task_alloc(struct task_struct *task,  {  	u32 sid = current_sid(); -	return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); +	return avc_has_perm(&selinux_state, +			    sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);  }  /* @@ -3844,6 +3947,11 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old)  	*tsec = *old_tsec;  } +static void selinux_cred_getsecid(const struct cred *c, u32 *secid) +{ +	*secid = cred_sid(c); +} +  /*   * set the security data for a kernel service   * - all the creation contexts are set to unlabelled @@ -3854,7 +3962,8 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid)  	u32 sid = current_sid();  	int ret; -	ret = avc_has_perm(sid, secid, +	ret = avc_has_perm(&selinux_state, +			   sid, secid,  			   SECCLASS_KERNEL_SERVICE,  			   KERNEL_SERVICE__USE_AS_OVERRIDE,  			   NULL); @@ -3878,7 +3987,8 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)  	u32 sid = current_sid();  	int ret; -	ret = avc_has_perm(sid, isec->sid, +	ret = avc_has_perm(&selinux_state, +			   sid, isec->sid,  			   SECCLASS_KERNEL_SERVICE,  			   KERNEL_SERVICE__CREATE_FILES_AS,  			   NULL); @@ -3895,7 +4005,8 @@ static int selinux_kernel_module_request(char *kmod_name)  	ad.type = LSM_AUDIT_DATA_KMOD;  	ad.u.kmod_name = kmod_name; -	return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, +	return avc_has_perm(&selinux_state, +			    current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,  			    SYSTEM__MODULE_REQUEST, &ad);  } @@ -3909,7 +4020,8 @@ static int selinux_kernel_module_from_file(struct file *file)  	/* init_module */  	if (file == NULL) -		return avc_has_perm(sid, sid, SECCLASS_SYSTEM, +		return avc_has_perm(&selinux_state, +				    sid, sid, SECCLASS_SYSTEM,  					SYSTEM__MODULE_LOAD, NULL);  	/* finit_module */ @@ -3919,13 +4031,15 @@ static int selinux_kernel_module_from_file(struct file *file)  	fsec = file->f_security;  	if (sid != fsec->sid) { -		rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); +		rc = avc_has_perm(&selinux_state, +				  sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);  		if (rc)  			return rc;  	}  	isec = inode_security(file_inode(file)); -	return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, +	return avc_has_perm(&selinux_state, +			    sid, isec->sid, SECCLASS_SYSTEM,  				SYSTEM__MODULE_LOAD, &ad);  } @@ -3947,19 +4061,22 @@ static int selinux_kernel_read_file(struct file *file,  static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__SETPGID, NULL);  }  static int selinux_task_getpgid(struct task_struct *p)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__GETPGID, NULL);  }  static int selinux_task_getsid(struct task_struct *p)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__GETSESSION, NULL);  } @@ -3970,19 +4087,22 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid)  static int selinux_task_setnice(struct task_struct *p, int nice)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__SETSCHED, NULL);  }  static int selinux_task_setioprio(struct task_struct *p, int ioprio)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__SETSCHED, NULL);  }  static int selinux_task_getioprio(struct task_struct *p)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__GETSCHED, NULL);  } @@ -3997,7 +4117,8 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre  		av |= PROCESS__SETRLIMIT;  	if (flags & LSM_PRLIMIT_READ)  		av |= PROCESS__GETRLIMIT; -	return avc_has_perm(cred_sid(cred), cred_sid(tcred), +	return avc_has_perm(&selinux_state, +			    cred_sid(cred), cred_sid(tcred),  			    SECCLASS_PROCESS, av, NULL);  } @@ -4011,7 +4132,8 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,  	   later be used as a safe reset point for the soft limit  	   upon context transitions.  See selinux_bprm_committing_creds. */  	if (old_rlim->rlim_max != new_rlim->rlim_max) -		return avc_has_perm(current_sid(), task_sid(p), +		return avc_has_perm(&selinux_state, +				    current_sid(), task_sid(p),  				    SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);  	return 0; @@ -4019,34 +4141,41 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,  static int selinux_task_setscheduler(struct task_struct *p)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__SETSCHED, NULL);  }  static int selinux_task_getscheduler(struct task_struct *p)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__GETSCHED, NULL);  }  static int selinux_task_movememory(struct task_struct *p)  { -	return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS, +	return avc_has_perm(&selinux_state, +			    current_sid(), task_sid(p), SECCLASS_PROCESS,  			    PROCESS__SETSCHED, NULL);  }  static int selinux_task_kill(struct task_struct *p, struct siginfo *info, -				int sig, u32 secid) +				int sig, const struct cred *cred)  { +	u32 secid;  	u32 perm;  	if (!sig)  		perm = PROCESS__SIGNULL; /* null signal; existence test */  	else  		perm = signal_to_av(sig); -	if (!secid) +	if (!cred)  		secid = current_sid(); -	return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL); +	else +		secid = cred_sid(cred); +	return avc_has_perm(&selinux_state, +			    secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);  }  static void selinux_task_to_inode(struct task_struct *p, @@ -4134,6 +4263,23 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,  		break;  	} +#if IS_ENABLED(CONFIG_IP_SCTP) +	case IPPROTO_SCTP: { +		struct sctphdr _sctph, *sh; + +		if (ntohs(ih->frag_off) & IP_OFFSET) +			break; + +		offset += ihlen; +		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); +		if (sh == NULL) +			break; + +		ad->u.net->sport = sh->source; +		ad->u.net->dport = sh->dest; +		break; +	} +#endif  	default:  		break;  	} @@ -4207,6 +4353,19 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,  		break;  	} +#if IS_ENABLED(CONFIG_IP_SCTP) +	case IPPROTO_SCTP: { +		struct sctphdr _sctph, *sh; + +		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); +		if (sh == NULL) +			break; + +		ad->u.net->sport = sh->source; +		ad->u.net->dport = sh->dest; +		break; +	} +#endif  	/* includes fragments */  	default:  		break; @@ -4287,7 +4446,8 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)  	if (unlikely(err))  		return -EACCES; -	err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); +	err = security_net_peersid_resolve(&selinux_state, nlbl_sid, +					   nlbl_type, xfrm_sid, sid);  	if (unlikely(err)) {  		printk(KERN_WARNING  		       "SELinux: failure in selinux_skb_peerlbl_sid()," @@ -4315,7 +4475,8 @@ static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)  	int err = 0;  	if (skb_sid != SECSID_NULL) -		err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid); +		err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid, +					    conn_sid);  	else  		*conn_sid = sk_sid; @@ -4332,8 +4493,8 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,  		return 0;  	} -	return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL, -				       socksid); +	return security_transition_sid(&selinux_state, tsec->sid, tsec->sid, +				       secclass, NULL, socksid);  }  static int sock_has_perm(struct sock *sk, u32 perms) @@ -4349,7 +4510,8 @@ static int sock_has_perm(struct sock *sk, u32 perms)  	ad.u.net = &net;  	ad.u.net->sk = sk; -	return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms, +	return avc_has_perm(&selinux_state, +			    current_sid(), sksec->sid, sksec->sclass, perms,  			    &ad);  } @@ -4369,7 +4531,8 @@ static int selinux_socket_create(int family, int type,  	if (rc)  		return rc; -	return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); +	return avc_has_perm(&selinux_state, +			    tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);  }  static int selinux_socket_post_create(struct socket *sock, int family, @@ -4396,6 +4559,10 @@ static int selinux_socket_post_create(struct socket *sock, int family,  		sksec = sock->sk->sk_security;  		sksec->sclass = sclass;  		sksec->sid = sid; +		/* Allows detection of the first association on this socket */ +		if (sksec->sclass == SECCLASS_SCTP_SOCKET) +			sksec->sctp_assoc_state = SCTP_ASSOC_UNSET; +  		err = selinux_netlbl_socket_post_create(sock->sk, family);  	} @@ -4416,11 +4583,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  	if (err)  		goto out; -	/* -	 * If PF_INET or PF_INET6, check name_bind permission for the port. -	 * Multiple address binding for SCTP is not supported yet: we just -	 * check the first address now. -	 */ +	/* If PF_INET or PF_INET6, check name_bind permission for the port. */  	family = sk->sk_family;  	if (family == PF_INET || family == PF_INET6) {  		char *addrp; @@ -4432,22 +4595,35 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  		unsigned short snum;  		u32 sid, node_perm; -		if (family == PF_INET) { -			if (addrlen < sizeof(struct sockaddr_in)) { -				err = -EINVAL; -				goto out; -			} +		/* +		 * sctp_bindx(3) calls via selinux_sctp_bind_connect() +		 * that validates multiple binding addresses. Because of this +		 * need to check address->sa_family as it is possible to have +		 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. +		 */ +		switch (address->sa_family) { +		case AF_INET: +			if (addrlen < sizeof(struct sockaddr_in)) +				return -EINVAL;  			addr4 = (struct sockaddr_in *)address;  			snum = ntohs(addr4->sin_port);  			addrp = (char *)&addr4->sin_addr.s_addr; -		} else { -			if (addrlen < SIN6_LEN_RFC2133) { -				err = -EINVAL; -				goto out; -			} +			break; +		case AF_INET6: +			if (addrlen < SIN6_LEN_RFC2133) +				return -EINVAL;  			addr6 = (struct sockaddr_in6 *)address;  			snum = ntohs(addr6->sin6_port);  			addrp = (char *)&addr6->sin6_addr.s6_addr; +			break; +		default: +			/* Note that SCTP services expect -EINVAL, whereas +			 * others expect -EAFNOSUPPORT. +			 */ +			if (sksec->sclass == SECCLASS_SCTP_SOCKET) +				return -EINVAL; +			else +				return -EAFNOSUPPORT;  		}  		if (snum) { @@ -4465,7 +4641,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  				ad.u.net = &net;  				ad.u.net->sport = htons(snum);  				ad.u.net->family = family; -				err = avc_has_perm(sksec->sid, sid, +				err = avc_has_perm(&selinux_state, +						   sksec->sid, sid,  						   sksec->sclass,  						   SOCKET__NAME_BIND, &ad);  				if (err) @@ -4486,6 +4663,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  			node_perm = DCCP_SOCKET__NODE_BIND;  			break; +		case SECCLASS_SCTP_SOCKET: +			node_perm = SCTP_SOCKET__NODE_BIND; +			break; +  		default:  			node_perm = RAWIP_SOCKET__NODE_BIND;  			break; @@ -4500,12 +4681,13 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  		ad.u.net->sport = htons(snum);  		ad.u.net->family = family; -		if (family == PF_INET) +		if (address->sa_family == AF_INET)  			ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;  		else  			ad.u.net->v6info.saddr = addr6->sin6_addr; -		err = avc_has_perm(sksec->sid, sid, +		err = avc_has_perm(&selinux_state, +				   sksec->sid, sid,  				   sksec->sclass, node_perm, &ad);  		if (err)  			goto out; @@ -4514,7 +4696,11 @@ out:  	return err;  } -static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) +/* This supports connect(2) and SCTP connect services such as sctp_connectx(3) + * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.txt + */ +static int selinux_socket_connect_helper(struct socket *sock, +					 struct sockaddr *address, int addrlen)  {  	struct sock *sk = sock->sk;  	struct sk_security_struct *sksec = sk->sk_security; @@ -4525,10 +4711,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,  		return err;  	/* -	 * If a TCP or DCCP socket, check name_connect permission for the port. +	 * If a TCP, DCCP or SCTP socket, check name_connect permission +	 * for the port.  	 */  	if (sksec->sclass == SECCLASS_TCP_SOCKET || -	    sksec->sclass == SECCLASS_DCCP_SOCKET) { +	    sksec->sclass == SECCLASS_DCCP_SOCKET || +	    sksec->sclass == SECCLASS_SCTP_SOCKET) {  		struct common_audit_data ad;  		struct lsm_network_audit net = {0,};  		struct sockaddr_in *addr4 = NULL; @@ -4536,38 +4724,75 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,  		unsigned short snum;  		u32 sid, perm; -		if (sk->sk_family == PF_INET) { +		/* sctp_connectx(3) calls via selinux_sctp_bind_connect() +		 * that validates multiple connect addresses. Because of this +		 * need to check address->sa_family as it is possible to have +		 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. +		 */ +		switch (address->sa_family) { +		case AF_INET:  			addr4 = (struct sockaddr_in *)address;  			if (addrlen < sizeof(struct sockaddr_in))  				return -EINVAL;  			snum = ntohs(addr4->sin_port); -		} else { +			break; +		case AF_INET6:  			addr6 = (struct sockaddr_in6 *)address;  			if (addrlen < SIN6_LEN_RFC2133)  				return -EINVAL;  			snum = ntohs(addr6->sin6_port); +			break; +		default: +			/* Note that SCTP services expect -EINVAL, whereas +			 * others expect -EAFNOSUPPORT. +			 */ +			if (sksec->sclass == SECCLASS_SCTP_SOCKET) +				return -EINVAL; +			else +				return -EAFNOSUPPORT;  		}  		err = sel_netport_sid(sk->sk_protocol, snum, &sid);  		if (err) -			goto out; +			return err; -		perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? -		       TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; +		switch (sksec->sclass) { +		case SECCLASS_TCP_SOCKET: +			perm = TCP_SOCKET__NAME_CONNECT; +			break; +		case SECCLASS_DCCP_SOCKET: +			perm = DCCP_SOCKET__NAME_CONNECT; +			break; +		case SECCLASS_SCTP_SOCKET: +			perm = SCTP_SOCKET__NAME_CONNECT; +			break; +		}  		ad.type = LSM_AUDIT_DATA_NET;  		ad.u.net = &net;  		ad.u.net->dport = htons(snum);  		ad.u.net->family = sk->sk_family; -		err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); +		err = avc_has_perm(&selinux_state, +				   sksec->sid, sid, sksec->sclass, perm, &ad);  		if (err) -			goto out; +			return err;  	} -	err = selinux_netlbl_socket_connect(sk, address); +	return 0; +} -out: -	return err; +/* Supports connect(2), see comments in selinux_socket_connect_helper() */ +static int selinux_socket_connect(struct socket *sock, +				  struct sockaddr *address, int addrlen) +{ +	int err; +	struct sock *sk = sock->sk; + +	err = selinux_socket_connect_helper(sock, address, addrlen); +	if (err) +		return err; + +	return selinux_netlbl_socket_connect(sk, address);  }  static int selinux_socket_listen(struct socket *sock, int backlog) @@ -4660,7 +4885,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,  	ad.u.net = &net;  	ad.u.net->sk = other; -	err = avc_has_perm(sksec_sock->sid, sksec_other->sid, +	err = avc_has_perm(&selinux_state, +			   sksec_sock->sid, sksec_other->sid,  			   sksec_other->sclass,  			   UNIX_STREAM_SOCKET__CONNECTTO, &ad);  	if (err) @@ -4668,8 +4894,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,  	/* server child socket */  	sksec_new->peer_sid = sksec_sock->sid; -	err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, -				    &sksec_new->sid); +	err = security_sid_mls_copy(&selinux_state, sksec_other->sid, +				    sksec_sock->sid, &sksec_new->sid);  	if (err)  		return err; @@ -4691,7 +4917,8 @@ static int selinux_socket_unix_may_send(struct socket *sock,  	ad.u.net = &net;  	ad.u.net->sk = other->sk; -	return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, +	return avc_has_perm(&selinux_state, +			    ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,  			    &ad);  } @@ -4706,7 +4933,8 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,  	err = sel_netif_sid(ns, ifindex, &if_sid);  	if (err)  		return err; -	err = avc_has_perm(peer_sid, if_sid, +	err = avc_has_perm(&selinux_state, +			   peer_sid, if_sid,  			   SECCLASS_NETIF, NETIF__INGRESS, ad);  	if (err)  		return err; @@ -4714,7 +4942,8 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,  	err = sel_netnode_sid(addrp, family, &node_sid);  	if (err)  		return err; -	return avc_has_perm(peer_sid, node_sid, +	return avc_has_perm(&selinux_state, +			    peer_sid, node_sid,  			    SECCLASS_NODE, NODE__RECVFROM, ad);  } @@ -4737,7 +4966,8 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,  		return err;  	if (selinux_secmark_enabled()) { -		err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, +		err = avc_has_perm(&selinux_state, +				   sk_sid, skb->secmark, SECCLASS_PACKET,  				   PACKET__RECV, &ad);  		if (err)  			return err; @@ -4774,7 +5004,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)  	 * to the selinux_sock_rcv_skb_compat() function to deal with the  	 * special handling.  We do this in an attempt to keep this function  	 * as fast and as clean as possible. */ -	if (!selinux_policycap_netpeer) +	if (!selinux_policycap_netpeer())  		return selinux_sock_rcv_skb_compat(sk, skb, family);  	secmark_active = selinux_secmark_enabled(); @@ -4802,7 +5032,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)  			selinux_netlbl_err(skb, family, err, 0);  			return err;  		} -		err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, +		err = avc_has_perm(&selinux_state, +				   sk_sid, peer_sid, SECCLASS_PEER,  				   PEER__RECV, &ad);  		if (err) {  			selinux_netlbl_err(skb, family, err, 0); @@ -4811,7 +5042,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)  	}  	if (secmark_active) { -		err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, +		err = avc_has_perm(&selinux_state, +				   sk_sid, skb->secmark, SECCLASS_PACKET,  				   PACKET__RECV, &ad);  		if (err)  			return err; @@ -4830,12 +5062,14 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op  	u32 peer_sid = SECSID_NULL;  	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || -	    sksec->sclass == SECCLASS_TCP_SOCKET) +	    sksec->sclass == SECCLASS_TCP_SOCKET || +	    sksec->sclass == SECCLASS_SCTP_SOCKET)  		peer_sid = sksec->peer_sid;  	if (peer_sid == SECSID_NULL)  		return -ENOPROTOOPT; -	err = security_sid_to_context(peer_sid, &scontext, &scontext_len); +	err = security_sid_to_context(&selinux_state, peer_sid, &scontext, +				      &scontext_len);  	if (err)  		return err; @@ -4943,6 +5177,172 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)  	sksec->sclass = isec->sclass;  } +/* Called whenever SCTP receives an INIT chunk. This happens when an incoming + * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association + * already present). + */ +static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, +				      struct sk_buff *skb) +{ +	struct sk_security_struct *sksec = ep->base.sk->sk_security; +	struct common_audit_data ad; +	struct lsm_network_audit net = {0,}; +	u8 peerlbl_active; +	u32 peer_sid = SECINITSID_UNLABELED; +	u32 conn_sid; +	int err = 0; + +	if (!selinux_policycap_extsockclass()) +		return 0; + +	peerlbl_active = selinux_peerlbl_enabled(); + +	if (peerlbl_active) { +		/* This will return peer_sid = SECSID_NULL if there are +		 * no peer labels, see security_net_peersid_resolve(). +		 */ +		err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family, +					      &peer_sid); +		if (err) +			return err; + +		if (peer_sid == SECSID_NULL) +			peer_sid = SECINITSID_UNLABELED; +	} + +	if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) { +		sksec->sctp_assoc_state = SCTP_ASSOC_SET; + +		/* Here as first association on socket. As the peer SID +		 * was allowed by peer recv (and the netif/node checks), +		 * then it is approved by policy and used as the primary +		 * peer SID for getpeercon(3). +		 */ +		sksec->peer_sid = peer_sid; +	} else if  (sksec->peer_sid != peer_sid) { +		/* Other association peer SIDs are checked to enforce +		 * consistency among the peer SIDs. +		 */ +		ad.type = LSM_AUDIT_DATA_NET; +		ad.u.net = &net; +		ad.u.net->sk = ep->base.sk; +		err = avc_has_perm(&selinux_state, +				   sksec->peer_sid, peer_sid, sksec->sclass, +				   SCTP_SOCKET__ASSOCIATION, &ad); +		if (err) +			return err; +	} + +	/* Compute the MLS component for the connection and store +	 * the information in ep. This will be used by SCTP TCP type +	 * sockets and peeled off connections as they cause a new +	 * socket to be generated. selinux_sctp_sk_clone() will then +	 * plug this into the new socket. +	 */ +	err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid); +	if (err) +		return err; + +	ep->secid = conn_sid; +	ep->peer_secid = peer_sid; + +	/* Set any NetLabel labels including CIPSO/CALIPSO options. */ +	return selinux_netlbl_sctp_assoc_request(ep, skb); +} + +/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting + * based on their @optname. + */ +static int selinux_sctp_bind_connect(struct sock *sk, int optname, +				     struct sockaddr *address, +				     int addrlen) +{ +	int len, err = 0, walk_size = 0; +	void *addr_buf; +	struct sockaddr *addr; +	struct socket *sock; + +	if (!selinux_policycap_extsockclass()) +		return 0; + +	/* Process one or more addresses that may be IPv4 or IPv6 */ +	sock = sk->sk_socket; +	addr_buf = address; + +	while (walk_size < addrlen) { +		addr = addr_buf; +		switch (addr->sa_family) { +		case AF_INET: +			len = sizeof(struct sockaddr_in); +			break; +		case AF_INET6: +			len = sizeof(struct sockaddr_in6); +			break; +		default: +			return -EAFNOSUPPORT; +		} + +		err = -EINVAL; +		switch (optname) { +		/* Bind checks */ +		case SCTP_PRIMARY_ADDR: +		case SCTP_SET_PEER_PRIMARY_ADDR: +		case SCTP_SOCKOPT_BINDX_ADD: +			err = selinux_socket_bind(sock, addr, len); +			break; +		/* Connect checks */ +		case SCTP_SOCKOPT_CONNECTX: +		case SCTP_PARAM_SET_PRIMARY: +		case SCTP_PARAM_ADD_IP: +		case SCTP_SENDMSG_CONNECT: +			err = selinux_socket_connect_helper(sock, addr, len); +			if (err) +				return err; + +			/* As selinux_sctp_bind_connect() is called by the +			 * SCTP protocol layer, the socket is already locked, +			 * therefore selinux_netlbl_socket_connect_locked() is +			 * is called here. The situations handled are: +			 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2), +			 * whenever a new IP address is added or when a new +			 * primary address is selected. +			 * Note that an SCTP connect(2) call happens before +			 * the SCTP protocol layer and is handled via +			 * selinux_socket_connect(). +			 */ +			err = selinux_netlbl_socket_connect_locked(sk, addr); +			break; +		} + +		if (err) +			return err; + +		addr_buf += len; +		walk_size += len; +	} + +	return 0; +} + +/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */ +static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, +				  struct sock *newsk) +{ +	struct sk_security_struct *sksec = sk->sk_security; +	struct sk_security_struct *newsksec = newsk->sk_security; + +	/* If policy does not support SECCLASS_SCTP_SOCKET then call +	 * the non-sctp clone version. +	 */ +	if (!selinux_policycap_extsockclass()) +		return selinux_sk_clone_security(sk, newsk); + +	newsksec->sid = ep->secid; +	newsksec->peer_sid = ep->peer_secid; +	newsksec->sclass = sksec->sclass; +	selinux_netlbl_sctp_sk_clone(sk, newsk); +} +  static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,  				     struct request_sock *req)  { @@ -5001,7 +5401,9 @@ static int selinux_secmark_relabel_packet(u32 sid)  	__tsec = current_security();  	tsid = __tsec->sid; -	return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); +	return avc_has_perm(&selinux_state, +			    tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, +			    NULL);  }  static void selinux_secmark_refcount_inc(void) @@ -5049,7 +5451,8 @@ static int selinux_tun_dev_create(void)  	 * connections unlike traditional sockets - check the TUN driver to  	 * get a better understanding of why this socket is special */ -	return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, +	return avc_has_perm(&selinux_state, +			    sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,  			    NULL);  } @@ -5057,7 +5460,8 @@ static int selinux_tun_dev_attach_queue(void *security)  {  	struct tun_security_struct *tunsec = security; -	return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, +	return avc_has_perm(&selinux_state, +			    current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,  			    TUN_SOCKET__ATTACH_QUEUE, NULL);  } @@ -5085,11 +5489,13 @@ static int selinux_tun_dev_open(void *security)  	u32 sid = current_sid();  	int err; -	err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET, +	err = avc_has_perm(&selinux_state, +			   sid, tunsec->sid, SECCLASS_TUN_SOCKET,  			   TUN_SOCKET__RELABELFROM, NULL);  	if (err)  		return err; -	err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, +	err = avc_has_perm(&selinux_state, +			   sid, sid, SECCLASS_TUN_SOCKET,  			   TUN_SOCKET__RELABELTO, NULL);  	if (err)  		return err; @@ -5120,7 +5526,8 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)  			       sk->sk_protocol, nlh->nlmsg_type,  			       secclass_map[sksec->sclass - 1].name,  			       task_pid_nr(current), current->comm); -			if (!selinux_enforcing || security_get_allow_unknown()) +			if (!enforcing_enabled(&selinux_state) || +			    security_get_allow_unknown(&selinux_state))  				err = 0;  		} @@ -5150,7 +5557,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb,  	u8 netlbl_active;  	u8 peerlbl_active; -	if (!selinux_policycap_netpeer) +	if (!selinux_policycap_netpeer())  		return NF_ACCEPT;  	secmark_active = selinux_secmark_enabled(); @@ -5179,7 +5586,8 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb,  	}  	if (secmark_active) -		if (avc_has_perm(peer_sid, skb->secmark, +		if (avc_has_perm(&selinux_state, +				 peer_sid, skb->secmark,  				 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))  			return NF_DROP; @@ -5291,7 +5699,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,  		return NF_DROP;  	if (selinux_secmark_enabled()) -		if (avc_has_perm(sksec->sid, skb->secmark, +		if (avc_has_perm(&selinux_state, +				 sksec->sid, skb->secmark,  				 SECCLASS_PACKET, PACKET__SEND, &ad))  			return NF_DROP_ERR(-ECONNREFUSED); @@ -5319,7 +5728,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,  	 * to the selinux_ip_postroute_compat() function to deal with the  	 * special handling.  We do this in an attempt to keep this function  	 * as fast and as clean as possible. */ -	if (!selinux_policycap_netpeer) +	if (!selinux_policycap_netpeer())  		return selinux_ip_postroute_compat(skb, ifindex, family);  	secmark_active = selinux_secmark_enabled(); @@ -5414,7 +5823,8 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,  		return NF_DROP;  	if (secmark_active) -		if (avc_has_perm(peer_sid, skb->secmark, +		if (avc_has_perm(&selinux_state, +				 peer_sid, skb->secmark,  				 SECCLASS_PACKET, secmark_perm, &ad))  			return NF_DROP_ERR(-ECONNREFUSED); @@ -5424,13 +5834,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,  		if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))  			return NF_DROP; -		if (avc_has_perm(peer_sid, if_sid, +		if (avc_has_perm(&selinux_state, +				 peer_sid, if_sid,  				 SECCLASS_NETIF, NETIF__EGRESS, &ad))  			return NF_DROP_ERR(-ECONNREFUSED);  		if (sel_netnode_sid(addrp, family, &node_sid))  			return NF_DROP; -		if (avc_has_perm(peer_sid, node_sid, +		if (avc_has_perm(&selinux_state, +				 peer_sid, node_sid,  				 SECCLASS_NODE, NODE__SENDTO, &ad))  			return NF_DROP_ERR(-ECONNREFUSED);  	} @@ -5518,7 +5930,8 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,  	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = ipc_perms->key; -	return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); +	return avc_has_perm(&selinux_state, +			    sid, isec->sid, isec->sclass, perms, &ad);  }  static int selinux_msg_msg_alloc_security(struct msg_msg *msg) @@ -5532,52 +5945,54 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg)  }  /* message queue security operations */ -static int selinux_msg_queue_alloc_security(struct msg_queue *msq) +static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad;  	u32 sid = current_sid();  	int rc; -	rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ); +	rc = ipc_alloc_security(msq, SECCLASS_MSGQ);  	if (rc)  		return rc; -	isec = msq->q_perm.security; +	isec = msq->security;  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = msq->q_perm.key; +	ad.u.ipc_id = msq->key; -	rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, +	rc = avc_has_perm(&selinux_state, +			  sid, isec->sid, SECCLASS_MSGQ,  			  MSGQ__CREATE, &ad);  	if (rc) { -		ipc_free_security(&msq->q_perm); +		ipc_free_security(msq);  		return rc;  	}  	return 0;  } -static void selinux_msg_queue_free_security(struct msg_queue *msq) +static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq)  { -	ipc_free_security(&msq->q_perm); +	ipc_free_security(msq);  } -static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) +static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad;  	u32 sid = current_sid(); -	isec = msq->q_perm.security; +	isec = msq->security;  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = msq->q_perm.key; +	ad.u.ipc_id = msq->key; -	return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, +	return avc_has_perm(&selinux_state, +			    sid, isec->sid, SECCLASS_MSGQ,  			    MSGQ__ASSOCIATE, &ad);  } -static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) +static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)  {  	int err;  	int perms; @@ -5586,10 +6001,12 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)  	case IPC_INFO:  	case MSG_INFO:  		/* No specific object, just general system-wide information. */ -		return avc_has_perm(current_sid(), SECINITSID_KERNEL, +		return avc_has_perm(&selinux_state, +				    current_sid(), SECINITSID_KERNEL,  				    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);  	case IPC_STAT:  	case MSG_STAT: +	case MSG_STAT_ANY:  		perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;  		break;  	case IPC_SET: @@ -5602,11 +6019,11 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)  		return 0;  	} -	err = ipc_has_perm(&msq->q_perm, perms); +	err = ipc_has_perm(msq, perms);  	return err;  } -static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg) +static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)  {  	struct ipc_security_struct *isec;  	struct msg_security_struct *msec; @@ -5614,7 +6031,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,  	u32 sid = current_sid();  	int rc; -	isec = msq->q_perm.security; +	isec = msq->security;  	msec = msg->security;  	/* @@ -5625,31 +6042,34 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,  		 * Compute new sid based on current process and  		 * message queue this message will be stored in  		 */ -		rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, -					     NULL, &msec->sid); +		rc = security_transition_sid(&selinux_state, sid, isec->sid, +					     SECCLASS_MSG, NULL, &msec->sid);  		if (rc)  			return rc;  	}  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = msq->q_perm.key; +	ad.u.ipc_id = msq->key;  	/* Can this process write to the queue? */ -	rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, +	rc = avc_has_perm(&selinux_state, +			  sid, isec->sid, SECCLASS_MSGQ,  			  MSGQ__WRITE, &ad);  	if (!rc)  		/* Can this process send the message */ -		rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG, +		rc = avc_has_perm(&selinux_state, +				  sid, msec->sid, SECCLASS_MSG,  				  MSG__SEND, &ad);  	if (!rc)  		/* Can the message be put in the queue? */ -		rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ, +		rc = avc_has_perm(&selinux_state, +				  msec->sid, isec->sid, SECCLASS_MSGQ,  				  MSGQ__ENQUEUE, &ad);  	return rc;  } -static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, +static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,  				    struct task_struct *target,  				    long type, int mode)  { @@ -5659,68 +6079,72 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,  	u32 sid = task_sid(target);  	int rc; -	isec = msq->q_perm.security; +	isec = msq->security;  	msec = msg->security;  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = msq->q_perm.key; +	ad.u.ipc_id = msq->key; -	rc = avc_has_perm(sid, isec->sid, +	rc = avc_has_perm(&selinux_state, +			  sid, isec->sid,  			  SECCLASS_MSGQ, MSGQ__READ, &ad);  	if (!rc) -		rc = avc_has_perm(sid, msec->sid, +		rc = avc_has_perm(&selinux_state, +				  sid, msec->sid,  				  SECCLASS_MSG, MSG__RECEIVE, &ad);  	return rc;  }  /* Shared Memory security operations */ -static int selinux_shm_alloc_security(struct shmid_kernel *shp) +static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad;  	u32 sid = current_sid();  	int rc; -	rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM); +	rc = ipc_alloc_security(shp, SECCLASS_SHM);  	if (rc)  		return rc; -	isec = shp->shm_perm.security; +	isec = shp->security;  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = shp->shm_perm.key; +	ad.u.ipc_id = shp->key; -	rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, +	rc = avc_has_perm(&selinux_state, +			  sid, isec->sid, SECCLASS_SHM,  			  SHM__CREATE, &ad);  	if (rc) { -		ipc_free_security(&shp->shm_perm); +		ipc_free_security(shp);  		return rc;  	}  	return 0;  } -static void selinux_shm_free_security(struct shmid_kernel *shp) +static void selinux_shm_free_security(struct kern_ipc_perm *shp)  { -	ipc_free_security(&shp->shm_perm); +	ipc_free_security(shp);  } -static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) +static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad;  	u32 sid = current_sid(); -	isec = shp->shm_perm.security; +	isec = shp->security;  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = shp->shm_perm.key; +	ad.u.ipc_id = shp->key; -	return avc_has_perm(sid, isec->sid, SECCLASS_SHM, +	return avc_has_perm(&selinux_state, +			    sid, isec->sid, SECCLASS_SHM,  			    SHM__ASSOCIATE, &ad);  }  /* Note, at this point, shp is locked down */ -static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) +static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)  {  	int perms;  	int err; @@ -5729,10 +6153,12 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)  	case IPC_INFO:  	case SHM_INFO:  		/* No specific object, just general system-wide information. */ -		return avc_has_perm(current_sid(), SECINITSID_KERNEL, +		return avc_has_perm(&selinux_state, +				    current_sid(), SECINITSID_KERNEL,  				    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);  	case IPC_STAT:  	case SHM_STAT: +	case SHM_STAT_ANY:  		perms = SHM__GETATTR | SHM__ASSOCIATE;  		break;  	case IPC_SET: @@ -5749,11 +6175,11 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)  		return 0;  	} -	err = ipc_has_perm(&shp->shm_perm, perms); +	err = ipc_has_perm(shp, perms);  	return err;  } -static int selinux_shm_shmat(struct shmid_kernel *shp, +static int selinux_shm_shmat(struct kern_ipc_perm *shp,  			     char __user *shmaddr, int shmflg)  {  	u32 perms; @@ -5763,57 +6189,59 @@ static int selinux_shm_shmat(struct shmid_kernel *shp,  	else  		perms = SHM__READ | SHM__WRITE; -	return ipc_has_perm(&shp->shm_perm, perms); +	return ipc_has_perm(shp, perms);  }  /* Semaphore security operations */ -static int selinux_sem_alloc_security(struct sem_array *sma) +static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad;  	u32 sid = current_sid();  	int rc; -	rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM); +	rc = ipc_alloc_security(sma, SECCLASS_SEM);  	if (rc)  		return rc; -	isec = sma->sem_perm.security; +	isec = sma->security;  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = sma->sem_perm.key; +	ad.u.ipc_id = sma->key; -	rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, +	rc = avc_has_perm(&selinux_state, +			  sid, isec->sid, SECCLASS_SEM,  			  SEM__CREATE, &ad);  	if (rc) { -		ipc_free_security(&sma->sem_perm); +		ipc_free_security(sma);  		return rc;  	}  	return 0;  } -static void selinux_sem_free_security(struct sem_array *sma) +static void selinux_sem_free_security(struct kern_ipc_perm *sma)  { -	ipc_free_security(&sma->sem_perm); +	ipc_free_security(sma);  } -static int selinux_sem_associate(struct sem_array *sma, int semflg) +static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad;  	u32 sid = current_sid(); -	isec = sma->sem_perm.security; +	isec = sma->security;  	ad.type = LSM_AUDIT_DATA_IPC; -	ad.u.ipc_id = sma->sem_perm.key; +	ad.u.ipc_id = sma->key; -	return avc_has_perm(sid, isec->sid, SECCLASS_SEM, +	return avc_has_perm(&selinux_state, +			    sid, isec->sid, SECCLASS_SEM,  			    SEM__ASSOCIATE, &ad);  }  /* Note, at this point, sma is locked down */ -static int selinux_sem_semctl(struct sem_array *sma, int cmd) +static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)  {  	int err;  	u32 perms; @@ -5822,7 +6250,8 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)  	case IPC_INFO:  	case SEM_INFO:  		/* No specific object, just general system-wide information. */ -		return avc_has_perm(current_sid(), SECINITSID_KERNEL, +		return avc_has_perm(&selinux_state, +				    current_sid(), SECINITSID_KERNEL,  				    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);  	case GETPID:  	case GETNCNT: @@ -5845,17 +6274,18 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)  		break;  	case IPC_STAT:  	case SEM_STAT: +	case SEM_STAT_ANY:  		perms = SEM__GETATTR | SEM__ASSOCIATE;  		break;  	default:  		return 0;  	} -	err = ipc_has_perm(&sma->sem_perm, perms); +	err = ipc_has_perm(sma, perms);  	return err;  } -static int selinux_sem_semop(struct sem_array *sma, +static int selinux_sem_semop(struct kern_ipc_perm *sma,  			     struct sembuf *sops, unsigned nsops, int alter)  {  	u32 perms; @@ -5865,7 +6295,7 @@ static int selinux_sem_semop(struct sem_array *sma,  	else  		perms = SEM__READ; -	return ipc_has_perm(&sma->sem_perm, perms); +	return ipc_has_perm(sma, perms);  }  static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) @@ -5908,7 +6338,8 @@ static int selinux_getprocattr(struct task_struct *p,  	__tsec = __task_cred(p)->security;  	if (current != p) { -		error = avc_has_perm(current_sid(), __tsec->sid, +		error = avc_has_perm(&selinux_state, +				     current_sid(), __tsec->sid,  				     SECCLASS_PROCESS, PROCESS__GETATTR, NULL);  		if (error)  			goto bad; @@ -5935,7 +6366,7 @@ static int selinux_getprocattr(struct task_struct *p,  	if (!sid)  		return 0; -	error = security_sid_to_context(sid, value, &len); +	error = security_sid_to_context(&selinux_state, sid, value, &len);  	if (error)  		return error;  	return len; @@ -5957,19 +6388,24 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)  	 * Basic control over ability to set these attributes at all.  	 */  	if (!strcmp(name, "exec")) -		error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, +		error = avc_has_perm(&selinux_state, +				     mysid, mysid, SECCLASS_PROCESS,  				     PROCESS__SETEXEC, NULL);  	else if (!strcmp(name, "fscreate")) -		error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, +		error = avc_has_perm(&selinux_state, +				     mysid, mysid, SECCLASS_PROCESS,  				     PROCESS__SETFSCREATE, NULL);  	else if (!strcmp(name, "keycreate")) -		error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, +		error = avc_has_perm(&selinux_state, +				     mysid, mysid, SECCLASS_PROCESS,  				     PROCESS__SETKEYCREATE, NULL);  	else if (!strcmp(name, "sockcreate")) -		error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, +		error = avc_has_perm(&selinux_state, +				     mysid, mysid, SECCLASS_PROCESS,  				     PROCESS__SETSOCKCREATE, NULL);  	else if (!strcmp(name, "current")) -		error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, +		error = avc_has_perm(&selinux_state, +				     mysid, mysid, SECCLASS_PROCESS,  				     PROCESS__SETCURRENT, NULL);  	else  		error = -EINVAL; @@ -5982,7 +6418,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)  			str[size-1] = 0;  			size--;  		} -		error = security_context_to_sid(value, size, &sid, GFP_KERNEL); +		error = security_context_to_sid(&selinux_state, value, size, +						&sid, GFP_KERNEL);  		if (error == -EINVAL && !strcmp(name, "fscreate")) {  			if (!has_cap_mac_admin(true)) {  				struct audit_buffer *ab; @@ -6001,8 +6438,9 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)  				return error;  			} -			error = security_context_to_sid_force(value, size, -							      &sid); +			error = security_context_to_sid_force( +						      &selinux_state, +						      value, size, &sid);  		}  		if (error)  			return error; @@ -6024,7 +6462,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)  	} else if (!strcmp(name, "fscreate")) {  		tsec->create_sid = sid;  	} else if (!strcmp(name, "keycreate")) { -		error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE, +		error = avc_has_perm(&selinux_state, +				     mysid, sid, SECCLASS_KEY, KEY__CREATE,  				     NULL);  		if (error)  			goto abort_change; @@ -6039,13 +6478,15 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)  		/* Only allow single threaded processes to change context */  		error = -EPERM;  		if (!current_is_single_threaded()) { -			error = security_bounded_transition(tsec->sid, sid); +			error = security_bounded_transition(&selinux_state, +							    tsec->sid, sid);  			if (error)  				goto abort_change;  		}  		/* Check permissions for the transition. */ -		error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, +		error = avc_has_perm(&selinux_state, +				     tsec->sid, sid, SECCLASS_PROCESS,  				     PROCESS__DYNTRANSITION, NULL);  		if (error)  			goto abort_change; @@ -6054,7 +6495,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)  		   Otherwise, leave SID unchanged and fail. */  		ptsid = ptrace_parent_sid();  		if (ptsid != 0) { -			error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, +			error = avc_has_perm(&selinux_state, +					     ptsid, sid, SECCLASS_PROCESS,  					     PROCESS__PTRACE, NULL);  			if (error)  				goto abort_change; @@ -6081,12 +6523,14 @@ static int selinux_ismaclabel(const char *name)  static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)  { -	return security_sid_to_context(secid, secdata, seclen); +	return security_sid_to_context(&selinux_state, secid, +				       secdata, seclen);  }  static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)  { -	return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL); +	return security_context_to_sid(&selinux_state, secdata, seclen, +				       secid, GFP_KERNEL);  }  static void selinux_release_secctx(char *secdata, u32 seclen) @@ -6178,7 +6622,8 @@ static int selinux_key_permission(key_ref_t key_ref,  	key = key_ref_to_ptr(key_ref);  	ksec = key->security; -	return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL); +	return avc_has_perm(&selinux_state, +			    sid, ksec->sid, SECCLASS_KEY, perm, NULL);  }  static int selinux_key_getsecurity(struct key *key, char **_buffer) @@ -6188,7 +6633,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)  	unsigned len;  	int rc; -	rc = security_sid_to_context(ksec->sid, &context, &len); +	rc = security_sid_to_context(&selinux_state, ksec->sid, +				     &context, &len);  	if (!rc)  		rc = len;  	*_buffer = context; @@ -6213,7 +6659,8 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)  	ibpkey.subnet_prefix = subnet_prefix;  	ibpkey.pkey = pkey_val;  	ad.u.ibpkey = &ibpkey; -	return avc_has_perm(sec->sid, sid, +	return avc_has_perm(&selinux_state, +			    sec->sid, sid,  			    SECCLASS_INFINIBAND_PKEY,  			    INFINIBAND_PKEY__ACCESS, &ad);  } @@ -6227,7 +6674,8 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,  	struct ib_security_struct *sec = ib_sec;  	struct lsm_ibendport_audit ibendport; -	err = security_ib_endport_sid(dev_name, port_num, &sid); +	err = security_ib_endport_sid(&selinux_state, dev_name, port_num, +				      &sid);  	if (err)  		return err; @@ -6236,7 +6684,8 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,  	strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));  	ibendport.port = port_num;  	ad.u.ibendport = &ibendport; -	return avc_has_perm(sec->sid, sid, +	return avc_has_perm(&selinux_state, +			    sec->sid, sid,  			    SECCLASS_INFINIBAND_ENDPORT,  			    INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);  } @@ -6269,11 +6718,13 @@ static int selinux_bpf(int cmd, union bpf_attr *attr,  	switch (cmd) {  	case BPF_MAP_CREATE: -		ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, +		ret = avc_has_perm(&selinux_state, +				   sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,  				   NULL);  		break;  	case BPF_PROG_LOAD: -		ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, +		ret = avc_has_perm(&selinux_state, +				   sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,  				   NULL);  		break;  	default: @@ -6313,14 +6764,16 @@ static int bpf_fd_pass(struct file *file, u32 sid)  	if (file->f_op == &bpf_map_fops) {  		map = file->private_data;  		bpfsec = map->security; -		ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, +		ret = avc_has_perm(&selinux_state, +				   sid, bpfsec->sid, SECCLASS_BPF,  				   bpf_map_fmode_to_av(file->f_mode), NULL);  		if (ret)  			return ret;  	} else if (file->f_op == &bpf_prog_fops) {  		prog = file->private_data;  		bpfsec = prog->aux->security; -		ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, +		ret = avc_has_perm(&selinux_state, +				   sid, bpfsec->sid, SECCLASS_BPF,  				   BPF__PROG_RUN, NULL);  		if (ret)  			return ret; @@ -6334,7 +6787,8 @@ static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)  	struct bpf_security_struct *bpfsec;  	bpfsec = map->security; -	return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, +	return avc_has_perm(&selinux_state, +			    sid, bpfsec->sid, SECCLASS_BPF,  			    bpf_map_fmode_to_av(fmode), NULL);  } @@ -6344,7 +6798,8 @@ static int selinux_bpf_prog(struct bpf_prog *prog)  	struct bpf_security_struct *bpfsec;  	bpfsec = prog->aux->security; -	return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, +	return avc_has_perm(&selinux_state, +			    sid, bpfsec->sid, SECCLASS_BPF,  			    BPF__PROG_RUN, NULL);  } @@ -6479,6 +6934,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {  	LSM_HOOK_INIT(cred_free, selinux_cred_free),  	LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),  	LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer), +	LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),  	LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),  	LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),  	LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), @@ -6563,6 +7019,9 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {  	LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),  	LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),  	LSM_HOOK_INIT(sock_graft, selinux_sock_graft), +	LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request), +	LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone), +	LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),  	LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),  	LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),  	LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established), @@ -6638,6 +7097,12 @@ static __init int selinux_init(void)  	printk(KERN_INFO "SELinux:  Initializing.\n"); +	memset(&selinux_state, 0, sizeof(selinux_state)); +	enforcing_set(&selinux_state, selinux_enforcing_boot); +	selinux_state.checkreqprot = selinux_checkreqprot_boot; +	selinux_ss_init(&selinux_state.ss); +	selinux_avc_init(&selinux_state.avc); +  	/* Set the security state for the initial task. */  	cred_init_security(); @@ -6651,6 +7116,12 @@ static __init int selinux_init(void)  					    0, SLAB_PANIC, NULL);  	avc_init(); +	avtab_cache_init(); + +	ebitmap_cache_init(); + +	hashtab_cache_init(); +  	security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");  	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) @@ -6659,7 +7130,7 @@ static __init int selinux_init(void)  	if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))  		panic("SELinux: Unable to register AVC LSM notifier callback\n"); -	if (selinux_enforcing) +	if (selinux_enforcing_boot)  		printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");  	else  		printk(KERN_DEBUG "SELinux:  Starting in permissive mode\n"); @@ -6780,23 +7251,22 @@ static void selinux_nf_ip_exit(void)  #endif /* CONFIG_NETFILTER */  #ifdef CONFIG_SECURITY_SELINUX_DISABLE -static int selinux_disabled; - -int selinux_disable(void) +int selinux_disable(struct selinux_state *state)  { -	if (ss_initialized) { +	if (state->initialized) {  		/* Not permitted after initial policy load. */  		return -EINVAL;  	} -	if (selinux_disabled) { +	if (state->disabled) {  		/* Only do this once. */  		return -EINVAL;  	} +	state->disabled = 1; +  	printk(KERN_INFO "SELinux:  Disabled at runtime.\n"); -	selinux_disabled = 1;  	selinux_enabled = 0;  	security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks)); | 
