Commit a71dc65d30a472409f05d247f4eab91b14acf2f5

Authored by Roberto Sassu
Committed by Mimi Zohar
1 parent 4d7aeee73f

ima: switch to new template management mechanism

This patch performs the switch to the new template mechanism by modifying
the functions ima_alloc_init_template(), ima_measurements_show() and
ima_ascii_measurements_show(). The old function ima_template_show() was
removed as it is no longer needed. Also, if the template descriptor used
to generate a measurement entry is not 'ima', the whole length of field
data stored for an entry is provided before the data itself through the
binary_runtime_measurement interface.

Changelog:
- unnecessary to use strncmp() (Mimi Zohar)
- create new variable 'field' in ima_alloc_init_template() (Roberto Sassu)
- use GFP_NOFS flag in ima_alloc_init_template() (Roberto Sassu)
- new variable 'num_fields' in ima_store_template() (Roberto Sassu,
  proposed by Mimi Zohar)
- rename ima_calc_buffer_hash/template_hash() to ima_calc_field_array_hash(),
  something more generic (Mimi, requested by Dmitry)
- sparse error fix - Fengguang Wu
- fix lindent warnings
- always include the field length in the template data length
- include the template field length variable size in the template data length
- include both the template field data and field length in the template digest
  calculation. Simplifies verifying the template digest. (Mimi)

Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>

Showing 5 changed files with 107 additions and 97 deletions Side-by-side Diff

security/integrity/ima/ima.h
... ... @@ -72,17 +72,11 @@
72 72 struct ima_template_field **fields;
73 73 };
74 74  
75   -/* IMA inode template definition */
76   -struct ima_template_data {
77   - u8 digest[IMA_DIGEST_SIZE]; /* sha1/md5 measurement hash */
78   - char file_name[IMA_EVENT_NAME_LEN_MAX + 1]; /* name + \0 */
79   -};
80   -
81 75 struct ima_template_entry {
82 76 u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
83   - const char *template_name;
84   - int template_len;
85   - struct ima_template_data template;
  77 + struct ima_template_desc *template_desc; /* template descriptor */
  78 + u32 template_data_len;
  79 + struct ima_field_data template_data[0]; /* template related data */
86 80 };
87 81  
88 82 struct ima_queue_entry {
89 83  
... ... @@ -102,14 +96,16 @@
102 96 const char *op, struct inode *inode,
103 97 const unsigned char *filename);
104 98 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
105   -int ima_calc_buffer_hash(const void *data, int len,
106   - struct ima_digest_data *hash);
  99 +int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
  100 + struct ima_digest_data *hash);
107 101 int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
108 102 void ima_add_violation(struct file *file, const unsigned char *filename,
109 103 const char *op, const char *cause);
110 104 int ima_init_crypto(void);
111 105 void ima_putc(struct seq_file *m, void *data, int datalen);
112 106 void ima_print_digest(struct seq_file *m, u8 *digest, int size);
  107 +struct ima_template_desc *ima_template_desc_current(void);
  108 +int ima_init_template(void);
113 109  
114 110 int ima_init_template(void);
115 111  
... ... @@ -146,7 +142,6 @@
146 142 struct ima_template_entry **entry);
147 143 int ima_store_template(struct ima_template_entry *entry, int violation,
148 144 struct inode *inode, const unsigned char *filename);
149   -void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
150 145 const char *ima_d_path(struct path *path, char **pathbuf);
151 146  
152 147 /* rbtree tree calls to lookup, insert, delete
security/integrity/ima/ima_api.c
... ... @@ -21,8 +21,6 @@
21 21 #include <crypto/hash_info.h>
22 22 #include "ima.h"
23 23  
24   -static const char *IMA_TEMPLATE_NAME = "ima";
25   -
26 24 /*
27 25 * ima_alloc_init_template - create and initialize a new template entry
28 26 */
29 27  
30 28  
31 29  
32 30  
33 31  
... ... @@ -30,52 +28,32 @@
30 28 struct file *file, const unsigned char *filename,
31 29 struct ima_template_entry **entry)
32 30 {
33   - struct ima_template_entry *e;
34   - int result = 0;
  31 + struct ima_template_desc *template_desc = ima_template_desc_current();
  32 + int i, result = 0;
35 33  
36   - e = kzalloc(sizeof(**entry), GFP_NOFS);
37   - if (!e)
  34 + *entry = kzalloc(sizeof(**entry) + template_desc->num_fields *
  35 + sizeof(struct ima_field_data), GFP_NOFS);
  36 + if (!*entry)
38 37 return -ENOMEM;
39 38  
40   - memset(&(e)->template, 0, sizeof(e->template));
41   - if (!iint) /* IMA measurement violation entry */
42   - goto out;
  39 + for (i = 0; i < template_desc->num_fields; i++) {
  40 + struct ima_template_field *field = template_desc->fields[i];
  41 + u32 len;
43 42  
44   - if (iint->ima_hash->algo != ima_hash_algo) {
45   - struct inode *inode;
46   - struct {
47   - struct ima_digest_data hdr;
48   - char digest[IMA_MAX_DIGEST_SIZE];
49   - } hash;
  43 + result = field->field_init(iint, file, filename,
  44 + &((*entry)->template_data[i]));
  45 + if (result != 0)
  46 + goto out;
50 47  
51   - if (!file) {
52   - result = -EINVAL;
53   - goto out_free;
54   - }
55   -
56   - inode = file_inode(file);
57   - hash.hdr.algo = ima_hash_algo;
58   - hash.hdr.length = SHA1_DIGEST_SIZE;
59   - result = ima_calc_file_hash(file, &hash.hdr);
60   - if (result) {
61   - integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
62   - filename, "collect_data",
63   - "failed", result, 0);
64   - goto out_free;
65   - } else
66   - memcpy(e->template.digest, hash.hdr.digest,
67   - hash.hdr.length);
68   - } else
69   - memcpy(e->template.digest, iint->ima_hash->digest,
70   - iint->ima_hash->length);
71   -out:
72   - strcpy(e->template.file_name,
73   - (strlen(filename) > IMA_EVENT_NAME_LEN_MAX && file != NULL) ?
74   - file->f_dentry->d_name.name : filename);
75   - *entry = e;
  48 + len = (*entry)->template_data[i].len;
  49 + (*entry)->template_data_len += sizeof(len);
  50 + (*entry)->template_data_len += len;
  51 + }
  52 + (*entry)->template_desc = template_desc;
