root/security/integrity/ima/ima_template.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ima_template_has_modsig
  2. ima_template_setup
  3. ima_template_fmt_setup
  4. lookup_template_desc
  5. lookup_template_field
  6. template_fmt_size
  7. template_desc_init_fields
  8. ima_init_template_list
  9. ima_template_desc_current
  10. ima_init_template
  11. restore_template_fmt
  12. ima_restore_template_data
  13. ima_restore_measurement_list

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

/* [<][>][^][v][top][bottom][index][help] */