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