76 53 return 0;
77   -out_free:
78   - kfree(e);
  54 +out:
  55 + kfree(*entry);
  56 + *entry = NULL;
79 57 return result;
80 58 }
81 59  
82 60  
83 61  
84 62  
85 63  
... ... @@ -101,24 +79,23 @@
101 79 {
102 80 const char *op = "add_template_measure";
103 81 const char *audit_cause = "hashing_error";
  82 + char *template_name = entry->template_desc->name;
104 83 int result;
105 84 struct {
106 85 struct ima_digest_data hdr;
107 86 char digest[TPM_DIGEST_SIZE];
108 87 } hash;
109 88  
110   - memset(entry->digest, 0, sizeof(entry->digest));
111   - entry->template_name = IMA_TEMPLATE_NAME;
112   - entry->template_len = sizeof(entry->template);
113   -
114 89 if (!violation) {
  90 + int num_fields = entry->template_desc->num_fields;
  91 +
115 92 /* this function uses default algo */
116 93 hash.hdr.algo = HASH_ALGO_SHA1;
117   - result = ima_calc_buffer_hash(&entry->template,
118   - entry->template_len, &hash.hdr);
  94 + result = ima_calc_field_array_hash(&entry->template_data[0],
  95 + num_fields, &hash.hdr);
119 96 if (result < 0) {
120 97 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
121   - entry->template_name, op,
  98 + template_name, op,
122 99 audit_cause, result, 0);
123 100 return result;
124 101 }
security/integrity/ima/ima_crypto.c
... ... @@ -137,26 +137,46 @@
137 137 }
138 138  
139 139 /*
140   - * Calculate the hash of a given buffer
  140 + * Calculate the hash of template data
141 141 */
142   -static int ima_calc_buffer_hash_tfm(const void *buf, int len,
143   - struct ima_digest_data *hash,
144   - struct crypto_shash *tfm)
  142 +static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
  143 + int num_fields,
  144 + struct ima_digest_data *hash,
  145 + struct crypto_shash *tfm)
145 146 {
146 147 struct {
147 148 struct shash_desc shash;
148 149 char ctx[crypto_shash_descsize(tfm)];
149 150 } desc;
  151 + int rc, i;
150 152  
151 153 desc.shash.tfm = tfm;
152 154 desc.shash.flags = 0;
153 155  
154 156 hash->length = crypto_shash_digestsize(tfm);
155 157  
156   - return crypto_shash_digest(&desc.shash, buf, len, hash->digest);
  158 + rc = crypto_shash_init(&desc.shash);
  159 + if (rc != 0)
  160 + return rc;
  161 +
  162 + for (i = 0; i < num_fields; i++) {
  163 + rc = crypto_shash_update(&desc.shash,
  164 + (const u8 *) &field_data[i].len,
  165 + sizeof(field_data[i].len));
  166 + rc = crypto_shash_update(&desc.shash, field_data[i].data,
  167 + field_data[i].len);
  168 + if (rc)
  169 + break;
  170 + }
  171 +
  172 + if (!rc)
  173 + rc = crypto_shash_final(&desc.shash, hash->digest);
  174 +
  175 + return rc;
157 176 }
158 177  
159   -int ima_calc_buffer_hash(const void *buf, int len, struct ima_digest_data *hash)
  178 +int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
  179 + struct ima_digest_data *hash)
