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