Skip to contentSkip to conversation

Code improvements in integrity and IMA

PATCH In review Thiago Jung Bauermann 3 participants 13 messages Mar 14, 2018 – Mar 17, 2018

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover Code improvements in integrity and IMA

Hello,

These patches come from the "appended signatures support for IMA appraisal" series. They are code improvements and cleanups and I decided to submit them separately for a couple of reasons:

1. they stand on their own and could be included in v4.17;

2. this will simplify the original patch series a bit, by having it contain only the patches actually necessary to implement the feature.

These are the changes made to them since v5 of the modsig series:

- Patch "integrity: Remove unused macro IMA_ACTION_RULE_FLAGS"
- New patch.

- Patch "ima: Improvements in ima_appraise_measurement()"
- Moved is_ima_sig() to its own patch (not in this series).

Mimi Zohar (1):
ima: Improvements in ima_appraise_measurement()

Thiago Jung Bauermann (3):
integrity: Remove unused macro IMA_ACTION_RULE_FLAGS
ima: Simplify ima_eventsig_init()
integrity: Introduce struct evm_xattr

 security/integrity/evm/evm_crypto.c       |  4 ++--
 security/integrity/evm/evm_main.c         | 10 ++++----
 security/integrity/ima/ima_appraise.c     | 40 ++++++++++++++++++-------------
 security/integrity/ima/ima_template_lib.c | 11 +++------
 security/integrity/integrity.h            |  6 ++++-
 5 files changed, 39 insertions(+), 32 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#1 lore raw

PATCH 1/4 integrity: Remove unused macro IMA_ACTION_RULE_FLAGS

This macro isn't used anymore since commit 0d73a55208e9 ("ima: re-introduce own integrity cache lock"), so remove it.

---
 security/integrity/integrity.h | 1 -
 1 file changed, 1 deletion(-)
security/integrity/integrity.h +0 -1
index 8224880935e0..5e58e02ba8dc 100644
@@ -30,7 +30,6 @@
 
 /* iint cache flags */
 #define IMA_ACTION_FLAGS	0xff000000
-#define IMA_ACTION_RULE_FLAGS	0x06000000
 #define IMA_DIGSIG_REQUIRED	0x01000000
 #define IMA_PERMIT_DIRECTIO	0x02000000
 #define IMA_NEW_FILE		0x04000000

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer Acked-by on v1 1/4
#2 lore raw

Re: [PATCH 1/4] integrity: Remove unused macro IMA_ACTION_RULE_FLAGS

Quoted 4 lines · Thiago Jung Bauermann

This macro isn't used anymore since commit 0d73a55208e9 ("ima: re-introduce own integrity cache lock"), so remove it.

Quoted 9 lines
---
 security/integrity/integrity.h | 1 -
 1 file changed, 1 deletion(-)
security/integrity/integrity.h +0 -0
index 8224880935e0..5e58e02ba8dc 100644

security/integrity/integrity.h line 35

Quoted 7 lines
security/integrity/integrity.h +0 -1
@@ -30,7 +30,6 @@
 
 /* iint cache flags */
 #define IMA_ACTION_FLAGS	0xff000000
-#define IMA_ACTION_RULE_FLAGS	0x06000000
 #define IMA_DIGSIG_REQUIRED	0x01000000
 #define IMA_PERMIT_DIRECTIO	0x02000000
 #define IMA_NEW_FILE		0x04000000

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw

PATCH 2/4 ima: Simplify ima_eventsig_init()

In reply to Thiago Jung Bauermann

The "goto out" statement doesn't have any purpose since there's no cleanup to be done when returning early, so remove it. This also makes the rc variable unnecessary so remove it as well.

Also, the xattr_len and fmt variables are redundant so remove them as well.

---
 security/integrity/ima/ima_template_lib.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)
