linux/security/integrity/ima/ima_template.c

436 lines
11 KiB
C
Raw Normal View History

ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
/*
* Copyright (C) 2013 Politecnico di Torino, Italy
* TORSEC group -- http://security.polito.it
*
* Author: Roberto Sassu <roberto.sassu@polito.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* File: ima_template.c
* Helpers to manage template descriptors.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/rculist.h>
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
#include "ima.h"
#include "ima_template_lib.h"
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
enum header_fields { HDR_PCR, HDR_DIGEST, HDR_TEMPLATE_NAME,
HDR_TEMPLATE_DATA, HDR__LAST };
static struct ima_template_desc builtin_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 */
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
};
static LIST_HEAD(defined_templates);
static DEFINE_SPINLOCK(template_list);
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
static struct ima_template_field supported_fields[] = {
{.field_id = "d", .field_init = ima_eventdigest_init,
.field_show = ima_show_template_digest},
{.field_id = "n", .field_init = ima_eventname_init,
.field_show = ima_show_template_string},
{.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
.field_show = ima_show_template_digest_ng},
{.field_id = "n-ng", .field_init = ima_eventname_ng_init,
.field_show = ima_show_template_string},
{.field_id = "sig", .field_init = ima_eventsig_init,
.field_show = ima_show_template_sig},
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
};
#define MAX_TEMPLATE_NAME_LEN 15
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
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;
ima_init_template_list();
/*
* Verify that a template with the supplied name exists.
* If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
*/
template_desc = lookup_template_desc(str);
if (!template_desc) {
pr_err("template %s not found, using %s\n",
str, CONFIG_IMA_DEFAULT_TEMPLATE);
return 1;
}
/*
* Verify whether the current hash algorithm is supported
* by the 'ima' template.
*/
if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
pr_err("template does not support hash alg\n");
return 1;
}
ima_template = template_desc;
return 1;
}
__setup("ima_template=", ima_template_setup);
static int __init ima_template_fmt_setup(char *str)
{
int num_templates = ARRAY_SIZE(builtin_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;
}
builtin_templates[num_templates - 1].fmt = str;
ima_template = builtin_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)
{
struct ima_template_desc *template_desc;
int found = 0;
rcu_read_lock();
list_for_each_entry_rcu(template_desc, &defined_templates, list) {
if ((strcmp(template_desc->name, name) == 0) ||
(strcmp(template_desc->fmt, name) == 0)) {
found = 1;
break;
}
}
rcu_read_unlock();
return found ? template_desc : NULL;
}
static struct ima_template_field *lookup_template_field(const char *field_id)
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
{
int i;
for (i = 0; i < ARRAY_SIZE(supported_fields); i++)
if (strncmp(supported_fields[i].field_id, field_id,
IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0)
return &supported_fields[i];
return NULL;
}
ima: make a copy of template_fmt in template_desc_init_fields() This patch makes a copy of the 'template_fmt' function argument so that the latter will not be modified by strsep(), which does the splitting by replacing the given separator with '\0'.  IMA: No TPM chip found, activating TPM-bypass!  Unable to handle kernel pointer dereference at virtual kernel address 0000000000842000  Oops: 0004 [#1] SMP  Modules linked in:  CPU: 3 PID: 1 Comm: swapper/0 Not tainted 3.12.0-rc2-00098-g3ce1217d6cd5 #17  task: 000000003ffa0000 ti: 000000003ff84000 task.ti: 000000003ff84000  Krnl PSW : 0704e00180000000 000000000044bf88 (strsep+0x7c/0xa0)             R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0 EA:3  Krnl GPRS: 000000000000007c 000000000000007c 000000003ff87d90 0000000000821fd8             0000000000000000 000000000000007c 0000000000aa37e0 0000000000aa9008             0000000000000051 0000000000a114d8 0000000100000002 0000000000842bde             0000000000842bdf 00000000006f97f0 000000000040062c 000000003ff87cf0  Krnl Code: 000000000044bf7c: a7f4000a           brc     15,44bf90             000000000044bf80: b90200cc           ltgr    %r12,%r12            #000000000044bf84: a7840006           brc     8,44bf90            >000000000044bf88: 9200c000           mvi     0(%r12),0             000000000044bf8c: 41c0c001           la      %r12,1(%r12)             000000000044bf90: e3c020000024       stg     %r12,0(%r2)             000000000044bf96: b904002b           lgr     %r2,%r11             000000000044bf9a: ebbcf0700004       lmg     %r11,%r12,112(%r15)  Call Trace:  ([<00000000004005fe>] ima_init_template+0xa2/0x1bc)   [<0000000000a7c896>] ima_init+0x7a/0xa8   [<0000000000a7c938>] init_ima+0x24/0x40   [<00000000001000e8>] do_one_initcall+0x68/0x128   [<0000000000a4eb56>] kernel_init_freeable+0x20a/0x2b4   [<00000000006a1ff4>] kernel_init+0x30/0x178   [<00000000006b69fe>] kernel_thread_starter+0x6/0xc   [<00000000006b69f8>] kernel_thread_starter+0x0/0xc  Last Breaking-Event-Address:   [<000000000044bf42>] strsep+0x36/0xa0 Fixes commit: adf53a7 ima: new templates management mechanism Changelog v1: - make template_fmt 'const char *' (reported-by James Morris) - fix kstrdup memory leak (reported-by James Morris) Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Tested-by: Heiko Carstens <heiko.carstens@de.ibm.com>
2013-11-25 19:18:52 +00:00
static int template_fmt_size(const char *template_fmt)
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
{
char c;
int template_fmt_len = strlen(template_fmt);
int i = 0, j = 0;
while (i < template_fmt_len) {
c = template_fmt[i];
if (c == '|')
j++;
i++;
}
return j + 1;
}
ima: make a copy of template_fmt in template_desc_init_fields() This patch makes a copy of the 'template_fmt' function argument so that the latter will not be modified by strsep(), which does the splitting by replacing the given separator with '\0'.  IMA: No TPM chip found, activating TPM-bypass!  Unable to handle kernel pointer dereference at virtual kernel address 0000000000842000  Oops: 0004 [#1] SMP  Modules linked in:  CPU: 3 PID: 1 Comm: swapper/0 Not tainted 3.12.0-rc2-00098-g3ce1217d6cd5 #17  task: 000000003ffa0000 ti: 000000003ff84000 task.ti: 000000003ff84000  Krnl PSW : 0704e00180000000 000000000044bf88 (strsep+0x7c/0xa0)             R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0 EA:3  Krnl GPRS: 000000000000007c 000000000000007c 000000003ff87d90 0000000000821fd8             0000000000000000 000000000000007c 0000000000aa37e0 0000000000aa9008             0000000000000051 0000000000a114d8 0000000100000002 0000000000842bde             0000000000842bdf 00000000006f97f0 000000000040062c 000000003ff87cf0  Krnl Code: 000000000044bf7c: a7f4000a           brc     15,44bf90             000000000044bf80: b90200cc           ltgr    %r12,%r12            #000000000044bf84: a7840006           brc     8,44bf90            >000000000044bf88: 9200c000           mvi     0(%r12),0             000000000044bf8c: 41c0c001           la      %r12,1(%r12)             000000000044bf90: e3c020000024       stg     %r12,0(%r2)             000000000044bf96: b904002b           lgr     %r2,%r11             000000000044bf9a: ebbcf0700004       lmg     %r11,%r12,112(%r15)  Call Trace:  ([<00000000004005fe>] ima_init_template+0xa2/0x1bc)   [<0000000000a7c896>] ima_init+0x7a/0xa8   [<0000000000a7c938>] init_ima+0x24/0x40   [<00000000001000e8>] do_one_initcall+0x68/0x128   [<0000000000a4eb56>] kernel_init_freeable+0x20a/0x2b4   [<00000000006a1ff4>] kernel_init+0x30/0x178   [<00000000006b69fe>] kernel_thread_starter+0x6/0xc   [<00000000006b69f8>] kernel_thread_starter+0x0/0xc  Last Breaking-Event-Address:   [<000000000044bf42>] strsep+0x36/0xa0 Fixes commit: adf53a7 ima: new templates management mechanism Changelog v1: - make template_fmt 'const char *' (reported-by James Morris) - fix kstrdup memory leak (reported-by James Morris) Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Tested-by: Heiko Carstens <heiko.carstens@de.ibm.com>
2013-11-25 19:18:52 +00:00
static int template_desc_init_fields(const char *template_fmt,
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
struct ima_template_field ***fields,
int *num_fields)
{
const char *template_fmt_ptr;
struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];
int template_num_fields;
int i, len;
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
if (num_fields && *num_fields > 0) /* already initialized? */
return 0;
template_num_fields = template_fmt_size(template_fmt);
if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) {
pr_err("format string '%s' contains too many fields\n",
template_fmt);
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
return -EINVAL;
}
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields;
i++, template_fmt_ptr += len + 1) {
char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1];
len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr;
if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) {
pr_err("Invalid field with length %d\n", len);
return -EINVAL;
}
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
memcpy(tmp_field_id, template_fmt_ptr, len);
tmp_field_id[len] = '\0';
found_fields[i] = lookup_template_field(tmp_field_id);
if (!found_fields[i]) {
pr_err("field '%s' not found\n", tmp_field_id);
return -ENOENT;
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
}
}
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;
}
return 0;
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
}
void ima_init_template_list(void)
{
int i;
if (!list_empty(&defined_templates))
return;
spin_lock(&template_list);
for (i = 0; i < ARRAY_SIZE(builtin_templates); i++) {
list_add_tail_rcu(&builtin_templates[i].list,
&defined_templates);
}
spin_unlock(&template_list);
}
struct ima_template_desc *ima_template_desc_current(void)
{
if (!ima_template) {
ima_init_template_list();
ima_template =
lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE);
}
return ima_template;
}
int __init ima_init_template(void)
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
{
struct ima_template_desc *template = ima_template_desc_current();
int result;
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
result = template_desc_init_fields(template->fmt,
&(template->fields),
&(template->num_fields));
if (result < 0)
pr_err("template %s init failed, result: %d\n",
(strlen(template->name) ?
template->name : template->fmt), result);
return result;
ima: new templates management mechanism The original 'ima' template is fixed length, containing the filedata hash and pathname. The filedata hash is limited to 20 bytes (md5/sha1). The pathname is a null terminated string, limited to 255 characters. To overcome these limitations and to add additional file metadata, it is necessary to extend the current version of IMA by defining additional templates. The main reason to introduce this feature is that, each time a new template is defined, the functions that generate and display the measurement list would include the code for handling a new format and, thus, would significantly grow over time. This patch set solves this problem by separating the template management from the remaining IMA code. The core of this solution is the definition of two new data structures: a template descriptor, to determine which information should be included in the measurement list, and a template field, to generate and display data of a given type. To define a new template field, developers define the field identifier and implement two functions, init() and show(), respectively to generate and display measurement entries. Initially, this patch set defines the following template fields (support for additional data types will be added later):  - 'd': the digest of the event (i.e. the digest of a measured file),         calculated with the SHA1 or MD5 hash algorithm;  - 'n': the name of the event (i.e. the file name), with size up to         255 bytes;  - 'd-ng': the digest of the event, calculated with an arbitrary hash            algorithm (field format: [<hash algo>:]digest, where the digest            prefix is shown only if the hash algorithm is not SHA1 or MD5);  - 'n-ng': the name of the event, without size limitations. Defining a new template descriptor requires specifying the template format, a string of field identifiers separated by the '|' character. This patch set defines the following template descriptors:  - "ima": its format is 'd|n';  - "ima-ng" (default): its format is 'd-ng|n-ng' Further details about the new template architecture can be found in Documentation/security/IMA-templates.txt. Changelog: - don't defer calling ima_init_template() - Mimi - don't define ima_lookup_template_desc() until used - Mimi - squashed with documentation patch - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2013-06-07 10:16:29 +00:00
}
static struct ima_template_desc *restore_template_fmt(char *template_name)
{
struct ima_template_desc *template_desc = NULL;
int ret;
ret = template_desc_init_fields(template_name, NULL, NULL);
if (ret < 0) {
pr_err("attempting to initialize the template \"%s\" failed\n",
template_name);
goto out;
}
template_desc = kzalloc(sizeof(*template_desc), GFP_KERNEL);
if (!template_desc)
goto out;
template_desc->name = "";
template_desc->fmt = kstrdup(template_name, GFP_KERNEL);
if (!template_desc->fmt)
goto out;
spin_lock(&template_list);
list_add_tail_rcu(&template_desc->list, &defined_templates);
spin_unlock(&template_list);
out:
return template_desc;
}
static int ima_restore_template_data(struct ima_template_desc *template_desc,
void *template_data,
int template_data_size,
struct ima_template_entry **entry)
{
int ret = 0;
int i;
*entry = kzalloc(sizeof(**entry) +
template_desc->num_fields * sizeof(struct ima_field_data),
GFP_NOFS);
if (!*entry)
return -ENOMEM;
ret = ima_parse_buf(template_data, template_data + template_data_size,
NULL, template_desc->num_fields,
(*entry)->template_data, NULL, NULL,
ENFORCE_FIELDS | ENFORCE_BUFEND, "template data");
if (ret < 0) {
kfree(*entry);
return ret;
}
(*entry)->template_desc = template_desc;
for (i = 0; i < template_desc->num_fields; i++) {
struct ima_field_data *field_data = &(*entry)->template_data[i];
u8 *data = field_data->data;
(*entry)->template_data[i].data =
kzalloc(field_data->len + 1, GFP_KERNEL);
if (!(*entry)->template_data[i].data) {
ret = -ENOMEM;
break;
}
memcpy((*entry)->template_data[i].data, data, field_data->len);
(*entry)->template_data_len += sizeof(field_data->len);
(*entry)->template_data_len += field_data->len;
}
if (ret < 0) {
ima_free_template_entry(*entry);
*entry = NULL;
}
return ret;
}
/* Restore the serialized binary measurement list without extending PCRs. */
int ima_restore_measurement_list(loff_t size, void *buf)
{
char template_name[MAX_TEMPLATE_NAME_LEN];
struct ima_kexec_hdr *khdr = buf;
struct ima_field_data hdr[HDR__LAST] = {
[HDR_PCR] = {.len = sizeof(u32)},
[HDR_DIGEST] = {.len = TPM_DIGEST_SIZE},
};
void *bufp = buf + sizeof(*khdr);
ima: define a canonical binary_runtime_measurements list format The IMA binary_runtime_measurements list is currently in platform native format. To allow restoring a measurement list carried across kexec with a different endianness than the targeted kernel, this patch defines little-endian as the canonical format. For big endian systems wanting to save/restore the measurement list from a system with a different endianness, a new boot command line parameter named "ima_canonical_fmt" is defined. Considerations: use of the "ima_canonical_fmt" boot command line option will break existing userspace applications on big endian systems expecting the binary_runtime_measurements list to be in platform native format. Link: http://lkml.kernel.org/r/1480554346-29071-10-git-send-email-zohar@linux.vnet.ibm.com Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Acked-by: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Andreas Steffen <andreas.steffen@strongswan.org> Cc: Josh Sklar <sklar@linux.vnet.ibm.com> Cc: Dave Young <dyoung@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Stewart Smith <stewart@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-12-20 00:22:57 +00:00
void *bufendp;
struct ima_template_entry *entry;
struct ima_template_desc *template_desc;
DECLARE_BITMAP(hdr_mask, HDR__LAST);
unsigned long count = 0;
int ret = 0;
if (!buf || size < sizeof(*khdr))
return 0;
ima: define a canonical binary_runtime_measurements list format The IMA binary_runtime_measurements list is currently in platform native format. To allow restoring a measurement list carried across kexec with a different endianness than the targeted kernel, this patch defines little-endian as the canonical format. For big endian systems wanting to save/restore the measurement list from a system with a different endianness, a new boot command line parameter named "ima_canonical_fmt" is defined. Considerations: use of the "ima_canonical_fmt" boot command line option will break existing userspace applications on big endian systems expecting the binary_runtime_measurements list to be in platform native format. Link: http://lkml.kernel.org/r/1480554346-29071-10-git-send-email-zohar@linux.vnet.ibm.com Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Acked-by: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Andreas Steffen <andreas.steffen@strongswan.org> Cc: Josh Sklar <sklar@linux.vnet.ibm.com> Cc: Dave Young <dyoung@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Stewart Smith <stewart@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-12-20 00:22:57 +00:00
if (ima_canonical_fmt) {
khdr->version = le16_to_cpu(khdr->version);
khdr->count = le64_to_cpu(khdr->count);
khdr->buffer_size = le64_to_cpu(khdr->buffer_size);
}
if (khdr->version != 1) {
pr_err("attempting to restore a incompatible measurement list");
return -EINVAL;
}
if (khdr->count > ULONG_MAX - 1) {
pr_err("attempting to restore too many measurements");
return -EINVAL;
}
bitmap_zero(hdr_mask, HDR__LAST);
bitmap_set(hdr_mask, HDR_PCR, 1);
bitmap_set(hdr_mask, HDR_DIGEST, 1);
/*
* ima kexec buffer prefix: version, buffer size, count
* v1 format: pcr, digest, template-name-len, template-name,
* template-data-size, template-data
*/
ima: define a canonical binary_runtime_measurements list format The IMA binary_runtime_measurements list is currently in platform native format. To allow restoring a measurement list carried across kexec with a different endianness than the targeted kernel, this patch defines little-endian as the canonical format. For big endian systems wanting to save/restore the measurement list from a system with a different endianness, a new boot command line parameter named "ima_canonical_fmt" is defined. Considerations: use of the "ima_canonical_fmt" boot command line option will break existing userspace applications on big endian systems expecting the binary_runtime_measurements list to be in platform native format. Link: http://lkml.kernel.org/r/1480554346-29071-10-git-send-email-zohar@linux.vnet.ibm.com Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Acked-by: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Andreas Steffen <andreas.steffen@strongswan.org> Cc: Josh Sklar <sklar@linux.vnet.ibm.com> Cc: Dave Young <dyoung@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Stewart Smith <stewart@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-12-20 00:22:57 +00:00
bufendp = buf + khdr->buffer_size;
while ((bufp < bufendp) && (count++ < khdr->count)) {
int enforce_mask = ENFORCE_FIELDS;
enforce_mask |= (count == khdr->count) ? ENFORCE_BUFEND : 0;
ret = ima_parse_buf(bufp, bufendp, &bufp, HDR__LAST, hdr, NULL,
hdr_mask, enforce_mask, "entry header");
if (ret < 0)
break;
ima: define a canonical binary_runtime_measurements list format The IMA binary_runtime_measurements list is currently in platform native format. To allow restoring a measurement list carried across kexec with a different endianness than the targeted kernel, this patch defines little-endian as the canonical format. For big endian systems wanting to save/restore the measurement list from a system with a different endianness, a new boot command line parameter named "ima_canonical_fmt" is defined. Considerations: use of the "ima_canonical_fmt" boot command line option will break existing userspace applications on big endian systems expecting the binary_runtime_measurements list to be in platform native format. Link: http://lkml.kernel.org/r/1480554346-29071-10-git-send-email-zohar@linux.vnet.ibm.com Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Acked-by: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Andreas Steffen <andreas.steffen@strongswan.org> Cc: Josh Sklar <sklar@linux.vnet.ibm.com> Cc: Dave Young <dyoung@redhat.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Stewart Smith <stewart@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-12-20 00:22:57 +00:00
if (hdr[HDR_TEMPLATE_NAME].len >= MAX_TEMPLATE_NAME_LEN) {
pr_err("attempting to restore a template name that is too long\n");
ret = -EINVAL;
break;
}
/* template name is not null terminated */
memcpy(template_name, hdr[HDR_TEMPLATE_NAME].data,
hdr[HDR_TEMPLATE_NAME].len);
template_name[hdr[HDR_TEMPLATE_NAME].len] = 0;
if (strcmp(template_name, "ima") == 0) {
pr_err("attempting to restore an unsupported template \"%s\" failed\n",
template_name);
ret = -EINVAL;
break;
}
template_desc = lookup_template_desc(template_name);
if (!template_desc) {
template_desc = restore_template_fmt(template_name);
if (!template_desc)
break;
}
/*
* Only the running system's template format is initialized
* on boot. As needed, initialize the other template formats.
*/
ret = template_desc_init_fields(template_desc->fmt,
&(template_desc->fields),
&(template_desc->num_fields));
if (ret < 0) {
pr_err("attempting to restore the template fmt \"%s\" failed\n",
template_desc->fmt);
ret = -EINVAL;
break;
}
ret = ima_restore_template_data(template_desc,
hdr[HDR_TEMPLATE_DATA].data,
hdr[HDR_TEMPLATE_DATA].len,
&entry);
if (ret < 0)
break;
memcpy(entry->digest, hdr[HDR_DIGEST].data,
hdr[HDR_DIGEST].len);
entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) :
le32_to_cpu(*(hdr[HDR_PCR].data));
ret = ima_restore_measurement_entry(entry);
if (ret < 0)
break;
}
return ret;
}