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 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 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 struct ima_template_field *lookup_template_field(const char *field_id) 129 { 130 int i; 131 132 for (i = 0; i < ARRAY_SIZE(supported_fields); i++) 133 if (strncmp(supported_fields[i].field_id, field_id, 134 IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0) 135 return &supported_fields[i]; 136 return NULL; 137 } 138 139 static int template_fmt_size(const char *template_fmt) 140 { 141 char c; 142 int template_fmt_len = strlen(template_fmt); 143 int i = 0, j = 0; 144 145 while (i < template_fmt_len) { 146 c = template_fmt[i]; 147 if (c == '|') 148 j++; 149 i++; 150 } 151 152 return j + 1; 153 } 154 155 static int template_desc_init_fields(const char *template_fmt, 156 struct ima_template_field ***fields, 157 int *num_fields) 158 { 159 const char *template_fmt_ptr; 160 struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX]; 161 int template_num_fields; 162 int i, len; 163 164 if (num_fields && *num_fields > 0) /* already initialized? */ 165 return 0; 166 167 template_num_fields = template_fmt_size(template_fmt); 168 169 if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) { 170 pr_err("format string '%s' contains too many fields\n", 171 template_fmt); 172 return -EINVAL; 173 } 174 175 for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields; 176 i++, template_fmt_ptr += len + 1) { 177 char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1]; 178 179 len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr; 180 if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) { 181 pr_err("Invalid field with length %d\n", len); 182 return -EINVAL; 183 } 184 185 memcpy(tmp_field_id, template_fmt_ptr, len); 186 tmp_field_id[len] = '\0'; 187 found_fields[i] = lookup_template_field(tmp_field_id); 188 if (!found_fields[i]) { 189 pr_err("field '%s' not found\n", tmp_field_id); 190 return -ENOENT; 191 } 192 } 193 194 if (fields && num_fields) { 195 *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL); 196 if (*fields == NULL) 197 return -ENOMEM; 198 199 memcpy(*fields, found_fields, i * sizeof(*fields)); 200 *num_fields = i; 201 } 202 203 return 0; 204 } 205 206 void ima_init_template_list(void) 207 { 208 int i; 209 210 if (!list_empty(&defined_templates)) 211 return; 212 213 spin_lock(&template_list); 214 for (i = 0; i < ARRAY_SIZE(builtin_templates); i++) { 215 list_add_tail_rcu(&builtin_templates[i].list, 216 &defined_templates); 217 } 218 spin_unlock(&template_list); 219 } 220 221 struct ima_template_desc *ima_template_desc_current(void) 222 { 223 if (!ima_template) { 224 ima_init_template_list(); 225 ima_template = 226 lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE); 227 } 228 return ima_template; 229 } 230 231 int __init ima_init_template(void) 232 { 233 struct ima_template_desc *template = ima_template_desc_current(); 234 int result; 235 236 result = template_desc_init_fields(template->fmt, 237 &(template->fields), 238 &(template->num_fields)); 239 if (result < 0) 240 pr_err("template %s init failed, result: %d\n", 241 (strlen(template->name) ? 242 template->name : template->fmt), result); 243 244 return result; 245 } 246 247 static struct ima_template_desc *restore_template_fmt(char *template_name) 248 { 249 struct ima_template_desc *template_desc = NULL; 250 int ret; 251 252 ret = template_desc_init_fields(template_name, NULL, NULL); 253 if (ret < 0) { 254 pr_err("attempting to initialize the template \"%s\" failed\n", 255 template_name); 256 goto out; 257 } 258 259 template_desc = kzalloc(sizeof(*template_desc), GFP_KERNEL); 260 if (!template_desc) 261 goto out; 262 263 template_desc->name = ""; 264 template_desc->fmt = kstrdup(template_name, GFP_KERNEL); 265 if (!template_desc->fmt) 266 goto out; 267 268 spin_lock(&template_list); 269 list_add_tail_rcu(&template_desc->list, &defined_templates); 270 spin_unlock(&template_list); 271 out: 272 return template_desc; 273 } 274 275 static int ima_restore_template_data(struct ima_template_desc *template_desc, 276 void *template_data, 277 int template_data_size, 278 struct ima_template_entry **entry) 279 { 280 int ret = 0; 281 int i; 282 283 *entry = kzalloc(sizeof(**entry) + 284 template_desc->num_fields * sizeof(struct ima_field_data), 285 GFP_NOFS); 286 if (!*entry) 287 return -ENOMEM; 288 289 ret = ima_parse_buf(template_data, template_data + template_data_size, 290 NULL, template_desc->num_fields, 291 (*entry)->template_data, NULL, NULL, 292 ENFORCE_FIELDS | ENFORCE_BUFEND, "template data"); 293 if (ret < 0) { 294 kfree(*entry); 295 return ret; 296 } 297 298 (*entry)->template_desc = template_desc; 299 for (i = 0; i < template_desc->num_fields; i++) { 300 struct ima_field_data *field_data = &(*entry)->template_data[i]; 301 u8 *data = field_data->data; 302 303 (*entry)->template_data[i].data = 304 kzalloc(field_data->len + 1, GFP_KERNEL); 305 if (!(*entry)->template_data[i].data) { 306 ret = -ENOMEM; 307 break; 308 } 309 memcpy((*entry)->template_data[i].data, data, field_data->len); 310 (*entry)->template_data_len += sizeof(field_data->len); 311 (*entry)->template_data_len += field_data->len; 312 } 313 314 if (ret < 0) { 315 ima_free_template_entry(*entry); 316 *entry = NULL; 317 } 318 319 return ret; 320 } 321 322 /* Restore the serialized binary measurement list without extending PCRs. */ 323 int ima_restore_measurement_list(loff_t size, void *buf) 324 { 325 char template_name[MAX_TEMPLATE_NAME_LEN]; 326 327 struct ima_kexec_hdr *khdr = buf; 328 struct ima_field_data hdr[HDR__LAST] = { 329 [HDR_PCR] = {.len = sizeof(u32)}, 330 [HDR_DIGEST] = {.len = TPM_DIGEST_SIZE}, 331 }; 332 333 void *bufp = buf + sizeof(*khdr); 334 void *bufendp; 335 struct ima_template_entry *entry; 336 struct ima_template_desc *template_desc; 337 DECLARE_BITMAP(hdr_mask, HDR__LAST); 338 unsigned long count = 0; 339 int ret = 0; 340 341 if (!buf || size < sizeof(*khdr)) 342 return 0; 343 344 if (ima_canonical_fmt) { 345 khdr->version = le16_to_cpu(khdr->version); 346 khdr->count = le64_to_cpu(khdr->count); 347 khdr->buffer_size = le64_to_cpu(khdr->buffer_size); 348 } 349 350 if (khdr->version != 1) { 351 pr_err("attempting to restore a incompatible measurement list"); 352 return -EINVAL; 353 } 354 355 if (khdr->count > ULONG_MAX - 1) { 356 pr_err("attempting to restore too many measurements"); 357 return -EINVAL; 358 } 359 360 bitmap_zero(hdr_mask, HDR__LAST); 361 bitmap_set(hdr_mask, HDR_PCR, 1); 362 bitmap_set(hdr_mask, HDR_DIGEST, 1); 363 364 /* 365 * ima kexec buffer prefix: version, buffer size, count 366 * v1 format: pcr, digest, template-name-len, template-name, 367 * template-data-size, template-data 368 */ 369 bufendp = buf + khdr->buffer_size; 370 while ((bufp < bufendp) && (count++ < khdr->count)) { 371 int enforce_mask = ENFORCE_FIELDS; 372 373 enforce_mask |= (count == khdr->count) ? ENFORCE_BUFEND : 0; 374 ret = ima_parse_buf(bufp, bufendp, &bufp, HDR__LAST, hdr, NULL, 375 hdr_mask, enforce_mask, "entry header"); 376 if (ret < 0) 377 break; 378 379 if (hdr[HDR_TEMPLATE_NAME].len >= MAX_TEMPLATE_NAME_LEN) { 380 pr_err("attempting to restore a template name that is too long\n"); 381 ret = -EINVAL; 382 break; 383 } 384 385 /* template name is not null terminated */ 386 memcpy(template_name, hdr[HDR_TEMPLATE_NAME].data, 387 hdr[HDR_TEMPLATE_NAME].len); 388 template_name[hdr[HDR_TEMPLATE_NAME].len] = 0; 389 390 if (strcmp(template_name, "ima") == 0) { 391 pr_err("attempting to restore an unsupported template \"%s\" failed\n", 392 template_name); 393 ret = -EINVAL; 394 break; 395 } 396 397 template_desc = lookup_template_desc(template_name); 398 if (!template_desc) { 399 template_desc = restore_template_fmt(template_name); 400 if (!template_desc) 401 break; 402 } 403 404 /* 405 * Only the running system's template format is initialized 406 * on boot. As needed, initialize the other template formats. 407 */ 408 ret = template_desc_init_fields(template_desc->fmt, 409 &(template_desc->fields), 410 &(template_desc->num_fields)); 411 if (ret < 0) { 412 pr_err("attempting to restore the template fmt \"%s\" failed\n", 413 template_desc->fmt); 414 ret = -EINVAL; 415 break; 416 } 417 418 ret = ima_restore_template_data(template_desc, 419 hdr[HDR_TEMPLATE_DATA].data, 420 hdr[HDR_TEMPLATE_DATA].len, 421 &entry); 422 if (ret < 0) 423 break; 424 425 memcpy(entry->digest, hdr[HDR_DIGEST].data, 426 hdr[HDR_DIGEST].len); 427 entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) : 428 le32_to_cpu(*(hdr[HDR_PCR].data)); 429 ret = ima_restore_measurement_entry(entry); 430 if (ret < 0) 431 break; 432 433 } 434 return ret; 435 } 436