ima: added support for new kernel cmdline parameter ima_template_fmt
authorRoberto Sassu <roberto.sassu@polito.it>
Mon, 13 Oct 2014 12:08:42 +0000 (14:08 +0200)
committerMimi Zohar <zohar@linux.vnet.ibm.com>
Mon, 13 Oct 2014 12:39:02 +0000 (08:39 -0400)
This patch allows users to provide a custom template format through the
new kernel command line parameter 'ima_template_fmt'. If the supplied
format is not valid, IMA uses the default template descriptor.

Changelog:
 - v3:
   - added check for 'fields' and 'num_fields' in
     template_desc_init_fields() (suggested by Mimi Zohar)

 - v2:
   - using template_desc_init_fields() to validate a format string
     (Roberto Sassu)
   - updated documentation by stating that only the chosen template
     descriptor is initialized (Roberto Sassu)

 - v1:
   - simplified code of ima_template_fmt_setup()
     (Roberto Sassu, suggested by Mimi Zohar)

Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Documentation/kernel-parameters.txt
Documentation/security/IMA-templates.txt
security/integrity/ima/ima_template.c

index 802a3fd9e4850fa05ae02d45fd772ce6bed02b95..06b2cd5739dddfea99719447480c39999234cdd7 100644 (file)
@@ -1318,6 +1318,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Formats: { "ima" | "ima-ng" }
                        Default: "ima-ng"
 
+       ima_template_fmt=
+                       [IMA] Define a custom template format.
+                       Format: { "field1|...|fieldN" }
+
        ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
                        Format: <min_file_size>
                        Set the minimal file size for using asynchronous hash.
index a4e102dddfea4cfec1698d55f0a39fea1b503e20..839b5dad922663b6e94bc0e5a8ebc55a96e08fb9 100644 (file)
@@ -27,25 +27,22 @@ Managing templates with these structures is very simple. To support
 a new data type, developers define the field identifier and implement
 two functions, init() and show(), respectively to generate and display
 measurement entries. Defining a new template descriptor requires
-specifying the template format, a string of field identifiers separated
-by the '|' character. While in the current implementation it is possible
-to define new template descriptors only by adding their definition in the
-template specific code (ima_template.c), in a future version it will be
-possible to register a new template on a running kernel by supplying to IMA
-the desired format string. In this version, IMA initializes at boot time
-all defined template descriptors by translating the format into an array
-of template fields structures taken from the set of the supported ones.
+specifying the template format (a string of field identifiers separated
+by the '|' character) through the 'ima_template_fmt' kernel command line
+parameter. At boot time, IMA initializes the chosen template descriptor
+by translating the format into an array of template fields structures taken
+from the set of the supported ones.
 
 After the initialization step, IMA will call ima_alloc_init_template()
 (new function defined within the patches for the new template management
 mechanism) to generate a new measurement entry by using the template
 descriptor chosen through the kernel configuration or through the newly
-introduced 'ima_template=' kernel command line parameter. It is during this
-phase that the advantages of the new architecture are clearly shown:
-the latter function will not contain specific code to handle a given template
-but, instead, it simply calls the init() method of the template fields
-associated to the chosen template descriptor and store the result (pointer
-to allocated data and data length) in the measurement entry structure.
+introduced 'ima_template' and 'ima_template_fmt' kernel command line parameters.
+It is during this phase that the advantages of the new architecture are
+clearly shown: the latter function will not contain specific code to handle
+a given template but, instead, it simply calls the init() method of the template
+fields associated to the chosen template descriptor and store the result
+(pointer to allocated data and data length) in the measurement entry structure.
 
 The same mechanism is employed to display measurements entries.
 The functions ima[_ascii]_measurements_show() retrieve, for each entry,
@@ -86,4 +83,6 @@ currently the following methods are supported:
  - select a template descriptor among those supported in the kernel
    configuration ('ima-ng' is the default choice);
  - specify a template descriptor name from the kernel command line through
-   the 'ima_template=' parameter.
+   the 'ima_template=' parameter;
+ - register a new template descriptor with custom format through the kernel
+   command line parameter 'ima_template_fmt='.
index 65117ba06809685b346476db20b4e358e96c2baf..0b7404ebfa80baf9a3741fa36f74aca5548f8405 100644 (file)
@@ -24,6 +24,7 @@ static struct ima_template_desc defined_templates[] = {
        {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
        {.name = "ima-ng", .fmt = "d-ng|n-ng"},
        {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
+       {.name = "", .fmt = ""},        /* placeholder for a custom format */
 };
 
 static struct ima_template_field supported_fields[] = {
@@ -41,12 +42,18 @@ static struct ima_template_field supported_fields[] = {
 
 static struct ima_template_desc *ima_template;
 static struct ima_template_desc *lookup_template_desc(const char *name);
+static int template_desc_init_fields(const char *template_fmt,
+                                    struct ima_template_field ***fields,
+                                    int *num_fields);
 
 static int __init ima_template_setup(char *str)
 {
        struct ima_template_desc *template_desc;
        int template_len = strlen(str);
 
+       if (ima_template)
+               return 1;
+
        /*
         * Verify that a template with the supplied name exists.
         * If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
@@ -73,6 +80,25 @@ static int __init ima_template_setup(char *str)
 }
 __setup("ima_template=", ima_template_setup);
 
+static int __init ima_template_fmt_setup(char *str)
+{
+       int num_templates = ARRAY_SIZE(defined_templates);
+
+       if (ima_template)
+               return 1;
+
+       if (template_desc_init_fields(str, NULL, NULL) < 0) {
+               pr_err("format string '%s' not valid, using template %s\n",
+                      str, CONFIG_IMA_DEFAULT_TEMPLATE);
+               return 1;
+       }
+
+       defined_templates[num_templates - 1].fmt = str;
+       ima_template = defined_templates + num_templates - 1;
+       return 1;
+}
+__setup("ima_template_fmt=", ima_template_fmt_setup);
+
 static struct ima_template_desc *lookup_template_desc(const char *name)
 {
        int i;
@@ -146,12 +172,15 @@ static int template_desc_init_fields(const char *template_fmt,
                }
        }
 
-       *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL);
-       if (*fields == NULL)
-               return -ENOMEM;
+       if (fields && num_fields) {
+               *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL);
+               if (*fields == NULL)
+                       return -ENOMEM;
+
+               memcpy(*fields, found_fields, i * sizeof(*fields));
+               *num_fields = i;
+       }
 
-       memcpy(*fields, found_fields, i * sizeof(*fields));
-       *num_fields = i;
        return 0;
 }