security/integrity/ima/ima_template_lib.c +3 -8
index 28af43f63572..5afaa53decc5 100644
@@ -378,16 +378,11 @@ int ima_eventname_ng_init(struct ima_event_data *event_data,
 int ima_eventsig_init(struct ima_event_data *event_data,
 		      struct ima_field_data *field_data)
 {
-	enum data_formats fmt = DATA_FMT_HEX;
 	struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
-	int xattr_len = event_data->xattr_len;
-	int rc = 0;
 
 	if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
-		goto out;
+		return 0;
 
-	rc = ima_write_template_field_data(xattr_value, xattr_len, fmt,
-					   field_data);
-out:
-	return rc;
+	return ima_write_template_field_data(xattr_value, event_data->xattr_len,
+					     DATA_FMT_HEX, field_data);
 }

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer Acked-by on v1 2/4
#4 lore raw

Re: [PATCH 2/4] ima: Simplify ima_eventsig_init()

Quoted 7 lines · Thiago Jung Bauermann

The "goto out" statement doesn't have any purpose since there's no cleanup to be done when returning early, so remove it. This also makes the rc variable unnecessary so remove it as well.

Also, the xattr_len and fmt variables are redundant so remove them as well.

Quoted 18 lines
---
 security/integrity/ima/ima_template_lib.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)
security/integrity/ima/ima_template_lib.c +0 -3
index 28af43f63572..5afaa53decc5 100644
@@ -378,16 +378,11 @@ int ima_eventname_ng_init(struct ima_event_data *event_data,
 int ima_eventsig_init(struct ima_event_data *event_data,
 		      struct ima_field_data *field_data)
 {
-	enum data_formats fmt = DATA_FMT_HEX;
 	struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
-	int xattr_len = event_data->xattr_len;
-	int rc = 0;
 
 	if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))

security/integrity/ima/ima_template_lib.c int ima_eventname_ng_init(struct ima_event_data *event_data, · line 388

Quoted 10 lines
security/integrity/ima/ima_template_lib.c +3 -5
-		goto out;
+		return 0;
 
-	rc = ima_write_template_field_data(xattr_value, xattr_len, fmt,
-					   field_data);
-out:
-	return rc;
+	return ima_write_template_field_data(xattr_value, event_data->xattr_len,
+					     DATA_FMT_HEX, field_data);
 }

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw

PATCH 3/4 ima: Improvements in ima_appraise_measurement()

In reply to Thiago Jung Bauermann

From: Mimi Zohar <[email protected]>

Replace nested ifs in the EVM xattr verification logic with a switch statement, making the code easier to understand.

Also, add comments to the if statements in the out section and constify the cause variable.

---
 security/integrity/ima/ima_appraise.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)
