Commit 4958db32 authored by Roberto Sassu's avatar Roberto Sassu Committed by Mimi Zohar
Browse files

ima: Introduce MMAP_CHECK_REQPROT hook



Commit 98de59bf ("take calculation of final prot in
security_mmap_file() into a helper") caused ima_file_mmap() to receive the
protections requested by the application and not those applied by the
kernel.

After restoring the original MMAP_CHECK behavior, existing attestation
servers might be broken due to not being ready to handle new entries
(previously missing) in the IMA measurement list.

Restore the original correct MMAP_CHECK behavior, instead of keeping the
current buggy one and introducing a new hook with the correct behavior.
Otherwise, there would have been the risk of IMA users not noticing the
problem at all, as they would actively have to update the IMA policy, to
switch to the correct behavior.

Also, introduce the new MMAP_CHECK_REQPROT hook to keep the current
behavior, so that IMA users could easily fix a broken attestation server,
although this approach is discouraged due to potentially missing
measurements.

Signed-off-by: default avatarRoberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: default avatarMimi Zohar <zohar@linux.ibm.com>
parent 4971c268
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ Description:
				[FIRMWARE_CHECK]
				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
				[KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA]
				[SETXATTR_CHECK]
				[SETXATTR_CHECK][MMAP_CHECK_REQPROT]
			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
			       [[^]MAY_EXEC]
			fsmagic:= hex value
+1 −0
Original line number Diff line number Diff line
@@ -190,6 +190,7 @@ static inline unsigned int ima_hash_key(u8 *digest)
	hook(NONE, none)				\
	hook(FILE_CHECK, file)				\
	hook(MMAP_CHECK, mmap)				\
	hook(MMAP_CHECK_REQPROT, mmap_reqprot)		\
	hook(BPRM_CHECK, bprm)				\
	hook(CREDS_CHECK, creds)			\
	hook(POST_SETATTR, post_setattr)		\
+2 −1
Original line number Diff line number Diff line
@@ -179,7 +179,8 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
 *		subj=, obj=, type=, func=, mask=, fsmagic=
 *	subj,obj, and type: are LSM specific.
 *	func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
 *	| KEXEC_CMDLINE | KEY_CHECK | CRITICAL_DATA
 *	| KEXEC_CMDLINE | KEY_CHECK | CRITICAL_DATA | SETXATTR_CHECK
 *	| MMAP_CHECK_REQPROT
 *	mask: contains the permission mask
 *	fsmagic: hex value
 *
+3 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
{
	switch (func) {
	case MMAP_CHECK:
	case MMAP_CHECK_REQPROT:
		return iint->ima_mmap_status;
	case BPRM_CHECK:
		return iint->ima_bprm_status;
@@ -131,6 +132,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint,
{
	switch (func) {
	case MMAP_CHECK:
	case MMAP_CHECK_REQPROT:
		iint->ima_mmap_status = status;
		break;
	case BPRM_CHECK:
@@ -155,6 +157,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint,
{
	switch (func) {
	case MMAP_CHECK:
	case MMAP_CHECK_REQPROT:
		iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED);
		break;
	case BPRM_CHECK:
+22 −5
Original line number Diff line number Diff line
@@ -89,7 +89,8 @@ static int mmap_violation_check(enum ima_hooks func, struct file *file,
	struct inode *inode;
	int rc = 0;

	if ((func == MMAP_CHECK) && mapping_writably_mapped(file->f_mapping)) {
	if ((func == MMAP_CHECK || func == MMAP_CHECK_REQPROT) &&
	    mapping_writably_mapped(file->f_mapping)) {
		rc = -ETXTBSY;
		inode = file_inode(file);

@@ -227,7 +228,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
	action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid,
				mask, func, &pcr, &template_desc, NULL,
				&allowed_algos);
	violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
	violation_check = ((func == FILE_CHECK || func == MMAP_CHECK ||
			    func == MMAP_CHECK_REQPROT) &&
			   (ima_policy_flag & IMA_MEASURE));
	if (!action && !violation_check)
		return 0;
@@ -411,12 +413,23 @@ int ima_file_mmap(struct file *file, unsigned long reqprot,
		  unsigned long prot, unsigned long flags)
{
	u32 secid;
	int ret;

	if (!file)
		return 0;

	if (file && (prot & PROT_EXEC)) {
	security_current_getsecid_subj(&secid);

	if (reqprot & PROT_EXEC) {
		ret = process_measurement(file, current_cred(), secid, NULL,
					  0, MAY_EXEC, MMAP_CHECK_REQPROT);
		if (ret)
			return ret;
	}

	if (prot & PROT_EXEC)
		return process_measurement(file, current_cred(), secid, NULL,
					   0, MAY_EXEC, MMAP_CHECK);
	}

	return 0;
}
@@ -457,6 +470,10 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
	action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
				current_cred(), secid, MAY_EXEC, MMAP_CHECK,
				&pcr, &template, NULL, NULL);
	action |= ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
				 current_cred(), secid, MAY_EXEC,
				 MMAP_CHECK_REQPROT, &pcr, &template, NULL,
				 NULL);

	/* Is the mmap'ed file in policy? */
	if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
Loading