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 <crypto/hash_info.h>
  19
  20#include "ima.h"
  21#include "ima_template_lib.h"
  22
  23static struct ima_template_desc defined_templates[] = {
  24        {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
  25        {.name = "ima-ng", .fmt = "d-ng|n-ng"},
  26        {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
  27        {.name = "", .fmt = ""},        /* placeholder for a custom format */
  28};
  29
  30static struct ima_template_field supported_fields[] = {
  31        {.field_id = "d", .field_init = ima_eventdigest_init,
  32         .field_show = ima_show_template_digest},
  33        {.field_id = "n", .field_init = ima_eventname_init,
  34         .field_show = ima_show_template_string},
  35        {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
  36         .field_show = ima_show_template_digest_ng},
  37        {.field_id = "n-ng", .field_init = ima_eventname_ng_init,
  38         .field_show = ima_show_template_string},
  39        {.field_id = "sig", .field_init = ima_eventsig_init,
  40         .field_show = ima_show_template_sig},
  41};
  42
  43static struct ima_template_desc *ima_template;
  44static struct ima_template_desc *lookup_template_desc(const char *name);
  45static int template_desc_init_fields(const char *template_fmt,
  46                                     struct ima_template_field ***fields,
  47                                     int *num_fields);
  48
  49static int __init ima_template_setup(char *str)
  50{
  51        struct ima_template_desc *template_desc;
  52        int template_len = strlen(str);
  53
  54        if (ima_template)
  55                return 1;
  56
  57        /*
  58         * Verify that a template with the supplied name exists.
  59         * If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
  60         */
  61        template_desc = lookup_template_desc(str);
  62        if (!template_desc) {
  63                pr_err("template %s not found, using %s\n",
  64                       str, CONFIG_IMA_DEFAULT_TEMPLATE);
  65                return 1;
  66        }
  67
  68        /*
  69         * Verify whether the current hash algorithm is supported
  70         * by the 'ima' template.
  71         */
  72        if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
  73            ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
  74                pr_err("template does not support hash alg\n");
  75                return 1;
  76        }
  77
  78        ima_template = template_desc;
  79        return 1;
  80}
  81__setup("ima_template=", ima_template_setup);
  82
  83static int __init ima_template_fmt_setup(char *str)
  84{
  85        int num_templates = ARRAY_SIZE(defined_templates);
  86
  87        if (ima_template)
  88                return 1;
  89
  90        if (template_desc_init_fields(str, NULL, NULL) < 0) {
  91                pr_err("format string '%s' not valid, using template %s\n",
  92                       str, CONFIG_IMA_DEFAULT_TEMPLATE);
  93                return 1;
  94        }
  95
  96        defined_templates[num_templates - 1].fmt = str;
  97        ima_template = defined_templates + num_templates - 1;
  98        return 1;
  99}
 100__setup("ima_template_fmt=", ima_template_fmt_setup);
 101
 102static struct ima_template_desc *lookup_template_desc(const char *name)
 103{
 104        int i;
 105
 106        for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
 107                if (strcmp(defined_templates[i].name, name) == 0)
 108                        return defined_templates + i;
 109        }
 110
 111        return NULL;
 112}
 113
 114static struct ima_template_field *lookup_template_field(const char *field_id)
 115{
 116        int i;
 117
 118        for (i = 0; i < ARRAY_SIZE(supported_fields); i++)
 119                if (strncmp(supported_fields[i].field_id, field_id,
 120                            IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0)
 121                        return &supported_fields[i];
 122        return NULL;
 123}
 124
 125static int template_fmt_size(const char *template_fmt)
 126{
 127        char c;
 128        int template_fmt_len = strlen(template_fmt);
 129        int i = 0, j = 0;
 130
 131        while (i < template_fmt_len) {
 132                c = template_fmt[i];
 133                if (c == '|')
 134                        j++;
 135                i++;
 136        }
 137
 138        return j + 1;
 139}
 140
 141static int template_desc_init_fields(const char *template_fmt,
 142                                     struct ima_template_field ***fields,
 143                                     int *num_fields)
 144{
 145        const char *template_fmt_ptr;
 146        struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];
 147        int template_num_fields = template_fmt_size(template_fmt);
 148        int i, len;
 149
 150        if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) {
 151                pr_err("format string '%s' contains too many fields\n",
 152                       template_fmt);
 153                return -EINVAL;
 154        }
 155
 156        for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields;
 157             i++, template_fmt_ptr += len + 1) {
 158                char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1];
 159
 160                len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr;
 161                if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) {
 162                        pr_err("Invalid field with length %d\n", len);
 163                        return -EINVAL;
 164                }
 165
 166                memcpy(tmp_field_id, template_fmt_ptr, len);
 167                tmp_field_id[len] = '\0';
 168                found_fields[i] = lookup_template_field(tmp_field_id);
 169                if (!found_fields[i]) {
 170                        pr_err("field '%s' not found\n", tmp_field_id);
 171                        return -ENOENT;
 172                }
 173        }
 174
 175        if (fields && num_fields) {
 176                *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL);
 177                if (*fields == NULL)
 178                        return -ENOMEM;
 179
 180                memcpy(*fields, found_fields, i * sizeof(*fields));
 181                *num_fields = i;
 182        }
 183
 184        return 0;
 185}
 186
 187struct ima_template_desc *ima_template_desc_current(void)
 188{
 189        if (!ima_template)
 190                ima_template =
 191                    lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE);
 192        return ima_template;
 193}
 194
 195int __init ima_init_template(void)
 196{
 197        struct ima_template_desc *template = ima_template_desc_current();
 198        int result;
 199
 200        result = template_desc_init_fields(template->fmt,
 201                                           &(template->fields),
 202                                           &(template->num_fields));
 203        if (result < 0)
 204                pr_err("template %s init failed, result: %d\n",
 205                       (strlen(template->name) ?
 206                       template->name : template->fmt), result);
 207
 208        return result;
 209}
 210