1 /* 2 * Copyright (C) 2013 Politecnico di Torino, Italy 3 * TORSEC group -- http://security.polito.it 4 * 5 * Author: Roberto Sassu <roberto.sassu@polito.it> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation, version 2 of the 10 * License. 11 * 12 * File: ima_template.c 13 * Helpers to manage template descriptors. 14 */ 15 16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17 18 #include <linux/rculist.h> 19 #include "ima.h" 20 #include "ima_template_lib.h" 21 22 enum header_fields { HDR_PCR, HDR_DIGEST, HDR_TEMPLATE_NAME, 23 HDR_TEMPLATE_DATA, HDR__LAST }; 24 25 static struct ima_template_desc builtin_templates[] = { 26 {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, 27 {.name = "ima-ng", .fmt = "d-ng|n-ng"}, 28 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, 29 {.name = "", .fmt = ""}, /* placeholder for a custom format */ 30 }; 31 32 static LIST_HEAD(defined_templates); 33 static DEFINE_SPINLOCK(template_list); 34 35 static const struct ima_template_field supported_fields[] = { 36 {.field_id = "d", .field_init = ima_eventdigest_init, 37 .field_show = ima_show_template_digest}, 38 {.field_id = "n", .field_init = ima_eventname_init, 39 .field_show = ima_show_template_string}, 40 {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init, 41 .field_show = ima_show_template_digest_ng}, 42 {.field_id = "n-ng", .field_init = ima_eventname_ng_init, 43 .field_show = ima_show_template_string}, 44 {.field_id = "sig", .field_init = ima_eventsig_init, 45 .field_show = ima_show_template_sig}, 46 }; 47 #define MAX_TEMPLATE_NAME_LEN 15 48 49 static struct ima_template_desc *ima_template; 50 static struct ima_template_desc *lookup_template_desc(const char *name); 51 static int template_desc_init_fields(const char *template_fmt, 52 const struct ima_template_field ***fields, 53 int *num_fields); 54 55 static int __init ima_template_setup(char *str) 56 { 57 struct ima_template_desc *template_desc; 58 int template_len = strlen(str); 59 60 if (ima_template) 61 return 1; 62 63 ima_init_template_list(); 64 65 /* 66 * Verify that a template with the supplied name exists. 67 * If not, use CONFIG_IMA_DEFAULT_TEMPLATE. 68 */ 69 template_desc = lookup_template_desc(str); 70 if (!template_desc) { 71 pr_err("template %s not found, using %s\n", 72 str, CONFIG_IMA_DEFAULT_TEMPLATE); 73 return 1; 74 } 75 76 /* 77 * Verify whether the current hash algorithm is supported 78 * by the 'ima' template. 79 */ 80 if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 && 81 ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) { 82 pr_err("template does not support hash alg\n"); 83 return 1; 84 } 85 86 ima_template = template_desc; 87 return 1; 88 } 89 __setup("ima_template=", ima_template_setup); 90 91 static int __init ima_template_fmt_setup(char *str) 92 { 93 int num_templates = ARRAY_SIZE(builtin_templates); 94 95 if (ima_template) 96 return 1; 97 98 if (template_desc_init_fields(str, NULL, NULL) < 0) { 99 pr_err("format string '%s' not valid, using template %s\n", 100 str, CONFIG_IMA_DEFAULT_TEMPLATE); 101 return 1; 102 } 103 104 builtin_templates[num_templates - 1].fmt = str; 105 ima_template = builtin_templates + num_templates - 1; 106 107 return 1; 108 } 109 __setup("ima_template_fmt=", ima_template_fmt_setup); 110 111 static struct ima_template_desc *lookup_template_desc(const char *name) 112 { 113 struct ima_template_desc *template_desc; 114 int found = 0; 115 116 rcu_read_lock(); 117 list_for_each_entry_rcu(template_desc, &defined_templates, list) { 118 if ((strcmp(template_desc->name, name) == 0) || 119 (strcmp(template_desc->fmt, name) == 0)) { 120 found = 1; 121 break; 122 } 123 } 124 rcu_read_unlock(); 125 return found ? template_desc : NULL; 126 } 127 128 static const struct ima_template_field * 129 lookup_template_field(const char *field_id) 130 { 131 int i; 132 133 for (i = 0; i < ARRAY_SIZE(supported_fields); i++) 134 if (strncmp(supported_fields[i].field_id, field_id, 135 IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0) 136 return &supported_fields[i]; 137 return NULL; 138 } 139 140 static int template_fmt_size(const char *template_fmt) 141 { 142 char c; 143 int template_fmt_len = strlen(template_fmt); 144 int i = 0, j = 0; 145 146 while (i < template_fmt_len) { 147 c = template_fmt[i]; 148 if (c == '|') 149 j++; 150 i++; 151 } 152 153 return j + 1; 154 } 155 156 static int template_desc_init_fields(const char *template_fmt, 157 const struct ima_template_field ***fields, 158 int *num_fields) 159 { 160 const char *template_fmt_ptr; 161 const struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX]; 162 int template_num_fields; 163 int i, len; 164 165 if (num_fields && *num_fields > 0) /* already initialized? */ 166 return 0; 167 168 template_num_fields = template_fmt_size(template_fmt); 169 170 if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) { 171 pr_err("format string '%s' contains too many fields\n", 172 template_fmt); 173 return -EINVAL; 174 } 175 176 for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields; 177 i++, template_fmt_ptr += len + 1) { 178 char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1]; 179 180 len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr; 181 if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) { 182 pr_err("Invalid field with length %d\n", len); 183 return -EINVAL; 184 } 185 186 memcpy(tmp_field_id, template_fmt_ptr, len); 187 tmp_field_id[len] = '\0'; 188 found_fields[i] = lookup_template_field(tmp_field_id); 189 if (!found_fields[i]) { 190 pr_err("field '%s' not found\n", tmp_field_id); 191 return -ENOENT; 192 } 193 } 194 195 if (fields && num_fields) { 196 *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL); 197 if (*fields == NULL) 198 return -ENOMEM; 199 200 memcpy(*fields, found_fields, i * sizeof(*fields)); 201 *num_fields = i; 202 } 203 204 return 0; 205 } 206 207 void ima_init_template_list(void) 208 { 209 int i; 210 211 if (!list_empty(&defined_templates)) 212 return; 213 214 spin_lock(&template_list); 215 for (i = 0; i < ARRAY_SIZE(builtin_templates); i++) { 216 list_add_tail_rcu(&builtin_templates[i].list, 217 &defined_templates); 218 } 219 spin_unlock(&template_list); 220 } 221 222 struct ima_template_desc *ima_template_desc_current(void) 223 { 224 if (!ima_template) { 225 ima_init_template_list(); 226 ima_template = 227 lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE); 228 } 229 return ima_template; 230 } 231 232 int __init ima_init_template(void) 233 { 234 struct ima_template_desc *template = ima_template_desc_current(); 235 int result; 236 237 result = template_desc_init_fields(template->fmt, 238 &(template->fields), 239 &(template->num_fields)); 240 if (result < 0) 241 pr_err("template %s init failed, result: %d\n", 242 (strlen(template->name) ? 243 template->name : template->fmt), result); 244 245 return result; 246 } 247 248 static struct ima_template_desc *restore_template_fmt(char *template_name) 249 { 250 struct ima_template_desc *template_desc = NULL; 251 int ret; 252 253 ret = template_desc_init_fields(template_name, NULL, NULL); 254 if (ret < 0) { 255 pr_err("attempting to initialize the template \"%s\" failed\n", 256 template_name); 257 goto out; 258 } 259 260 template_desc = kzalloc(sizeof(*template_desc), GFP_KERNEL); 261 if (!template_desc) 262 goto out; 263 264 template_desc->name = ""; 265 template_desc->fmt = kstrdup(template_name, GFP_KERNEL); 266 if (!template_desc->fmt) 267 goto out; 268 269 spin_lock(&template_list); 270 list_add_tail_rcu(&template_desc->list, &defined_templates); 271 spin_unlock(&template_list); 272 out: 273 return template_desc; 274 } 275 276 static int ima_restore_template_data(struct ima_template_desc *template_desc, 277 void *template_data, 278 int template_data_size, 279 struct ima_template_entry **entry) 280 { 281 int ret = 0; 282 int i; 283 284 *entry = kzalloc(sizeof(**entry) + 285 template_desc->num_fields * sizeof(struct ima_field_data), 286 GFP_NOFS); 287 if (!*entry) 288 return -ENOMEM; 289 290 ret = ima_parse_buf(template_data, template_data + template_data_size, 291 NULL, template_desc->num_fields, 292 (*entry)->template_data, NULL, NULL, 293 ENFORCE_FIELDS | ENFORCE_BUFEND, "template data"); 294 if (ret < 0) { 295 kfree(*entry); 296 return ret; 297 } 298 299 (*entry)->template_desc = template_desc; 300 for (i = 0; i < template_desc->num_fields; i++) { 301 struct ima_field_data *field_data = &(*entry)->template_data[i]; 302 u8 *data = field_data->data; 303 304 (*entry)->template_data[i].data = 305 kzalloc(field_data->len + 1, GFP_KERNEL); 306 if (!(*entry)->template_data[i].data) { 307 ret = -ENOMEM; 308 break; 309 } 310 memcpy((*entry)->template_data[i].data, data, field_data->len); 311 (*entry)->template_data_len += sizeof(field_data->len); 312 (*entry)->template_data_len += field_data->len; 313 } 314 315 if (ret < 0) { 316 ima_free_template_entry(*entry); 317 *entry = NULL; 318 } 319 320 return ret; 321 } 322 323 /* Restore the serialized binary measurement list without extending PCRs. */ 324 int ima_restore_measurement_list(loff_t size, void *buf) 325 { 326 char template_name[MAX_TEMPLATE_NAME_LEN]; 327 328 struct ima_kexec_hdr *khdr = buf; 329 struct ima_field_data hdr[HDR__LAST] = { 330 [HDR_PCR] = {.len = sizeof(u32)}, 331 [HDR_DIGEST] = {.len = TPM_DIGEST_SIZE}, 332 }; 333 334 void *bufp = buf + sizeof(*khdr); 335 void *bufendp; 336 struct ima_template_entry *entry; 337 struct ima_template_desc *template_desc; 338 DECLARE_BITMAP(hdr_mask, HDR__LAST); 339 unsigned long count = 0; 340 int ret = 0; 341 342 if (!buf || size < sizeof(*khdr)) 343 return 0; 344 345 if (ima_canonical_fmt) { 346 khdr->version = le16_to_cpu(khdr->version); 347 khdr->count = le64_to_cpu(khdr->count); 348 khdr->buffer_size = le64_to_cpu(khdr->buffer_size); 349 } 350 351 if (khdr->version != 1) { 352 pr_err("attempting to restore a incompatible measurement list"); 353 return -EINVAL; 354 } 355 356 if (khdr->count > ULONG_MAX - 1) { 357 pr_err("attempting to restore too many measurements"); 358 return -EINVAL; 359 } 360 361 bitmap_zero(hdr_mask, HDR__LAST); 362 bitmap_set(hdr_mask, HDR_PCR, 1); 363 bitmap_set(hdr_mask, HDR_DIGEST, 1); 364 365 /* 366 * ima kexec buffer prefix: version, buffer size, count 367 * v1 format: pcr, digest, template-name-len, template-name, 368 * template-data-size, template-data 369 */ 370 bufendp = buf + khdr->buffer_size; 371 while ((bufp < bufendp) && (count++ < khdr->count)) { 372 int enforce_mask = ENFORCE_FIELDS; 373 374 enforce_mask |= (count == khdr->count) ? ENFORCE_BUFEND : 0; 375 ret = ima_parse_buf(bufp, bufendp, &bufp, HDR__LAST, hdr, NULL, 376 hdr_mask, enforce_mask, "entry header"); 377 if (ret < 0) 378 break; 379 380 if (hdr[HDR_TEMPLATE_NAME].len >= MAX_TEMPLATE_NAME_LEN) { 381 pr_err("attempting to restore a template name that is too long\n"); 382 ret = -EINVAL; 383 break; 384 } 385 386 /* template name is not null terminated */ 387 memcpy(template_name, hdr[HDR_TEMPLATE_NAME].data, 388 hdr[HDR_TEMPLATE_NAME].len); 389 template_name[hdr[HDR_TEMPLATE_NAME].len] = 0; 390 391 if (strcmp(template_name, "ima") == 0) { 392 pr_err("attempting to restore an unsupported template \"%s\" failed\n", 393 template_name); 394 ret = -EINVAL; 395 break; 396 } 397 398 template_desc = lookup_template_desc(template_name); 399 if (!template_desc) { 400 template_desc = restore_template_fmt(template_name); 401 if (!template_desc) 402 break; 403 } 404 405 /* 406 * Only the running system's template format is initialized 407 * on boot. As needed, initialize the other template formats. 408 */ 409 ret = template_desc_init_fields(template_desc->fmt, 410 &(template_desc->fields), 411 &(template_desc->num_fields)); 412 if (ret < 0) { 413 pr_err("attempting to restore the template fmt \"%s\" failed\n", 414 template_desc->fmt); 415 ret = -EINVAL; 416 break; 417 } 418 419 ret = ima_restore_template_data(template_desc, 420 hdr[HDR_TEMPLATE_DATA].data, 421 hdr[HDR_TEMPLATE_DATA].len, 422 &entry); 423 if (ret < 0) 424 break; 425 426 memcpy(entry->digest, hdr[HDR_DIGEST].data, 427 hdr[HDR_DIGEST].len); 428 entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) : 429 le32_to_cpu(*(hdr[HDR_PCR].data)); 430 ret = ima_restore_measurement_entry(entry); 431 if (ret < 0) 432 break; 433 434 } 435 return ret; 436 } 437