aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorDmitry Kasatkin <d.kasatkin@samsung.com>2013-08-12 04:22:51 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2013-10-26 21:32:55 -0400
commit3ea7a56067e663278470c04fd655adf809e72d4d (patch)
tree8216b30887dc86cf7594f6fd1cc729b7eda28c0a /security/integrity
parente7a2ad7eb6f48ad80c70a22dd8167fb34b409466 (diff)
ima: provide hash algo info in the xattr
All files labeled with 'security.ima' hashes, are hashed using the same hash algorithm. Changing from one hash algorithm to another, requires relabeling the filesystem. This patch defines a new xattr type, which includes the hash algorithm, permitting different files to be hashed with different algorithms. Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/ima/ima_appraise.c61
-rw-r--r--security/integrity/integrity.h13
2 files changed, 59 insertions, 15 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 116630ca5ff3..734e9468aca0 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -15,6 +15,7 @@
15#include <linux/magic.h> 15#include <linux/magic.h>
16#include <linux/ima.h> 16#include <linux/ima.h>
17#include <linux/evm.h> 17#include <linux/evm.h>
18#include <crypto/hash_info.h>
18 19
19#include "ima.h" 20#include "ima.h"
20 21
@@ -45,10 +46,22 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
45static int ima_fix_xattr(struct dentry *dentry, 46static int ima_fix_xattr(struct dentry *dentry,
46 struct integrity_iint_cache *iint) 47 struct integrity_iint_cache *iint)
47{ 48{
48 iint->ima_hash->type = IMA_XATTR_DIGEST; 49 int rc, offset;
49 return __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, 50 u8 algo = iint->ima_hash->algo;
50 &iint->ima_hash->type, 51
51 1 + iint->ima_hash->length, 0); 52 if (algo <= HASH_ALGO_SHA1) {
53 offset = 1;
54 iint->ima_hash->xattr.sha1.type = IMA_XATTR_DIGEST;
55 } else {
56 offset = 0;
57 iint->ima_hash->xattr.ng.type = IMA_XATTR_DIGEST_NG;
58 iint->ima_hash->xattr.ng.algo = algo;
59 }
60 rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA,
61 &iint->ima_hash->xattr.data[offset],
62 (sizeof(iint->ima_hash->xattr) - offset) +
63 iint->ima_hash->length, 0);
64 return rc;
52} 65}
53 66
54/* Return specific func appraised cached result */ 67/* Return specific func appraised cached result */
@@ -112,15 +125,31 @@ void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
112{ 125{
113 struct signature_v2_hdr *sig; 126 struct signature_v2_hdr *sig;
114 127
115 if (!xattr_value || xattr_len < 0 || xattr_len <= 1 + sizeof(*sig)) 128 if (!xattr_value || xattr_len < 2)
116 return; 129 return;
117 130
118 sig = (typeof(sig)) xattr_value->digest; 131 switch (xattr_value->type) {
119 132 case EVM_IMA_XATTR_DIGSIG:
120 if (xattr_value->type != EVM_IMA_XATTR_DIGSIG || sig->version != 2) 133 sig = (typeof(sig))xattr_value;
121 return; 134 if (sig->version != 2 || xattr_len <= sizeof(*sig))
122 135 return;
123 hash->algo = sig->hash_algo; 136 hash->algo = sig->hash_algo;
137 break;
138 case IMA_XATTR_DIGEST_NG:
139 hash->algo = xattr_value->digest[0];
140 break;
141 case IMA_XATTR_DIGEST:
142 /* this is for backward compatibility */
143 if (xattr_len == 21) {
144 unsigned int zero = 0;
145 if (!memcmp(&xattr_value->digest[16], &zero, 4))
146 hash->algo = HASH_ALGO_MD5;
147 else
148 hash->algo = HASH_ALGO_SHA1;
149 } else if (xattr_len == 17)
150 hash->algo = HASH_ALGO_MD5;
151 break;
152 }
124} 153}
125 154
126int ima_read_xattr(struct dentry *dentry, 155int ima_read_xattr(struct dentry *dentry,
@@ -153,7 +182,7 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
153 enum integrity_status status = INTEGRITY_UNKNOWN; 182 enum integrity_status status = INTEGRITY_UNKNOWN;
154 const char *op = "appraise_data"; 183 const char *op = "appraise_data";
155 char *cause = "unknown"; 184 char *cause = "unknown";
156 int rc = xattr_len; 185 int rc = xattr_len, hash_start = 0;
157 186
158 if (!ima_appraise) 187 if (!ima_appraise)
159 return 0; 188 return 0;
@@ -180,17 +209,21 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
180 goto out; 209 goto out;
181 } 210 }
182 switch (xattr_value->type) { 211 switch (xattr_value->type) {
212 case IMA_XATTR_DIGEST_NG:
213 /* first byte contains algorithm id */
214 hash_start = 1;
183 case IMA_XATTR_DIGEST: 215 case IMA_XATTR_DIGEST:
184 if (iint->flags & IMA_DIGSIG_REQUIRED) { 216 if (iint->flags & IMA_DIGSIG_REQUIRED) {
185 cause = "IMA signature required"; 217 cause = "IMA signature required";
186 status = INTEGRITY_FAIL; 218 status = INTEGRITY_FAIL;
187 break; 219 break;
188 } 220 }
189 if (xattr_len - 1 >= iint->ima_hash->length) 221 if (xattr_len - sizeof(xattr_value->type) - hash_start >=
222 iint->ima_hash->length)
190 /* xattr length may be longer. md5 hash in previous 223 /* xattr length may be longer. md5 hash in previous
191 version occupied 20 bytes in xattr, instead of 16 224 version occupied 20 bytes in xattr, instead of 16
192 */ 225 */
193 rc = memcmp(xattr_value->digest, 226 rc = memcmp(&xattr_value->digest[hash_start],
194 iint->ima_hash->digest, 227 iint->ima_hash->digest,
195 iint->ima_hash->length); 228 iint->ima_hash->length);
196 else 229 else
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 5429ca59125b..2fb5e53e927f 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -54,6 +54,7 @@ enum evm_ima_xattr_type {
54 IMA_XATTR_DIGEST = 0x01, 54 IMA_XATTR_DIGEST = 0x01,
55 EVM_XATTR_HMAC, 55 EVM_XATTR_HMAC,
56 EVM_IMA_XATTR_DIGSIG, 56 EVM_IMA_XATTR_DIGSIG,
57 IMA_XATTR_DIGEST_NG,
57}; 58};
58 59
59struct evm_ima_xattr_data { 60struct evm_ima_xattr_data {
@@ -66,7 +67,17 @@ struct evm_ima_xattr_data {
66struct ima_digest_data { 67struct ima_digest_data {
67 u8 algo; 68 u8 algo;
68 u8 length; 69 u8 length;
69 u8 type; 70 union {
71 struct {
72 u8 unused;
73 u8 type;
74 } sha1;
75 struct {
76 u8 type;
77 u8 algo;
78 } ng;
79 u8 data[2];
80 } xattr;
70 u8 digest[0]; 81 u8 digest[0];
71} __packed; 82} __packed;
72 83