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 "ima.h" 19 #include "ima_template_lib.h" 20 21 static struct ima_template_desc defined_templates[] = { 22 {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, 23 {.name = "ima-ng", .fmt = "d-ng|n-ng"}, 24 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, 25 {.name = "", .fmt = ""}, /* placeholder for a custom format */ 26 }; 27 28 static struct ima_template_field supported_fields[] = { 29 {.field_id = "d", .field_init = ima_eventdigest_init, 30 .field_show = ima_show_template_digest}, 31 {.field_id = "n", .field_init = ima_eventname_init, 32 .field_show = ima_show_template_string}, 33 {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init, 34 .field_show = ima_show_template_digest_ng}, 35 {.field_id = "n-ng", .field_init = ima_eventname_ng_init, 36 .field_show = ima_show_template_string}, 37 {.field_id = "sig", .field_init = ima_eventsig_init, 38 .field_show = ima_show_template_sig}, 39 }; 40 41 static struct ima_template_desc *ima_template; 42 static struct ima_template_desc *lookup_template_desc(const char *name); 43 static int template_desc_init_fields(const char *template_fmt, 44 struct ima_template_field ***fields, 45 int *num_fields); 46 47 static int __init ima_template_setup(char *str) 48 { 49 struct ima_template_desc *template_desc; 50 int template_len = strlen(str); 51 52 if (ima_template) 53 return 1; 54 55 /* 56 * Verify that a template with the supplied name exists. 57 * If not, use CONFIG_IMA_DEFAULT_TEMPLATE. 58 */ 59 template_desc = lookup_template_desc(str); 60 if (!template_desc) { 61 pr_err("template %s not found, using %s\n", 62 str, CONFIG_IMA_DEFAULT_TEMPLATE); 63 return 1; 64 } 65 66 /* 67 * Verify whether the current hash algorithm is supported 68 * by the 'ima' template. 69 */ 70 if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 && 71 ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) { 72 pr_err("template does not support hash alg\n"); 73 return 1; 74 } 75 76 ima_template = template_desc; 77 return 1; 78 } 79 __setup("ima_template=", ima_template_setup); 80 81 static int __init ima_template_fmt_setup(char *str) 82 { 83 int num_templates = ARRAY_SIZE(defined_templates); 84 85 if (ima_template) 86 return 1; 87 88 if (template_desc_init_fields(str, NULL, NULL) < 0) { 89 pr_err("format string '%s' not valid, using template %s\n", 90 str, CONFIG_IMA_DEFAULT_TEMPLATE); 91 return 1; 92 } 93 94 defined_templates[num_templates - 1].fmt = str; 95 ima_template = defined_templates + num_templates - 1; 96 return 1; 97 } 98 __setup("ima_template_fmt=", ima_template_fmt_setup); 99 100 static struct ima_template_desc *lookup_template_desc(const char *name) 101 { 102 int i; 103 104 for (i = 0; i < ARRAY_SIZE(defined_templates); i++) { 105 if (strcmp(defined_templates[i].name, name) == 0) 106 return defined_templates + i; 107 } 108 109 return NULL; 110 } 111 112 static struct ima_template_field *lookup_template_field(const char *field_id) 113 { 114 int i; 115 116 for (i = 0; i < ARRAY_SIZE(supported_fields); i++) 117 if (strncmp(supported_fields[i].field_id, field_id, 118 IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0) 119 return &supported_fields[i]; 120 return NULL; 121 } 122 123 static int template_fmt_size(const char *template_fmt) 124 { 125 char c; 126 int template_fmt_len = strlen(template_fmt); 127 int i = 0, j = 0; 128 129 while (i < template_fmt_len) { 130 c = template_fmt[i]; 131 if (c == '|') 132 j++; 133 i++; 134 } 135 136 return j + 1; 137 } 138 139 static int template_desc_init_fields(const char *template_fmt, 140 struct ima_template_field ***fields, 141 int *num_fields) 142 { 143 const char *template_fmt_ptr; 144 struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX]; 145 int template_num_fields = template_fmt_size(template_fmt); 146 int i, len; 147 148 if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) { 149 pr_err("format string '%s' contains too many fields\n", 150 template_fmt); 151 return -EINVAL; 152 } 153 154 for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields; 155 i++, template_fmt_ptr += len + 1) { 156 char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1]; 157 158 len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr; 159 if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) { 160 pr_err("Invalid field with length %d\n", len); 161 return -EINVAL; 162 } 163 164 memcpy(tmp_field_id, template_fmt_ptr, len); 165 tmp_field_id[len] = '\0'; 166 found_fields[i] = lookup_template_field(tmp_field_id); 167 if (!found_fields[i]) { 168 pr_err("field '%s' not found\n", tmp_field_id); 169 return -ENOENT; 170 } 171 } 172 173 if (fields && num_fields) { 174 *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL); 175 if (*fields == NULL) 176 return -ENOMEM; 177 178 memcpy(*fields, found_fields, i * sizeof(*fields)); 179 *num_fields = i; 180 } 181 182 return 0; 183 } 184 185 struct ima_template_desc *ima_template_desc_current(void) 186 { 187 if (!ima_template) 188 ima_template = 189 lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE); 190 return ima_template; 191 } 192 193 int __init ima_init_template(void) 194 { 195 struct ima_template_desc *template = ima_template_desc_current(); 196 int result; 197 198 result = template_desc_init_fields(template->fmt, 199 &(template->fields), 200 &(template->num_fields)); 201 if (result < 0) 202 pr_err("template %s init failed, result: %d\n", 203 (strlen(template->name) ? 204 template->name : template->fmt), result); 205 206 return result; 207 } 208