security/integrity/ima/ima_appraise.c +20 -13
index 0c5f94b7b9c3..dd10ecbdce45 100644
@@ -215,7 +215,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 			     int xattr_len, int opened)
 {
 	static const char op[] = "appraise_data";
-	char *cause = "unknown";
+	const char *cause = "unknown";
 	struct dentry *dentry = file_dentry(file);
 	struct inode *inode = d_backing_inode(dentry);
 	enum integrity_status status = INTEGRITY_UNKNOWN;
@@ -241,16 +241,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 	}
 
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) &&
-	    (status != INTEGRITY_PASS_IMMUTABLE) &&
-	    (status != INTEGRITY_UNKNOWN)) {
-		if ((status == INTEGRITY_NOLABEL)
-		    || (status == INTEGRITY_NOXATTRS))
-			cause = "missing-HMAC";
-		else if (status == INTEGRITY_FAIL)
-			cause = "invalid-HMAC";
+	switch (status) {
+	case INTEGRITY_PASS:
+	case INTEGRITY_PASS_IMMUTABLE:
+	case INTEGRITY_UNKNOWN:
+		break;
+	case INTEGRITY_NOXATTRS:	/* No EVM protected xattrs. */
+	case INTEGRITY_NOLABEL:		/* No security.evm xattr. */
+		cause = "missing-HMAC";
+		goto out;
+	case INTEGRITY_FAIL:		/* Invalid HMAC/signature. */
+		cause = "invalid-HMAC";
 		goto out;
 	}
+
 	switch (xattr_value->type) {
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
@@ -316,17 +320,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else if (status != INTEGRITY_PASS) {
+		/* Fix mode, but don't replace file signatures. */
 		if ((ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
 			if (!ima_fix_xattr(dentry, iint))
 				status = INTEGRITY_PASS;
-		} else if ((inode->i_size == 0) &&
-			   (iint->flags & IMA_NEW_FILE) &&
-			   (xattr_value &&
-			    xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+		}
+
+		/* Permit new files with file signatures, but without data. */
+		if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&
+		    xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG) {
 			status = INTEGRITY_PASS;
 		}
+
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else {

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer
#6 lore raw

Re: [PATCH 3/4] ima: Improvements in ima_appraise_measurement()

Quoted 33 lines · Thiago Jung Bauermann

From: Mimi Zohar <[email protected]>

Replace nested ifs in the EVM xattr verification logic with a switch statement, making the code easier to understand.

Also, add comments to the if statements in the out section and constify the cause variable.

---
 security/integrity/ima/ima_appraise.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)
security/integrity/ima/ima_appraise.c +1 -3
index 0c5f94b7b9c3..dd10ecbdce45 100644
@@ -215,7 +215,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 			     int xattr_len, int opened)
 {
 	static const char op[] = "appraise_data";
-	char *cause = "unknown";
+	const char *cause = "unknown";
 	struct dentry *dentry = file_dentry(file);
 	struct inode *inode = d_backing_inode(dentry);
 	enum integrity_status status = INTEGRITY_UNKNOWN;
@@ -241,16 +241,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 	}
 
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) &&
-	    (status != INTEGRITY_PASS_IMMUTABLE) &&

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 247

Quoted 10 lines
security/integrity/ima/ima_appraise.c +4 -6
-	    (status != INTEGRITY_UNKNOWN)) {
-		if ((status == INTEGRITY_NOLABEL)
-		    || (status == INTEGRITY_NOXATTRS))
-			cause = "missing-HMAC";
-		else if (status == INTEGRITY_FAIL)
-			cause = "invalid-HMAC";
+	switch (status) {
+	case INTEGRITY_PASS:
+	case INTEGRITY_PASS_IMMUTABLE:
+	case INTEGRITY_UNKNOWN:

Wouldn't it be more future-proof to replace this with a 'default', or to at least add a "default: BUG()" to catch new status values?

Quoted 21 lines
security/integrity/ima/ima_appraise.c +9 -0
+		break;
+	case INTEGRITY_NOXATTRS:	/* No EVM protected xattrs. */
+	case INTEGRITY_NOLABEL:		/* No security.evm xattr. */
+		cause = "missing-HMAC";
+		goto out;
+	case INTEGRITY_FAIL:		/* Invalid HMAC/signature. */
+		cause = "invalid-HMAC";
 		goto out;
 	}
+
 	switch (xattr_value->type) {
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
@@ -316,17 +320,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else if (status != INTEGRITY_PASS) {
+		/* Fix mode, but don't replace file signatures. */
 		if ((ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 332

Quoted 10 lines
security/integrity/ima/ima_appraise.c +4 -4
 			if (!ima_fix_xattr(dentry, iint))
 				status = INTEGRITY_PASS;
-		} else if ((inode->i_size == 0) &&
-			   (iint->flags & IMA_NEW_FILE) &&
-			   (xattr_value &&
-			    xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+		}
+
+		/* Permit new files with file signatures, but without data. */
+		if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&

This may be correct, but it's not identical to what you're replacing. Since in either case you're setting status to INTEGRITY_PASS the final result is the same, but with a few extra possible steps. Not sure whether that matters.

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 339

Quoted 7 lines
security/integrity/ima/ima_appraise.c +2 -0
+		    xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG) {
 			status = INTEGRITY_PASS;
 		}
+
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else {

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#7 lore raw

Re: [PATCH 3/4] ima: Improvements in ima_appraise_measurement()

Hello Serge,

Thanks for quickly reviewing these patches!

Quoted 5 lines · Serge E. Hallyn
Quoted 4 lines · Thiago Jung Bauermann

From: Mimi Zohar <[email protected]>

(quoted diff) +0 -0
@@ -241,16 +241,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 	}
 
Quoted 16 lines

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 247

Quoted 13 lines
security/integrity/ima/ima_appraise.c +4 -8
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) &&
-	    (status != INTEGRITY_PASS_IMMUTABLE) &&
-	    (status != INTEGRITY_UNKNOWN)) {
-		if ((status == INTEGRITY_NOLABEL)
-		    || (status == INTEGRITY_NOXATTRS))
-			cause = "missing-HMAC";
-		else if (status == INTEGRITY_FAIL)
-			cause = "invalid-HMAC";
+	switch (status) {
+	case INTEGRITY_PASS:
+	case INTEGRITY_PASS_IMMUTABLE:
+	case INTEGRITY_UNKNOWN:

Wouldn't it be more future-proof to replace this with a 'default', or to at least add a "default: BUG()" to catch new status values?

I agree. I like the "default: BUG()" option.

Quoted 28 lines
Quoted 28 lines
security/integrity/ima/ima_appraise.c +10 -4
+		break;
+	case INTEGRITY_NOXATTRS:	/* No EVM protected xattrs. */
+	case INTEGRITY_NOLABEL:		/* No security.evm xattr. */
+		cause = "missing-HMAC";
+		goto out;
+	case INTEGRITY_FAIL:		/* Invalid HMAC/signature. */
+		cause = "invalid-HMAC";
 		goto out;
 	}
+
 	switch (xattr_value->type) {
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
@@ -316,17 +320,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else if (status != INTEGRITY_PASS) {
+		/* Fix mode, but don't replace file signatures. */
 		if ((ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
 			if (!ima_fix_xattr(dentry, iint))
 				status = INTEGRITY_PASS;
-		} else if ((inode->i_size == 0) &&
-			   (iint->flags & IMA_NEW_FILE) &&
-			   (xattr_value &&
-			    xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+		}
Quoted 8 lines

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 332

Quoted 3 lines
security/integrity/ima/ima_appraise.c +3 -0
+
+		/* Permit new files with file signatures, but without data. */
+		if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&

This may be correct, but it's not identical to what you're replacing. Since in either case you're setting status to INTEGRITY_PASS the final result is the same, but with a few extra possible steps. Not sure whether that matters.

Good point. I'll have to defer this one to Mimi though.

Quoted 8 lines
Quoted 8 lines
security/integrity/ima/ima_appraise.c +2 -0
+		    xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG) {
 			status = INTEGRITY_PASS;
 		}
+
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else {
Signature · 7 lines
Thiago Jung Bauermann
IBM Linux Technology Center

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#8 lore raw

Re: [PATCH 3/4] ima: Improvements in ima_appraise_measurement()

Quoted 28 lines · Thiago Jung Bauermann

Hello Serge,

Thanks for quickly reviewing these patches!

Quoted 5 lines · Serge E. Hallyn
Quoted 4 lines · Thiago Jung Bauermann

From: Mimi Zohar <[email protected]>

(quoted diff) +0 -0
@@ -241,16 +241,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 	}
 
Quoted 16 lines

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 247

Quoted 13 lines
security/integrity/ima/ima_appraise.c +4 -8
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) &&
-	    (status != INTEGRITY_PASS_IMMUTABLE) &&
-	    (status != INTEGRITY_UNKNOWN)) {
-		if ((status == INTEGRITY_NOLABEL)
-		    || (status == INTEGRITY_NOXATTRS))
-			cause = "missing-HMAC";
-		else if (status == INTEGRITY_FAIL)
-			cause = "invalid-HMAC";
+	switch (status) {
+	case INTEGRITY_PASS:
+	case INTEGRITY_PASS_IMMUTABLE:
+	case INTEGRITY_UNKNOWN:

Wouldn't it be more future-proof to replace this with a 'default', or to at least add a "default: BUG()" to catch new status values?

Quoted 1 line

I agree. I like the "default: BUG()" option.

Agreed. ?I would put it at the end after INTEGRITY_FAIL.

Quoted 38 lines
Quoted 29 lines
Quoted 29 lines
security/integrity/ima/ima_appraise.c +10 -4
+		break;
+	case INTEGRITY_NOXATTRS:	/* No EVM protected xattrs. */
+	case INTEGRITY_NOLABEL:		/* No security.evm xattr. */
+		cause = "missing-HMAC";
+		goto out;
+	case INTEGRITY_FAIL:		/* Invalid HMAC/signature. */
+		cause = "invalid-HMAC";
 		goto out;
 	}
+
 	switch (xattr_value->type) {
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
@@ -316,17 +320,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else if (status != INTEGRITY_PASS) {
+		/* Fix mode, but don't replace file signatures. */
 		if ((ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
 			if (!ima_fix_xattr(dentry, iint))
 				status = INTEGRITY_PASS;
-		} else if ((inode->i_size == 0) &&
-			   (iint->flags & IMA_NEW_FILE) &&
-			   (xattr_value &&
-			    xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+		}
Quoted 8 lines

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 332

Quoted 3 lines
security/integrity/ima/ima_appraise.c +3 -0
+
+		/* Permit new files with file signatures, but without data. */
+		if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&

This may be correct, but it's not identical to what you're replacing. Since in either case you're setting status to INTEGRITY_PASS the final result is the same, but with a few extra possible steps. Not sure whether that matters.

Quoted 1 line

Good point. I'll have to defer this one to Mimi though.

The end result is the same, but add some needed comments.

Mimi

Quoted 11 lines
Quoted 9 lines

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 339

Quoted 9 lines
security/integrity/ima/ima_appraise.c +2 -0
+		    xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG) {
 			status = INTEGRITY_PASS;
 		}
+
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else {

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#9 lore raw

Re: [PATCH 3/4] ima: Improvements in ima_appraise_measurement()

Quoted 29 lines · Mimi Zohar
Quoted 28 lines · Thiago Jung Bauermann

Hello Serge,

Thanks for quickly reviewing these patches!

Quoted 21 lines · Serge E. Hallyn
Quoted 7 lines · Thiago Jung Bauermann

From: Mimi Zohar <[email protected]>

(quoted diff) +0 -2
@@ -241,16 +241,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 	}
 
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) &&
-	    (status != INTEGRITY_PASS_IMMUTABLE) &&

Review int ima_appraise_measurement(enum ima_hooks func, · line 247

Quoted 10 lines
(quoted diff) +4 -6
-	    (status != INTEGRITY_UNKNOWN)) {
-		if ((status == INTEGRITY_NOLABEL)
-		    || (status == INTEGRITY_NOXATTRS))
-			cause = "missing-HMAC";
-		else if (status == INTEGRITY_FAIL)
-			cause = "invalid-HMAC";
+	switch (status) {
+	case INTEGRITY_PASS:
+	case INTEGRITY_PASS_IMMUTABLE:
+	case INTEGRITY_UNKNOWN:

Wouldn't it be more future-proof to replace this with a 'default', or to at least add a "default: BUG()" to catch new status values?

Quoted 3 lines
Quoted 1 line

I agree. I like the "default: BUG()" option.

Agreed. I would put it at the end after INTEGRITY_FAIL.

Ok, what about the version below?

Quoted 38 lines
Quoted 38 lines
Quoted 37 lines
Quoted 22 lines
(quoted diff) +9 -0
+		break;
+	case INTEGRITY_NOXATTRS:	/* No EVM protected xattrs. */
+	case INTEGRITY_NOLABEL:		/* No security.evm xattr. */
+		cause = "missing-HMAC";
+		goto out;
+	case INTEGRITY_FAIL:		/* Invalid HMAC/signature. */
+		cause = "invalid-HMAC";
 		goto out;
 	}
+
 	switch (xattr_value->type) {
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
@@ -316,17 +320,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else if (status != INTEGRITY_PASS) {
+		/* Fix mode, but don't replace file signatures. */
 		if ((ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {

Review int ima_appraise_measurement(enum ima_hooks func, · line 332

Quoted 10 lines
(quoted diff) +4 -4
 			if (!ima_fix_xattr(dentry, iint))
 				status = INTEGRITY_PASS;
-		} else if ((inode->i_size == 0) &&
-			   (iint->flags & IMA_NEW_FILE) &&
-			   (xattr_value &&
-			    xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+		}
+
+		/* Permit new files with file signatures, but without data. */
+		if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&

This may be correct, but it's not identical to what you're replacing. Since in either case you're setting status to INTEGRITY_PASS the final result is the same, but with a few extra possible steps. Not sure whether that matters.

Quoted 3 lines
Quoted 1 line

Good point. I'll have to defer this one to Mimi though.

The end result is the same, but add some needed comments.

The patch is unchanged here, then.

Signature · 2 lines
Thiago Jung Bauermann
IBM Linux Technology Center
Quoted 1 line

From 343bf4ed2974421e254fb4d5cd79aed79c66f016 Mon Sep 17 00:00:00 2001

From: Mimi Zohar <[email protected]>
Date: Mon, 21 Aug 2017 19:28:51 -0300
Subject: [PATCH] ima: Improvements in ima_appraise_measurement()

Replace nested ifs in the EVM xattr verification logic with a switch statement, making the code easier to understand.

Also, add comments to the if statements in the out section and constify the cause variable.

---
 security/integrity/ima/ima_appraise.c | 35 ++++++++++++++++++++++-------------
 1 file changed, 22 insertions(+), 13 deletions(-)
security/integrity/ima/ima_appraise.c +22 -13
index 0c5f94b7b9c3..8bd7a0733e51 100644
@@ -215,7 +215,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 			     int xattr_len, int opened)
 {
 	static const char op[] = "appraise_data";
-	char *cause = "unknown";
+	const char *cause = "unknown";
 	struct dentry *dentry = file_dentry(file);
 	struct inode *inode = d_backing_inode(dentry);
 	enum integrity_status status = INTEGRITY_UNKNOWN;
@@ -241,16 +241,22 @@ int ima_appraise_measurement(enum ima_hooks func,
 	}
 
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) &&
-	    (status != INTEGRITY_PASS_IMMUTABLE) &&
-	    (status != INTEGRITY_UNKNOWN)) {
-		if ((status == INTEGRITY_NOLABEL)
-		    || (status == INTEGRITY_NOXATTRS))
-			cause = "missing-HMAC";
-		else if (status == INTEGRITY_FAIL)
-			cause = "invalid-HMAC";
+	switch (status) {
+	case INTEGRITY_PASS:
+	case INTEGRITY_PASS_IMMUTABLE:
+	case INTEGRITY_UNKNOWN:
+		break;
+	case INTEGRITY_NOXATTRS:	/* No EVM protected xattrs. */
+	case INTEGRITY_NOLABEL:		/* No security.evm xattr. */
+		cause = "missing-HMAC";
+		goto out;
+	case INTEGRITY_FAIL:		/* Invalid HMAC/signature. */
+		cause = "invalid-HMAC";
 		goto out;
+	default:
+		WARN_ONCE(true, "Unexpected integrity status %d\n", status);
 	}
+
 	switch (xattr_value->type) {
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
@@ -316,17 +322,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else if (status != INTEGRITY_PASS) {
+		/* Fix mode, but don't replace file signatures. */
 		if ((ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
 			if (!ima_fix_xattr(dentry, iint))
 				status = INTEGRITY_PASS;
-		} else if ((inode->i_size == 0) &&
-			   (iint->flags & IMA_NEW_FILE) &&
-			   (xattr_value &&
-			    xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+		}
+
+		/* Permit new files with file signatures, but without data. */
+		if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&
+		    xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG) {
 			status = INTEGRITY_PASS;
 		}
+
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else {

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer Acked-by
#10 lore raw

Re: [PATCH 3/4] ima: Improvements in ima_appraise_measurement()

Quoted 31 lines · Thiago Jung Bauermann
Quoted 29 lines · Mimi Zohar
Quoted 28 lines · Thiago Jung Bauermann

Hello Serge,

Thanks for quickly reviewing these patches!

Quoted 21 lines · Serge E. Hallyn
Quoted 7 lines · Thiago Jung Bauermann

From: Mimi Zohar <[email protected]>

security/integrity/ima/ima_appraise.c +0 -2
@@ -241,16 +241,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 	}
 
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) &&
-	    (status != INTEGRITY_PASS_IMMUTABLE) &&

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 247

Quoted 10 lines
security/integrity/ima/ima_appraise.c +4 -6
-	    (status != INTEGRITY_UNKNOWN)) {
-		if ((status == INTEGRITY_NOLABEL)
-		    || (status == INTEGRITY_NOXATTRS))
-			cause = "missing-HMAC";
-		else if (status == INTEGRITY_FAIL)
-			cause = "invalid-HMAC";
+	switch (status) {
+	case INTEGRITY_PASS:
+	case INTEGRITY_PASS_IMMUTABLE:
+	case INTEGRITY_UNKNOWN:

Wouldn't it be more future-proof to replace this with a 'default', or to at least add a "default: BUG()" to catch new status values?

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

I agree. I like the "default: BUG()" option.

Agreed. I would put it at the end after INTEGRITY_FAIL.

Ok, what about the version below?

Since the status is returned by evm, it seems like an actual BUG() is appropriate, but ok.

Quoted 39 lines
Quoted 39 lines
Quoted 39 lines
Quoted 38 lines
Quoted 23 lines
security/integrity/ima/ima_appraise.c +9 -0
+		break;
+	case INTEGRITY_NOXATTRS:	/* No EVM protected xattrs. */
+	case INTEGRITY_NOLABEL:		/* No security.evm xattr. */
+		cause = "missing-HMAC";
+		goto out;
+	case INTEGRITY_FAIL:		/* Invalid HMAC/signature. */
+		cause = "invalid-HMAC";
 		goto out;
 	}
+
 	switch (xattr_value->type) {
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
@@ -316,17 +320,20 @@ int ima_appraise_measurement(enum ima_hooks func,
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
 	} else if (status != INTEGRITY_PASS) {
+		/* Fix mode, but don't replace file signatures. */
 		if ((ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {

security/integrity/ima/ima_appraise.c int ima_appraise_measurement(enum ima_hooks func, · line 332

Quoted 10 lines
security/integrity/ima/ima_appraise.c +4 -4
 			if (!ima_fix_xattr(dentry, iint))
 				status = INTEGRITY_PASS;
-		} else if ((inode->i_size == 0) &&
-			   (iint->flags & IMA_NEW_FILE) &&
-			   (xattr_value &&
-			    xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+		}
+
+		/* Permit new files with file signatures, but without data. */
+		if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&

This may be correct, but it's not identical to what you're replacing. Since in either case you're setting status to INTEGRITY_PASS the final result is the same, but with a few extra possible steps. Not sure whether that matters.

Quoted 3 lines
Quoted 3 lines
Quoted 1 line

Good point. I'll have to defer this one to Mimi though.

The end result is the same, but add some needed comments.

Yes, the same, but with a few extra possible steps, impacting performance, so I just wanted to call that out.

-serge
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#11 lore raw

PATCH 4/4 integrity: Introduce struct evm_xattr

In reply to Thiago Jung Bauermann

Even though struct evm_ima_xattr_data includes a fixed-size array to hold a SHA1 digest, most of the code ignores the array and uses the struct to mean "type indicator followed by data of unspecified size" and tracks the real size of what the struct represents in a separate length variable.

The only exception to that is the EVM code, which correctly uses the definition of struct evm_ima_xattr_data.

This patch makes this explicit in the code by removing the length specification from the array in struct evm_ima_xattr_data. It also changes the name of the element from digest to data, since in most places the array doesn't hold a digest.

A separate struct evm_xattr is introduced, with the original definition of evm_ima_xattr_data to be used in the places that actually expect that definition.

---
 security/integrity/evm/evm_crypto.c   |  4 ++--
 security/integrity/evm/evm_main.c     | 10 +++++-----
 security/integrity/ima/ima_appraise.c |  7 ++++---
 security/integrity/integrity.h        |  5 +++++
 4 files changed, 16 insertions(+), 10 deletions(-)
security/integrity/evm/evm_crypto.c +2 -2
index a46fba322340..86511cf171c1 100644
@@ -302,7 +302,7 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
 			const char *xattr_value, size_t xattr_value_len)
 {
 	struct inode *inode = d_backing_inode(dentry);
-	struct evm_ima_xattr_data xattr_data;
+	struct evm_xattr xattr_data;
 	int rc = 0;
 
 	/*
@@ -318,7 +318,7 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
 	rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
 			   xattr_value_len, xattr_data.digest);
 	if (rc == 0) {
-		xattr_data.type = EVM_XATTR_HMAC;
+		xattr_data.data.type = EVM_XATTR_HMAC;
 		rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
 					   &xattr_data,
 					   sizeof(xattr_data), 0);
security/integrity/evm/evm_main.c +5 -5
index 7a968faca739..cd17744d4749 100644
@@ -122,7 +122,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 					     struct integrity_iint_cache *iint)
 {
 	struct evm_ima_xattr_data *xattr_data = NULL;
-	struct evm_ima_xattr_data calc;
+	struct evm_xattr calc;
 	enum integrity_status evm_status = INTEGRITY_PASS;
 	int rc, xattr_len;
 
@@ -154,7 +154,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 	/* check value type */
 	switch (xattr_data->type) {
 	case EVM_XATTR_HMAC:
-		if (xattr_len != sizeof(struct evm_ima_xattr_data)) {
+		if (xattr_len != sizeof(struct evm_xattr)) {
 			evm_status = INTEGRITY_FAIL;
 			goto out;
 		}
@@ -162,7 +162,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 				   xattr_value_len, calc.digest);
 		if (rc)
 			break;
-		rc = crypto_memneq(xattr_data->digest, calc.digest,
+		rc = crypto_memneq(xattr_data->data, calc.digest,
 			    sizeof(calc.digest));
 		if (rc)
 			rc = -EINVAL;
@@ -501,7 +501,7 @@ int evm_inode_init_security(struct inode *inode,
 				 const struct xattr *lsm_xattr,
 				 struct xattr *evm_xattr)
 {
-	struct evm_ima_xattr_data *xattr_data;
+	struct evm_xattr *xattr_data;
 	int rc;
 
 	if (!evm_key_loaded() || !evm_protected_xattr(lsm_xattr->name))
@@ -511,7 +511,7 @@ int evm_inode_init_security(struct inode *inode,
 	if (!xattr_data)
 		return -ENOMEM;
 
-	xattr_data->type = EVM_XATTR_HMAC;
+	xattr_data->data.type = EVM_XATTR_HMAC;
 	rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
 	if (rc < 0)
 		goto out;
security/integrity/ima/ima_appraise.c +4 -3
index dd10ecbdce45..96e0f95c294b 100644
@@ -167,7 +167,8 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
 		return sig->hash_algo;
 		break;
 	case IMA_XATTR_DIGEST_NG:
-		ret = xattr_value->digest[0];
+		/* first byte contains algorithm id */
+		ret = xattr_value->data[0];
 		if (ret < HASH_ALGO__LAST)
 			return ret;
 		break;
@@ -175,7 +176,7 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
 		/* this is for backward compatibility */
 		if (xattr_len == 21) {
 			unsigned int zero = 0;
-			if (!memcmp(&xattr_value->digest[16], &zero, 4))
+			if (!memcmp(&xattr_value->data[16], &zero, 4))
 				return HASH_ALGO_MD5;
 			else
 				return HASH_ALGO_SHA1;
@@ -272,7 +273,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 			/* xattr length may be longer. md5 hash in previous
 			   version occupied 20 bytes in xattr, instead of 16
 			 */
-			rc = memcmp(&xattr_value->digest[hash_start],
+			rc = memcmp(&xattr_value->data[hash_start],
 				    iint->ima_hash->digest,
 				    iint->ima_hash->length);
 		else
security/integrity/integrity.h +5 -0
index 5e58e02ba8dc..79799a0d9195 100644
@@ -78,6 +78,11 @@ enum evm_ima_xattr_type {
 
 struct evm_ima_xattr_data {
 	u8 type;
+	u8 data[];
+} __packed;
+
+struct evm_xattr {
+	struct evm_ima_xattr_data data;
 	u8 digest[SHA1_DIGEST_SIZE];
 } __packed;
 

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#12 lore raw
In reply to Thiago Jung Bauermann

Hi Thiago,

Quoted 10 lines · Thiago Jung Bauermann

Hello,

These patches come from the "appended signatures support for IMA appraisal" series. They are code improvements and cleanups and I decided to submit them separately for a couple of reasons:

1. they stand on their own and could be included in v4.17;

2. this will simplify the original patch series a bit, by having it contain only the patches actually necessary to implement the feature.

Agreed. ?The first 3 patches are applied. ?The last one, we'll see about.

Mimi

Quoted 17 lines

These are the changes made to them since v5 of the modsig series:

- Patch "integrity: Remove unused macro IMA_ACTION_RULE_FLAGS"
- New patch.

- Patch "ima: Improvements in ima_appraise_measurement()"
- Moved is_ima_sig() to its own patch (not in this series).

Mimi Zohar (1):
ima: Improvements in ima_appraise_measurement()

Thiago Jung Bauermann (3):
integrity: Remove unused macro IMA_ACTION_RULE_FLAGS
ima: Simplify ima_eventsig_init()
integrity: Introduce struct evm_xattr

Quoted 7 lines
 security/integrity/evm/evm_crypto.c       |  4 ++--
 security/integrity/evm/evm_main.c         | 10 ++++----
 security/integrity/ima/ima_appraise.c     | 40 ++++++++++++++++++-------------
 security/integrity/ima/ima_template_lib.c | 11 +++------
 security/integrity/integrity.h            |  6 ++++-
 5 files changed, 39 insertions(+), 32 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html