Commit 3ea7a56067e663278470c04fd655adf809e72d4d

Authored by Dmitry Kasatkin
Committed by Mimi Zohar
1 parent e7a2ad7eb6

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>

Showing 2 changed files with 59 additions and 15 deletions Side-by-side Diff

security/integrity/ima/ima_appraise.c
... ... @@ -15,6 +15,7 @@
15 15 #include <linux/magic.h>
16 16 #include <linux/ima.h>
17 17 #include <linux/evm.h>
  18 +#include <crypto/hash_info.h>
18 19  
19 20 #include "ima.h"
20 21  
... ... @@ -45,10 +46,22 @@
45 46 static int ima_fix_xattr(struct dentry *dentry,
46 47 struct integrity_iint_cache *iint)
47 48 {
48   - iint->ima_hash->type = IMA_XATTR_DIGEST;
49   - return __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA,
50   - &iint->ima_hash->type,
51   - 1 + iint->ima_hash->length, 0);
  49 + int rc, offset;
  50 + u8 algo = iint->ima_hash->algo;
  51 +
  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 67 /* Return specific func appraised cached result */
55 68  
... ... @@ -112,15 +125,31 @@
112 125 {
113 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 129 return;
117 130  
118   - sig = (typeof(sig)) xattr_value->digest;
119   -
120   - if (xattr_value->type != EVM_IMA_XATTR_DIGSIG || sig->version != 2)
121   - return;
122   -
123   - hash->algo = sig->hash_algo;
  131 + switch (xattr_value->type) {
  132 + case EVM_IMA_XATTR_DIGSIG:
  133 + sig = (typeof(sig))xattr_value;
  134 + if (sig->version != 2 || xattr_len <= sizeof(*sig))
  135 + return;
  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  
126 155 int ima_read_xattr(struct dentry *dentry,
... ... @@ -153,7 +182,7 @@
153 182 enum integrity_status status = INTEGRITY_UNKNOWN;
154 183 const char *op = "appraise_data";
155 184 char *cause = "unknown";
156   - int rc = xattr_len;
  185 + int rc = xattr_len, hash_start = 0;
157 186  
158 187 if (!ima_appraise)
159 188 return 0;
160 189  
161 190  
... ... @@ -180,17 +209,21 @@
180 209 goto out;
181 210 }
182 211 switch (xattr_value->type) {
  212 + case IMA_XATTR_DIGEST_NG:
  213 + /* first byte contains algorithm id */
  214 + hash_start = 1;
183 215 case IMA_XATTR_DIGEST:
184 216 if (iint->flags & IMA_DIGSIG_REQUIRED) {
185 217 cause = "IMA signature required";
186 218 status = INTEGRITY_FAIL;
187 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 223 /* xattr length may be longer. md5 hash in previous
191 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 227 iint->ima_hash->digest,
195 228 iint->ima_hash->length);
196 229 else
security/integrity/integrity.h
... ... @@ -54,6 +54,7 @@
54 54 IMA_XATTR_DIGEST = 0x01,
55 55 EVM_XATTR_HMAC,
56 56 EVM_IMA_XATTR_DIGSIG,
  57 + IMA_XATTR_DIGEST_NG,
57 58 };
58 59  
59 60 struct evm_ima_xattr_data {
... ... @@ -66,7 +67,17 @@
66 67 struct ima_digest_data {
67 68 u8 algo;
68 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 81 u8 digest[0];
71 82 } __packed;
72 83