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