All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
To: linux-security-module@vger.kernel.org
Cc: Dmitry Kasatkin <dmitry.kasatkin@intel.com>,
	linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	Al Viro <viro@ZenIV.linux.org.uk>,
	David Safford <safford@linux.vnet.ibm.com>,
	Mimi Zohar <zohar@linux.vnet.ibm.com>
Subject: [PATCH v4 12/12] ima: digital signature verification support
Date: Thu, 29 Mar 2012 10:41:40 -0400	[thread overview]
Message-ID: <1333032100-4159-13-git-send-email-zohar@linux.vnet.ibm.com> (raw)
In-Reply-To: <1333032100-4159-1-git-send-email-zohar@linux.vnet.ibm.com>

From: Dmitry Kasatkin <dmitry.kasatkin@intel.com>

This patch adds support for digital signature based integrity appraisal.
With this patch, 'security.ima' contains either the file data hash or
a digital signature of the file data hash. The file data hash provides
the security attribute of file integrity. In addition to file integrity,
a digital signature provides the security attribute of authenticity.

Unlike EVM, when the file metadata changes, the digital signature is
replaced with an HMAC, modification of the file data does not cause the
'security.ima' digital signature to be replaced with a hash. As a
result, after any modification, subsequent file integrity appraisals
would fail.

Although digitally signed files can be modified, but by not updating
'security.ima' to reflect these modifications, in essence digitally
signed files could be considered 'immutable'.

IMA uses a different keyring than EVM. While the EVM keyring should not
be updated after initialization and locked, the IMA keyring should allow
updating or adding new keys when upgrading or installing packages.

Changelog v3:
- Permit files without any 'security.ima' xattr to be labeled properly.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_appraise.c |   70 ++++++++++++++++++++++++---------
 security/integrity/integrity.h        |    1 +
 2 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 9a7d1eb..8324e49 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -64,7 +64,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
 {
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
-	struct evm_ima_xattr_data xattr_value;
+	struct evm_ima_xattr_data *xattr_value = NULL;
 	enum integrity_status status = INTEGRITY_UNKNOWN;
 	const char *op = "appraise_data";
 	char *cause = "unknown";
@@ -78,8 +78,8 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
 	if (iint->flags & IMA_APPRAISED)
 		return iint->ima_status;
 
-	rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value,
-				   sizeof xattr_value);
+	rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value,
+				0, GFP_NOFS);
 	if (rc <= 0) {
 		if (rc && rc != -ENODATA)
 			goto out;
@@ -90,8 +90,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
 		goto out;
 	}
 
-	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value,
-				 rc, iint);
+	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
 	if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
 		if ((status == INTEGRITY_NOLABEL)
 		    || (status == INTEGRITY_NOXATTRS))
@@ -101,30 +100,58 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
 		goto out;
 	}
 
-	rc = memcmp(xattr_value.digest, iint->ima_xattr.digest,
-		    IMA_DIGEST_SIZE);
-	if (rc) {
-		status = INTEGRITY_FAIL;
-		cause = "invalid-hash";
-		print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
-				     &xattr_value, sizeof xattr_value);
-		print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
-				     (u8 *)&iint->ima_xattr,
-				     sizeof iint->ima_xattr);
-		goto out;
+	switch (xattr_value->type) {
+	case IMA_XATTR_DIGEST:
+		rc = memcmp(xattr_value->digest, iint->ima_xattr.digest,
+			    IMA_DIGEST_SIZE);
+		if (rc) {
+			cause = "invalid-hash";
+			status = INTEGRITY_FAIL;
+			print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
+					     xattr_value, sizeof(*xattr_value));
+			print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
+					     (u8 *)&iint->ima_xattr,
+					     sizeof iint->ima_xattr);
+			break;
+		}
+		status = INTEGRITY_PASS;
+		break;
+	case EVM_IMA_XATTR_DIGSIG:
+		iint->flags |= IMA_DIGSIG;
+		rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
+					     xattr_value->digest, rc - 1,
+					     iint->ima_xattr.digest,
+					     IMA_DIGEST_SIZE);
+		if (rc == -EOPNOTSUPP) {
+			status = INTEGRITY_UNKNOWN;
+		} else if (rc) {
+			cause = "invalid-signature";
+			status = INTEGRITY_FAIL;
+		} else {
+			status = INTEGRITY_PASS;
+		}
+		break;
+	default:
+		status = INTEGRITY_UNKNOWN;
+		cause = "unknown-ima-data";
+		break;
 	}
-	status = INTEGRITY_PASS;
-	iint->flags |= IMA_APPRAISED;
+
 out:
 	if (status != INTEGRITY_PASS) {
-		if (ima_appraise & IMA_APPRAISE_FIX) {
+		if ((ima_appraise & IMA_APPRAISE_FIX) &&
+		    (!xattr_value ||
+		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
 			ima_fix_xattr(dentry, iint);
 			status = INTEGRITY_PASS;
 		}
 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
 				    op, cause, rc, 0);
+	} else {
+		iint->flags |= IMA_APPRAISED;
 	}
 	iint->ima_status = status;
+	kfree(xattr_value);
 	return status;
 }
 
@@ -136,9 +163,14 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
 	struct dentry *dentry = file->f_dentry;
 	int rc = 0;
 
+	/* do not collect and update hash for digital signatures */
+	if (iint->flags & IMA_DIGSIG)
+		return;
+
 	rc = ima_collect_measurement(iint, file);
 	if (rc < 0)
 		return;
+
 	ima_fix_xattr(dentry, iint);
 }
 
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index c145331..0594a57 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -21,6 +21,7 @@
 #define IMA_APPRAISE		4
 #define IMA_APPRAISED		8
 #define IMA_COLLECTED		16
+#define IMA_DIGSIG		32
 
 enum evm_ima_xattr_type {
 	IMA_XATTR_DIGEST = 0x01,
-- 
1.7.6.5


      parent reply	other threads:[~2012-03-29 14:43 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-29 14:41 [PATCH v4 00/12] ima: appraisal extension Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 01/12] vfs: extend vfs_removexattr locking Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 02/12] vfs: move ima_file_free before releasing the file Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 03/12] ima: free securityfs violations file Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 04/12] ima: integrity appraisal extension Mimi Zohar
2012-04-02  7:20   ` Kasatkin, Dmitry
2012-04-02  7:20     ` Kasatkin, Dmitry
2012-04-02 11:18     ` Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 05/12] ima: add appraise action keywords and default rules Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 06/12] ima: allocating iint improvements Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 07/12] ima: replace iint spinlock with rwlock/read_lock Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 08/12] ima: add inode_post_setattr call Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 09/12] ima: add ima_inode_setxattr/removexattr function and calls Mimi Zohar
2012-03-29 14:41 ` [PATCH v4 10/12] ima: defer calling __fput() Mimi Zohar
2012-04-04  8:52   ` Kasatkin, Dmitry
2012-04-04  8:52     ` Kasatkin, Dmitry
2012-03-29 14:41 ` [PATCH v4 11/12] ima: add support for different security.ima data types Mimi Zohar
2012-03-29 14:41 ` Mimi Zohar [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1333032100-4159-13-git-send-email-zohar@linux.vnet.ibm.com \
    --to=zohar@linux.vnet.ibm.com \
    --cc=dmitry.kasatkin@intel.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=safford@linux.vnet.ibm.com \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.