aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Kasatkin <dmitry.kasatkin@intel.com>2011-08-31 07:07:06 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2012-09-07 14:57:48 -0400
commit8606404fa555c2ee691376fcc640ab89fe752035 (patch)
tree4b2d2e43b7ad196b46757faff10d04803381a543
parent5a44b41207174e1882ce0c24a752f4cfb65dab07 (diff)
ima: digital signature verification support
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 v4: - Change IMA_DIGSIG to hex equivalent 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>
-rw-r--r--security/integrity/ima/ima_appraise.c70
-rw-r--r--security/integrity/integrity.h1
2 files changed, 52 insertions, 19 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index f9979976aa5d..4cdf36ad884a 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -63,7 +63,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
63{ 63{
64 struct dentry *dentry = file->f_dentry; 64 struct dentry *dentry = file->f_dentry;
65 struct inode *inode = dentry->d_inode; 65 struct inode *inode = dentry->d_inode;
66 struct evm_ima_xattr_data xattr_value; 66 struct evm_ima_xattr_data *xattr_value = NULL;
67 enum integrity_status status = INTEGRITY_UNKNOWN; 67 enum integrity_status status = INTEGRITY_UNKNOWN;
68 const char *op = "appraise_data"; 68 const char *op = "appraise_data";
69 char *cause = "unknown"; 69 char *cause = "unknown";
@@ -77,8 +77,8 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
77 if (iint->flags & IMA_APPRAISED) 77 if (iint->flags & IMA_APPRAISED)
78 return iint->ima_status; 78 return iint->ima_status;
79 79
80 rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value, 80 rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value,
81 sizeof xattr_value); 81 0, GFP_NOFS);
82 if (rc <= 0) { 82 if (rc <= 0) {
83 if (rc && rc != -ENODATA) 83 if (rc && rc != -ENODATA)
84 goto out; 84 goto out;
@@ -89,8 +89,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
89 goto out; 89 goto out;
90 } 90 }
91 91
92 status = evm_verifyxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value, 92 status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
93 rc, iint);
94 if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) { 93 if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
95 if ((status == INTEGRITY_NOLABEL) 94 if ((status == INTEGRITY_NOLABEL)
96 || (status == INTEGRITY_NOXATTRS)) 95 || (status == INTEGRITY_NOXATTRS))
@@ -100,30 +99,58 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
100 goto out; 99 goto out;
101 } 100 }
102 101
103 rc = memcmp(xattr_value.digest, iint->ima_xattr.digest, 102 switch (xattr_value->type) {
104 IMA_DIGEST_SIZE); 103 case IMA_XATTR_DIGEST:
105 if (rc) { 104 rc = memcmp(xattr_value->digest, iint->ima_xattr.digest,
106 status = INTEGRITY_FAIL; 105 IMA_DIGEST_SIZE);
107 cause = "invalid-hash"; 106 if (rc) {
108 print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE, 107 cause = "invalid-hash";
109 &xattr_value, sizeof xattr_value); 108 status = INTEGRITY_FAIL;
110 print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE, 109 print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
111 (u8 *)&iint->ima_xattr, 110 xattr_value, sizeof(*xattr_value));
112 sizeof iint->ima_xattr); 111 print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
113 goto out; 112 (u8 *)&iint->ima_xattr,
113 sizeof iint->ima_xattr);
114 break;
115 }
116 status = INTEGRITY_PASS;
117 break;
118 case EVM_IMA_XATTR_DIGSIG:
119 iint->flags |= IMA_DIGSIG;
120 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
121 xattr_value->digest, rc - 1,
122 iint->ima_xattr.digest,
123 IMA_DIGEST_SIZE);
124 if (rc == -EOPNOTSUPP) {
125 status = INTEGRITY_UNKNOWN;
126 } else if (rc) {
127 cause = "invalid-signature";
128 status = INTEGRITY_FAIL;
129 } else {
130 status = INTEGRITY_PASS;
131 }
132 break;
133 default:
134 status = INTEGRITY_UNKNOWN;
135 cause = "unknown-ima-data";
136 break;
114 } 137 }
115 status = INTEGRITY_PASS; 138
116 iint->flags |= IMA_APPRAISED;
117out: 139out:
118 if (status != INTEGRITY_PASS) { 140 if (status != INTEGRITY_PASS) {
119 if (ima_appraise & IMA_APPRAISE_FIX) { 141 if ((ima_appraise & IMA_APPRAISE_FIX) &&
142 (!xattr_value ||
143 xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
120 ima_fix_xattr(dentry, iint); 144 ima_fix_xattr(dentry, iint);
121 status = INTEGRITY_PASS; 145 status = INTEGRITY_PASS;
122 } 146 }
123 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, 147 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
124 op, cause, rc, 0); 148 op, cause, rc, 0);
149 } else {
150 iint->flags |= IMA_APPRAISED;
125 } 151 }
126 iint->ima_status = status; 152 iint->ima_status = status;
153 kfree(xattr_value);
127 return status; 154 return status;
128} 155}
129 156
@@ -135,9 +162,14 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
135 struct dentry *dentry = file->f_dentry; 162 struct dentry *dentry = file->f_dentry;
136 int rc = 0; 163 int rc = 0;
137 164
165 /* do not collect and update hash for digital signatures */
166 if (iint->flags & IMA_DIGSIG)
167 return;
168
138 rc = ima_collect_measurement(iint, file); 169 rc = ima_collect_measurement(iint, file);
139 if (rc < 0) 170 if (rc < 0)
140 return; 171 return;
172
141 ima_fix_xattr(dentry, iint); 173 ima_fix_xattr(dentry, iint);
142} 174}
143 175
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 91ccef1c704b..4eec1b14193e 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -21,6 +21,7 @@
21#define IMA_APPRAISE 0x04 21#define IMA_APPRAISE 0x04
22#define IMA_APPRAISED 0x08 22#define IMA_APPRAISED 0x08
23#define IMA_COLLECTED 0x10 23#define IMA_COLLECTED 0x10
24#define IMA_DIGSIG 0x20
24 25
25enum evm_ima_xattr_type { 26enum evm_ima_xattr_type {
26 IMA_XATTR_DIGEST = 0x01, 27 IMA_XATTR_DIGEST = 0x01,