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