Merge branch 'master' into for-next
Fast-forwarded to current state of Linus' tree as there are patches to be applied for files that didn't exist on the old branch.
This commit is contained in:
		| @@ -471,6 +471,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||||
|  * @avd: access vector decisions | ||||
|  * @result: result from avc_has_perm_noaudit | ||||
|  * @a:  auxiliary audit data | ||||
|  * @flags: VFS walk flags | ||||
|  * | ||||
|  * Audit the granting or denial of permissions in accordance | ||||
|  * with the policy.  This function is typically called by | ||||
| @@ -481,9 +482,10 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||||
|  * be performed under a lock, to allow the lock to be released | ||||
|  * before calling the auditing code. | ||||
|  */ | ||||
| void avc_audit(u32 ssid, u32 tsid, | ||||
| int avc_audit(u32 ssid, u32 tsid, | ||||
| 	       u16 tclass, u32 requested, | ||||
| 	       struct av_decision *avd, int result, struct common_audit_data *a) | ||||
| 	       struct av_decision *avd, int result, struct common_audit_data *a, | ||||
| 	       unsigned flags) | ||||
| { | ||||
| 	struct common_audit_data stack_data; | ||||
| 	u32 denied, audited; | ||||
| @@ -515,11 +517,24 @@ void avc_audit(u32 ssid, u32 tsid, | ||||
| 	else | ||||
| 		audited = requested & avd->auditallow; | ||||
| 	if (!audited) | ||||
| 		return; | ||||
| 		return 0; | ||||
|  | ||||
| 	if (!a) { | ||||
| 		a = &stack_data; | ||||
| 		COMMON_AUDIT_DATA_INIT(a, NONE); | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * When in a RCU walk do the audit on the RCU retry.  This is because | ||||
| 	 * the collection of the dname in an inode audit message is not RCU | ||||
| 	 * safe.  Note this may drop some audits when the situation changes | ||||
| 	 * during retry. However this is logically just as if the operation | ||||
| 	 * happened a little later. | ||||
| 	 */ | ||||
| 	if ((a->type == LSM_AUDIT_DATA_FS) && | ||||
| 	    (flags & IPERM_FLAG_RCU)) | ||||
| 		return -ECHILD; | ||||
|  | ||||
| 	a->selinux_audit_data.tclass = tclass; | ||||
| 	a->selinux_audit_data.requested = requested; | ||||
| 	a->selinux_audit_data.ssid = ssid; | ||||
| @@ -529,6 +544,7 @@ void avc_audit(u32 ssid, u32 tsid, | ||||
| 	a->lsm_pre_audit = avc_audit_pre_callback; | ||||
| 	a->lsm_post_audit = avc_audit_post_callback; | ||||
| 	common_lsm_audit(a); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -793,6 +809,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | ||||
|  * @tclass: target security class | ||||
|  * @requested: requested permissions, interpreted based on @tclass | ||||
|  * @auditdata: auxiliary audit data | ||||
|  * @flags: VFS walk flags | ||||
|  * | ||||
|  * Check the AVC to determine whether the @requested permissions are granted | ||||
|  * for the SID pair (@ssid, @tsid), interpreting the permissions | ||||
| @@ -802,14 +819,19 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | ||||
|  * permissions are granted, -%EACCES if any permissions are denied, or | ||||
|  * another -errno upon other errors. | ||||
|  */ | ||||
| int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, | ||||
| 		 u32 requested, struct common_audit_data *auditdata) | ||||
| int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass, | ||||
| 		       u32 requested, struct common_audit_data *auditdata, | ||||
| 		       unsigned flags) | ||||
| { | ||||
| 	struct av_decision avd; | ||||
| 	int rc; | ||||
| 	int rc, rc2; | ||||
|  | ||||
| 	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); | ||||
| 	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); | ||||
|  | ||||
| 	rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata, | ||||
| 			flags); | ||||
| 	if (rc2) | ||||
| 		return rc2; | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -79,6 +79,7 @@ | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/posix-timers.h> | ||||
| #include <linux/syslog.h> | ||||
| #include <linux/user_namespace.h> | ||||
|  | ||||
| #include "avc.h" | ||||
| #include "objsec.h" | ||||
| @@ -1445,8 +1446,11 @@ static int task_has_capability(struct task_struct *tsk, | ||||
| 	} | ||||
|  | ||||
| 	rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); | ||||
| 	if (audit == SECURITY_CAP_AUDIT) | ||||
| 		avc_audit(sid, sid, sclass, av, &avd, rc, &ad); | ||||
| 	if (audit == SECURITY_CAP_AUDIT) { | ||||
| 		int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); | ||||
| 		if (rc2) | ||||
| 			return rc2; | ||||
| 	} | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| @@ -1466,7 +1470,8 @@ static int task_has_system(struct task_struct *tsk, | ||||
| static int inode_has_perm(const struct cred *cred, | ||||
| 			  struct inode *inode, | ||||
| 			  u32 perms, | ||||
| 			  struct common_audit_data *adp) | ||||
| 			  struct common_audit_data *adp, | ||||
| 			  unsigned flags) | ||||
| { | ||||
| 	struct inode_security_struct *isec; | ||||
| 	struct common_audit_data ad; | ||||
| @@ -1486,7 +1491,7 @@ static int inode_has_perm(const struct cred *cred, | ||||
| 		ad.u.fs.inode = inode; | ||||
| 	} | ||||
|  | ||||
| 	return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); | ||||
| 	return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); | ||||
| } | ||||
|  | ||||
| /* Same as inode_has_perm, but pass explicit audit data containing | ||||
| @@ -1503,7 +1508,7 @@ static inline int dentry_has_perm(const struct cred *cred, | ||||
| 	COMMON_AUDIT_DATA_INIT(&ad, FS); | ||||
| 	ad.u.fs.path.mnt = mnt; | ||||
| 	ad.u.fs.path.dentry = dentry; | ||||
| 	return inode_has_perm(cred, inode, av, &ad); | ||||
| 	return inode_has_perm(cred, inode, av, &ad, 0); | ||||
| } | ||||
|  | ||||
| /* Check whether a task can use an open file descriptor to | ||||
| @@ -1539,7 +1544,7 @@ static int file_has_perm(const struct cred *cred, | ||||
| 	/* av is zero if only checking access to the descriptor. */ | ||||
| 	rc = 0; | ||||
| 	if (av) | ||||
| 		rc = inode_has_perm(cred, inode, av, &ad); | ||||
| 		rc = inode_has_perm(cred, inode, av, &ad, 0); | ||||
|  | ||||
| out: | ||||
| 	return rc; | ||||
| @@ -1846,11 +1851,11 @@ static int selinux_capset(struct cred *new, const struct cred *old, | ||||
|  */ | ||||
|  | ||||
| static int selinux_capable(struct task_struct *tsk, const struct cred *cred, | ||||
| 			   int cap, int audit) | ||||
| 			   struct user_namespace *ns, int cap, int audit) | ||||
| { | ||||
| 	int rc; | ||||
|  | ||||
| 	rc = cap_capable(tsk, cred, cap, audit); | ||||
| 	rc = cap_capable(tsk, cred, ns, cap, audit); | ||||
| 	if (rc) | ||||
| 		return rc; | ||||
|  | ||||
| @@ -1931,7 +1936,8 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | ||||
| { | ||||
| 	int rc, cap_sys_admin = 0; | ||||
|  | ||||
| 	rc = selinux_capable(current, current_cred(), CAP_SYS_ADMIN, | ||||
| 	rc = selinux_capable(current, current_cred(), | ||||
| 			     &init_user_ns, CAP_SYS_ADMIN, | ||||
| 			     SECURITY_CAP_NOAUDIT); | ||||
| 	if (rc == 0) | ||||
| 		cap_sys_admin = 1; | ||||
| @@ -2101,7 +2107,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | ||||
| 			file = file_priv->file; | ||||
| 			inode = file->f_path.dentry->d_inode; | ||||
| 			if (inode_has_perm(cred, inode, | ||||
| 					   FILE__READ | FILE__WRITE, NULL)) { | ||||
| 					   FILE__READ | FILE__WRITE, NULL, 0)) { | ||||
| 				drop_tty = 1; | ||||
| 			} | ||||
| 		} | ||||
| @@ -2633,7 +2639,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | ||||
| 	return dentry_has_perm(cred, NULL, dentry, FILE__READ); | ||||
| } | ||||
|  | ||||
| static int selinux_inode_permission(struct inode *inode, int mask) | ||||
| static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags) | ||||
| { | ||||
| 	const struct cred *cred = current_cred(); | ||||
| 	struct common_audit_data ad; | ||||
| @@ -2655,7 +2661,7 @@ static int selinux_inode_permission(struct inode *inode, int mask) | ||||
|  | ||||
| 	perms = file_mask_to_av(inode->i_mode, mask); | ||||
|  | ||||
| 	return inode_has_perm(cred, inode, perms, &ad); | ||||
| 	return inode_has_perm(cred, inode, perms, &ad, flags); | ||||
| } | ||||
|  | ||||
| static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | ||||
| @@ -2723,7 +2729,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | ||||
| 	if (!(sbsec->flags & SE_SBLABELSUPP)) | ||||
| 		return -EOPNOTSUPP; | ||||
|  | ||||
| 	if (!is_owner_or_cap(inode)) | ||||
| 	if (!inode_owner_or_capable(inode)) | ||||
| 		return -EPERM; | ||||
|  | ||||
| 	COMMON_AUDIT_DATA_INIT(&ad, FS); | ||||
| @@ -2834,7 +2840,8 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name | ||||
| 	 * and lack of permission just means that we fall back to the | ||||
| 	 * in-core context value, not a denial. | ||||
| 	 */ | ||||
| 	error = selinux_capable(current, current_cred(), CAP_MAC_ADMIN, | ||||
| 	error = selinux_capable(current, current_cred(), | ||||
| 				&init_user_ns, CAP_MAC_ADMIN, | ||||
| 				SECURITY_CAP_NOAUDIT); | ||||
| 	if (!error) | ||||
| 		error = security_sid_to_context_force(isec->sid, &context, | ||||
| @@ -2968,7 +2975,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | ||||
| 	case KDSKBENT: | ||||
| 	case KDSKBSENT: | ||||
| 		error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG, | ||||
| 					    SECURITY_CAP_AUDIT); | ||||
| 					SECURITY_CAP_AUDIT); | ||||
| 		break; | ||||
|  | ||||
| 	/* default case assumes that the command will go | ||||
| @@ -3202,7 +3209,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(cred, inode, open_file_to_av(file), NULL); | ||||
| 	return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); | ||||
| } | ||||
|  | ||||
| /* task security operations */ | ||||
|   | ||||
| @@ -54,11 +54,11 @@ struct avc_cache_stats { | ||||
|  | ||||
| void __init avc_init(void); | ||||
|  | ||||
| void avc_audit(u32 ssid, u32 tsid, | ||||
| int avc_audit(u32 ssid, u32 tsid, | ||||
| 	       u16 tclass, u32 requested, | ||||
| 	       struct av_decision *avd, | ||||
| 	       int result, | ||||
| 	       struct common_audit_data *a); | ||||
| 	      struct common_audit_data *a, unsigned flags); | ||||
|  | ||||
| #define AVC_STRICT 1 /* Ignore permissive mode. */ | ||||
| int avc_has_perm_noaudit(u32 ssid, u32 tsid, | ||||
| @@ -66,9 +66,17 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | ||||
| 			 unsigned flags, | ||||
| 			 struct av_decision *avd); | ||||
|  | ||||
| int avc_has_perm(u32 ssid, u32 tsid, | ||||
| 		 u16 tclass, u32 requested, | ||||
| 		 struct common_audit_data *auditdata); | ||||
| int avc_has_perm_flags(u32 ssid, u32 tsid, | ||||
| 		       u16 tclass, u32 requested, | ||||
| 		       struct common_audit_data *auditdata, | ||||
| 		       unsigned); | ||||
|  | ||||
| static inline int avc_has_perm(u32 ssid, u32 tsid, | ||||
| 			       u16 tclass, u32 requested, | ||||
| 			       struct common_audit_data *auditdata) | ||||
| { | ||||
| 	return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0); | ||||
| } | ||||
|  | ||||
| u32 avc_policy_seqno(void); | ||||
|  | ||||
|   | ||||
| @@ -151,7 +151,7 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) | ||||
|  * | ||||
|  * Description: | ||||
|  * Called when the NetLabel state of a sk_security_struct needs to be reset. | ||||
|  * The caller is responsibile for all the NetLabel sk_security_struct locking. | ||||
|  * The caller is responsible for all the NetLabel sk_security_struct locking. | ||||
|  * | ||||
|  */ | ||||
| void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) | ||||
|   | ||||
| @@ -213,7 +213,7 @@ static u16 map_class(u16 pol_value) | ||||
| 			return i; | ||||
| 	} | ||||
|  | ||||
| 	return pol_value; | ||||
| 	return SECCLASS_NULL; | ||||
| } | ||||
|  | ||||
| static void map_decision(u16 tclass, struct av_decision *avd, | ||||
| @@ -2806,7 +2806,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | ||||
| 	case AUDIT_SUBJ_CLR: | ||||
| 	case AUDIT_OBJ_LEV_LOW: | ||||
| 	case AUDIT_OBJ_LEV_HIGH: | ||||
| 		/* we do not allow a range, indicated by the presense of '-' */ | ||||
| 		/* we do not allow a range, indicated by the presence of '-' */ | ||||
| 		if (strchr(rulestr, '-')) | ||||
| 			return -EINVAL; | ||||
| 		break; | ||||
| @@ -3075,7 +3075,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, | ||||
|  * Description: | ||||
|  * Convert the given NetLabel security attributes in @secattr into a | ||||
|  * SELinux SID.  If the @secattr field does not contain a full SELinux | ||||
|  * SID/context then use SECINITSID_NETMSG as the foundation.  If possibile the | ||||
|  * SID/context then use SECINITSID_NETMSG as the foundation.  If possible the | ||||
|  * 'cache' field of @secattr is set and the CACHE flag is set; this is to | ||||
|  * allow the @secattr to be used by NetLabel to cache the secattr to SID | ||||
|  * conversion for future lookups.  Returns zero on success, negative values on | ||||
|   | ||||
		Reference in New Issue
	
	Block a user