160 180 {
161 181 struct crypto_shash *tfm;
162 182 int rc;
... ... @@ -165,7 +185,7 @@
165 185 if (IS_ERR(tfm))
166 186 return PTR_ERR(tfm);
167 187  
168   - rc = ima_calc_buffer_hash_tfm(buf, len, hash, tfm);
  188 + rc = ima_calc_field_array_hash_tfm(field_data, num_fields, hash, tfm);
169 189  
170 190 ima_free_tfm(tfm);
171 191  
security/integrity/ima/ima_fs.c
... ... @@ -110,6 +110,7 @@
110 110 * char[20]=template digest
111 111 * 32bit-le=template name size
112 112 * char[n]=template name
  113 + * [eventdata length]
113 114 * eventdata[n]=template specific data
114 115 */
115 116 static int ima_measurements_show(struct seq_file *m, void *v)
... ... @@ -119,6 +120,7 @@
119 120 struct ima_template_entry *e;
120 121 int namelen;
121 122 u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
  123 + int i;
122 124  
123 125 /* get entry */
124 126 e = qe->entry;
125 127  
126 128  
... ... @@ -136,15 +138,22 @@
136 138 ima_putc(m, e->digest, TPM_DIGEST_SIZE);
137 139  
138 140 /* 3rd: template name size */
139   - namelen = strlen(e->template_name);
  141 + namelen = strlen(e->template_desc->name);
140 142 ima_putc(m, &namelen, sizeof namelen);
141 143  
142 144 /* 4th: template name */
143   - ima_putc(m, (void *)e->template_name, namelen);
  145 + ima_putc(m, e->template_desc->name, namelen);
144 146  
145   - /* 5th: template specific data */
146   - ima_template_show(m, (struct ima_template_data *)&e->template,
147   - IMA_SHOW_BINARY);
  147 + /* 5th: template length (except for 'ima' template) */
  148 + if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
  149 + ima_putc(m, &e->template_data_len,
  150 + sizeof(e->template_data_len));
  151 +
  152 + /* 6th: template specific data */
  153 + for (i = 0; i < e->template_desc->num_fields; i++) {
  154 + e->template_desc->fields[i]->field_show(m, IMA_SHOW_BINARY,
  155 + &e->template_data[i]);
  156 + }
148 157 return 0;
149 158 }
150 159  
151 160  
... ... @@ -175,33 +184,13 @@
175 184 seq_printf(m, "%02x", *(digest + i));
176 185 }
177 186  
178   -void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
179   -{
180   - struct ima_template_data *entry = e;
181   - int namelen;
182   -
183   - switch (show) {
184   - case IMA_SHOW_ASCII:
185   - ima_print_digest(m, entry->digest, IMA_DIGEST_SIZE);
186   - seq_printf(m, " %s\n", entry->file_name);
187   - break;
188   - case IMA_SHOW_BINARY:
189   - ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
190   -
191   - namelen = strlen(entry->file_name);
192   - ima_putc(m, &namelen, sizeof namelen);
193   - ima_putc(m, entry->file_name, namelen);
194   - default:
195   - break;
196   - }
197   -}
198   -
199 187 /* print in ascii */
200 188 static int ima_ascii_measurements_show(struct seq_file *m, void *v)
201 189 {
202 190 /* the list never shrinks, so we don't need a lock here */
203 191 struct ima_queue_entry *qe = v;
204 192 struct ima_template_entry *e;
  193 + int i;
205 194  
206 195 /* get entry */
207 196 e = qe->entry;
208 197  
... ... @@ -215,11 +204,18 @@
215 204 ima_print_digest(m, e->digest, TPM_DIGEST_SIZE);
216 205  
217 206 /* 3th: template name */
218   - seq_printf(m, " %s ", e->template_name);
  207 + seq_printf(m, " %s", e->template_desc->name);
219 208  
220 209 /* 4th: template specific data */
221   - ima_template_show(m, (struct ima_template_data *)&e->template,
222   - IMA_SHOW_ASCII);
  210 + for (i = 0; i < e->template_desc->num_fields; i++) {
  211 + seq_puts(m, " ");
  212 + if (e->template_data[i].len == 0)
  213 + continue;
  214 +
  215 + e->template_desc->fields[i]->field_show(m, IMA_SHOW_ASCII,
  216 + &e->template_data[i]);
  217 + }
  218 + seq_puts(m, "\n");
223 219 return 0;
224 220 }
225 221  
security/integrity/ima/ima_template.c
... ... @@ -31,6 +31,20 @@
31 31 .field_show = ima_show_template_string},
32 32 };
33 33  
  34 +static struct ima_template_desc *ima_template;
  35 +
  36 +static struct ima_template_desc *lookup_template_desc(const char *name)
  37 +{
  38 + int i;
  39 +
  40 + for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
  41 + if (strcmp(defined_templates[i].name, name) == 0)
  42 + return defined_templates + i;
  43 + }
  44 +
  45 + return NULL;
  46 +}
  47 +
34 48 static struct ima_template_field *lookup_template_field(const char *field_id)
35 49 {
36 50 int i;
... ... @@ -108,6 +122,14 @@
108 122 return result;
109 123 }
110 124 return result;
  125 +}
  126 +
  127 +struct ima_template_desc *ima_template_desc_current(void)
  128 +{
  129 + if (!ima_template)
  130 + ima_template = lookup_template_desc(IMA_TEMPLATE_IMA_NAME);
  131 +
  132 + return ima_template;
111 133 }
112 134  
113 135 int ima_init_template(void)