diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 268 | 
1 files changed, 127 insertions, 141 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d85b793c9321..fa2341b68331 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred,  			       int cap, int audit)  {  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct av_decision avd;  	u16 sclass;  	u32 sid = cred_sid(cred);  	u32 av = CAP_TO_MASK(cap);  	int rc; -	COMMON_AUDIT_DATA_INIT(&ad, CAP); -	ad.selinux_audit_data = &sad; -	ad.tsk = current; +	ad.type = LSM_AUDIT_DATA_CAP;  	ad.u.cap = cap;  	switch (CAP_TO_INDEX(cap)) { @@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred,  	return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);  } -static int inode_has_perm_noadp(const struct cred *cred, -				struct inode *inode, -				u32 perms, -				unsigned flags) -{ -	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,}; - -	COMMON_AUDIT_DATA_INIT(&ad, INODE); -	ad.u.inode = inode; -	ad.selinux_audit_data = &sad; -	return inode_has_perm(cred, inode, perms, &ad, flags); -} -  /* Same as inode_has_perm, but pass explicit audit data containing     the dentry to help the auditing code to more easily generate the     pathname if needed. */ @@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred,  {  	struct inode *inode = dentry->d_inode;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,}; -	COMMON_AUDIT_DATA_INIT(&ad, DENTRY); +	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = dentry; -	ad.selinux_audit_data = &sad;  	return inode_has_perm(cred, inode, av, &ad, 0);  } @@ -1528,11 +1509,9 @@ static inline int path_has_perm(const struct cred *cred,  {  	struct inode *inode = path->dentry->d_inode;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,}; -	COMMON_AUDIT_DATA_INIT(&ad, PATH); +	ad.type = LSM_AUDIT_DATA_PATH;  	ad.u.path = *path; -	ad.selinux_audit_data = &sad;  	return inode_has_perm(cred, inode, av, &ad, 0);  } @@ -1551,13 +1530,11 @@ static int file_has_perm(const struct cred *cred,  	struct file_security_struct *fsec = file->f_security;  	struct inode *inode = file->f_path.dentry->d_inode;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = cred_sid(cred);  	int rc; -	COMMON_AUDIT_DATA_INIT(&ad, PATH); +	ad.type = LSM_AUDIT_DATA_PATH;  	ad.u.path = file->f_path; -	ad.selinux_audit_data = &sad;  	if (sid != fsec->sid) {  		rc = avc_has_perm(sid, fsec->sid, @@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir,  	struct superblock_security_struct *sbsec;  	u32 sid, newsid;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	int rc;  	dsec = dir->i_security; @@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir,  	sid = tsec->sid;  	newsid = tsec->create_sid; -	COMMON_AUDIT_DATA_INIT(&ad, DENTRY); +	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = dentry; -	ad.selinux_audit_data = &sad;  	rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,  			  DIR__ADD_NAME | DIR__SEARCH, @@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir,  {  	struct inode_security_struct *dsec, *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	u32 av;  	int rc; @@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir,  	dsec = dir->i_security;  	isec = dentry->d_inode->i_security; -	COMMON_AUDIT_DATA_INIT(&ad, DENTRY); +	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = dentry; -	ad.selinux_audit_data = &sad;  	av = DIR__SEARCH;  	av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); @@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir,  {  	struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	u32 av;  	int old_is_dir, new_is_dir; @@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir,  	old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);  	new_dsec = new_dir->i_security; -	COMMON_AUDIT_DATA_INIT(&ad, DENTRY); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = old_dentry;  	rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, @@ -1986,7 +1957,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  	struct task_security_struct *new_tsec;  	struct inode_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct inode *inode = bprm->file->f_path.dentry->d_inode;  	int rc; @@ -2016,6 +1986,13 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  		new_tsec->sid = old_tsec->exec_sid;  		/* Reset exec SID on execve. */  		new_tsec->exec_sid = 0; + +		/* +		 * Minimize confusion: if no_new_privs and a transition is +		 * explicitly requested, then fail the exec. +		 */ +		if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) +			return -EPERM;  	} else {  		/* Check for a default transition on this program. */  		rc = security_transition_sid(old_tsec->sid, isec->sid, @@ -2025,11 +2002,11 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  			return rc;  	} -	COMMON_AUDIT_DATA_INIT(&ad, PATH); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_PATH;  	ad.u.path = bprm->file->f_path; -	if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) +	if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || +	    (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))  		new_tsec->sid = old_tsec->sid;  	if (new_tsec->sid == old_tsec->sid) { @@ -2115,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)  static inline void flush_unauthorized_files(const struct cred *cred,  					    struct files_struct *files)  { -	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct file *file, *devnull = NULL;  	struct tty_struct *tty;  	struct fdtable *fdt; @@ -2128,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred,  		spin_lock(&tty_files_lock);  		if (!list_empty(&tty->tty_files)) {  			struct tty_file_private *file_priv; -			struct inode *inode;  			/* Revalidate access to controlling tty. -			   Use inode_has_perm on the tty inode directly rather +			   Use path_has_perm on the tty path directly rather  			   than using file_has_perm, as this particular open  			   file may belong to another process and we are only  			   interested in the inode-based check here. */  			file_priv = list_first_entry(&tty->tty_files,  						struct tty_file_private, list);  			file = file_priv->file; -			inode = file->f_path.dentry->d_inode; -			if (inode_has_perm_noadp(cred, inode, -					   FILE__READ | FILE__WRITE, 0)) { +			if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))  				drop_tty = 1; -			}  		}  		spin_unlock(&tty_files_lock);  		tty_kref_put(tty); @@ -2152,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred,  		no_tty();  	/* Revalidate access to inherited open files. */ - -	COMMON_AUDIT_DATA_INIT(&ad, INODE); -	ad.selinux_audit_data = &sad; -  	spin_lock(&files->file_lock);  	for (;;) {  		unsigned long set, i; @@ -2492,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)  {  	const struct cred *cred = current_cred();  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	int rc;  	rc = superblock_doinit(sb, data); @@ -2503,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)  	if (flags & MS_KERNMOUNT)  		return 0; -	COMMON_AUDIT_DATA_INIT(&ad, DENTRY); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = sb->s_root;  	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);  } @@ -2513,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry)  {  	const struct cred *cred = current_cred();  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,}; -	COMMON_AUDIT_DATA_INIT(&ad, DENTRY); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = dentry->d_sb->s_root;  	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);  } @@ -2676,14 +2639,35 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na  	return dentry_has_perm(cred, dentry, FILE__READ);  } +static noinline int audit_inode_permission(struct inode *inode, +					   u32 perms, u32 audited, u32 denied, +					   unsigned flags) +{ +	struct common_audit_data ad; +	struct inode_security_struct *isec = inode->i_security; +	int rc; + +	ad.type = LSM_AUDIT_DATA_INODE; +	ad.u.inode = inode; + +	rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms, +			    audited, denied, &ad, flags); +	if (rc) +		return rc; +	return 0; +} +  static int selinux_inode_permission(struct inode *inode, int mask)  {  	const struct cred *cred = current_cred(); -	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 perms;  	bool from_access;  	unsigned flags = mask & MAY_NOT_BLOCK; +	struct inode_security_struct *isec; +	u32 sid; +	struct av_decision avd; +	int rc, rc2; +	u32 audited, denied;  	from_access = mask & MAY_ACCESS;  	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); @@ -2692,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask)  	if (!mask)  		return 0; -	COMMON_AUDIT_DATA_INIT(&ad, INODE); -	ad.selinux_audit_data = &sad; -	ad.u.inode = inode; +	validate_creds(cred); -	if (from_access) -		ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; +	if (unlikely(IS_PRIVATE(inode))) +		return 0;  	perms = file_mask_to_av(inode->i_mode, mask); -	return inode_has_perm(cred, inode, perms, &ad, flags); +	sid = cred_sid(cred); +	isec = inode->i_security; + +	rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); +	audited = avc_audit_required(perms, &avd, rc, +				     from_access ? FILE__AUDIT_ACCESS : 0, +				     &denied); +	if (likely(!audited)) +		return rc; + +	rc2 = audit_inode_permission(inode, perms, audited, denied, flags); +	if (rc2) +		return rc2; +	return rc;  }  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)  {  	const struct cred *cred = current_cred();  	unsigned int ia_valid = iattr->ia_valid; +	__u32 av = FILE__WRITE;  	/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */  	if (ia_valid & ATTR_FORCE) { @@ -2721,7 +2717,10 @@ 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); -	return dentry_has_perm(cred, dentry, FILE__WRITE); +	if (ia_valid & ATTR_SIZE) +		av |= FILE__OPEN; + +	return dentry_has_perm(cred, dentry, av);  }  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) @@ -2763,7 +2762,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,  	struct inode_security_struct *isec = inode->i_security;  	struct superblock_security_struct *sbsec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 newsid, sid = current_sid();  	int rc = 0; @@ -2777,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,  	if (!inode_owner_or_capable(inode))  		return -EPERM; -	COMMON_AUDIT_DATA_INIT(&ad, DENTRY); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_DENTRY;  	ad.u.dentry = dentry;  	rc = avc_has_perm(sid, isec->sid, isec->sclass, @@ -2788,8 +2785,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,  	rc = security_context_to_sid(value, size, &newsid);  	if (rc == -EINVAL) { -		if (!capable(CAP_MAC_ADMIN)) +		if (!capable(CAP_MAC_ADMIN)) { +			struct audit_buffer *ab; +			size_t audit_size; +			const char *str; + +			/* We strip a nul only if it is at the end, otherwise the +			 * context contains a nul and we should audit that */ +			str = value; +			if (str[size - 1] == '\0') +				audit_size = size - 1; +			else +				audit_size = size; +			ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); +			audit_log_format(ab, "op=setxattr invalid_context="); +			audit_log_n_untrustedstring(ab, value, audit_size); +			audit_log_end(ab); +  			return rc; +		}  		rc = security_context_to_sid_force(value, size, &newsid);  	}  	if (rc) @@ -2969,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask)  	if (sid == fsec->sid && fsec->isid == isec->sid &&  	    fsec->pseqno == avc_policy_seqno()) -		/* No change since dentry_open check. */ +		/* No change since file_open check. */  		return 0;  	return selinux_revalidate_file_permission(file, mask); @@ -3228,15 +3242,13 @@ static int selinux_file_receive(struct file *file)  	return file_has_perm(cred, file, file_to_av(file));  } -static int selinux_dentry_open(struct file *file, const struct cred *cred) +static int selinux_file_open(struct file *file, const struct cred *cred)  {  	struct file_security_struct *fsec; -	struct inode *inode;  	struct inode_security_struct *isec; -	inode = file->f_path.dentry->d_inode;  	fsec = file->f_security; -	isec = inode->i_security; +	isec = file->f_path.dentry->d_inode->i_security;  	/*  	 * Save inode label and policy sequence number  	 * at open-time so that selinux_file_permission @@ -3254,7 +3266,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)  	 * new inode label or new policy.  	 * This check is not redundant - do not remove.  	 */ -	return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); +	return path_has_perm(cred, &file->f_path, open_file_to_av(file));  }  /* task security operations */ @@ -3373,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name)  {  	u32 sid;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	sid = task_sid(current); -	COMMON_AUDIT_DATA_INIT(&ad, KMOD); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_KMOD;  	ad.u.kmod_name = kmod_name;  	return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, @@ -3751,15 +3761,13 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)  {  	struct sk_security_struct *sksec = sk->sk_security;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,};  	u32 tsid = task_sid(task);  	if (sksec->sid == SECINITSID_KERNEL)  		return 0; -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->sk = sk; @@ -3839,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  		char *addrp;  		struct sk_security_struct *sksec = sk->sk_security;  		struct common_audit_data ad; -		struct selinux_audit_data sad = {0,};  		struct lsm_network_audit net = {0,};  		struct sockaddr_in *addr4 = NULL;  		struct sockaddr_in6 *addr6 = NULL; @@ -3866,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  						      snum, &sid);  				if (err)  					goto out; -				COMMON_AUDIT_DATA_INIT(&ad, NET); -				ad.selinux_audit_data = &sad; +				ad.type = LSM_AUDIT_DATA_NET;  				ad.u.net = &net;  				ad.u.net->sport = htons(snum);  				ad.u.net->family = family; @@ -3901,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in  		if (err)  			goto out; -		COMMON_AUDIT_DATA_INIT(&ad, NET); -		ad.selinux_audit_data = &sad; +		ad.type = LSM_AUDIT_DATA_NET;  		ad.u.net = &net;  		ad.u.net->sport = htons(snum);  		ad.u.net->family = family; @@ -3937,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,  	if (sksec->sclass == SECCLASS_TCP_SOCKET ||  	    sksec->sclass == SECCLASS_DCCP_SOCKET) {  		struct common_audit_data ad; -		struct selinux_audit_data sad = {0,};  		struct lsm_network_audit net = {0,};  		struct sockaddr_in *addr4 = NULL;  		struct sockaddr_in6 *addr6 = NULL; @@ -3963,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,  		perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?  		       TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; -		COMMON_AUDIT_DATA_INIT(&ad, NET); -		ad.selinux_audit_data = &sad; +		ad.type = LSM_AUDIT_DATA_NET;  		ad.u.net = &net;  		ad.u.net->dport = htons(snum);  		ad.u.net->family = sk->sk_family; @@ -4056,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,  	struct sk_security_struct *sksec_other = other->sk_security;  	struct sk_security_struct *sksec_new = newsk->sk_security;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,};  	int err; -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->sk = other; @@ -4090,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,  	struct sk_security_struct *ssec = sock->sk->sk_security;  	struct sk_security_struct *osec = other->sk->sk_security;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,}; -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->sk = other->sk; @@ -4132,12 +4131,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,  	struct sk_security_struct *sksec = sk->sk_security;  	u32 sk_sid = sksec->sid;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,};  	char *addrp; -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->netif = skb->skb_iif;  	ad.u.net->family = family; @@ -4167,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)  	u16 family = sk->sk_family;  	u32 sk_sid = sksec->sid;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,};  	char *addrp;  	u8 secmark_active; @@ -4192,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)  	if (!secmark_active && !peerlbl_active)  		return 0; -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->netif = skb->skb_iif;  	ad.u.net->family = family; @@ -4531,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,  	char *addrp;  	u32 peer_sid;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,};  	u8 secmark_active;  	u8 netlbl_active; @@ -4549,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,  	if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)  		return NF_DROP; -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->netif = ifindex;  	ad.u.net->family = family; @@ -4640,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,  	struct sock *sk = skb->sk;  	struct sk_security_struct *sksec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,};  	char *addrp;  	u8 proto; @@ -4649,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,  		return NF_ACCEPT;  	sksec = sk->sk_security; -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->netif = ifindex;  	ad.u.net->family = family; @@ -4675,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,  	u32 peer_sid;  	struct sock *sk;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	struct lsm_network_audit net = {0,};  	char *addrp;  	u8 secmark_active; @@ -4722,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,  		secmark_perm = PACKET__SEND;  	} -	COMMON_AUDIT_DATA_INIT(&ad, NET); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_NET;  	ad.u.net = &net;  	ad.u.net->netif = ifindex;  	ad.u.net->family = family; @@ -4841,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	isec = ipc_perms->security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = ipc_perms->key;  	return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); @@ -4868,7 +4855,6 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	int rc; @@ -4878,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)  	isec = msq->q_perm.security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = msq->q_perm.key;  	rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, @@ -4900,13 +4885,11 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	isec = msq->q_perm.security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = msq->q_perm.key;  	return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, @@ -4946,7 +4929,6 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,  	struct ipc_security_struct *isec;  	struct msg_security_struct *msec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	int rc; @@ -4967,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,  			return rc;  	} -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = msq->q_perm.key;  	/* Can this process write to the queue? */ @@ -4993,15 +4974,13 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,  	struct ipc_security_struct *isec;  	struct msg_security_struct *msec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = task_sid(target);  	int rc;  	isec = msq->q_perm.security;  	msec = msg->security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = msq->q_perm.key;  	rc = avc_has_perm(sid, isec->sid, @@ -5017,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	int rc; @@ -5027,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)  	isec = shp->shm_perm.security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = shp->shm_perm.key;  	rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, @@ -5049,13 +5026,11 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	isec = shp->shm_perm.security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = shp->shm_perm.key;  	return avc_has_perm(sid, isec->sid, SECCLASS_SHM, @@ -5113,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	int rc; @@ -5123,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)  	isec = sma->sem_perm.security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = sma->sem_perm.key;  	rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, @@ -5145,13 +5118,11 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)  {  	struct ipc_security_struct *isec;  	struct common_audit_data ad; -	struct selinux_audit_data sad = {0,};  	u32 sid = current_sid();  	isec = sma->sem_perm.security; -	COMMON_AUDIT_DATA_INIT(&ad, IPC); -	ad.selinux_audit_data = &sad; +	ad.type = LSM_AUDIT_DATA_IPC;  	ad.u.ipc_id = sma->sem_perm.key;  	return avc_has_perm(sid, isec->sid, SECCLASS_SEM, @@ -5331,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p,  		}  		error = security_context_to_sid(value, size, &sid);  		if (error == -EINVAL && !strcmp(name, "fscreate")) { -			if (!capable(CAP_MAC_ADMIN)) +			if (!capable(CAP_MAC_ADMIN)) { +				struct audit_buffer *ab; +				size_t audit_size; + +				/* We strip a nul only if it is at the end, otherwise the +				 * context contains a nul and we should audit that */ +				if (str[size - 1] == '\0') +					audit_size = size - 1; +				else +					audit_size = size; +				ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); +				audit_log_format(ab, "op=fscreate invalid_context="); +				audit_log_n_untrustedstring(ab, value, audit_size); +				audit_log_end(ab); +  				return error; +			}  			error = security_context_to_sid_force(value, size,  							      &sid);  		} @@ -5592,7 +5578,7 @@ static struct security_operations selinux_ops = {  	.file_send_sigiotask =		selinux_file_send_sigiotask,  	.file_receive =			selinux_file_receive, -	.dentry_open =			selinux_dentry_open, +	.file_open =			selinux_file_open,  	.task_create =			selinux_task_create,  	.cred_alloc_blank =		selinux_cred_alloc_blank,  | 
