diff options
author | Roberto Sassu <roberto.sassu@polito.it> | 2013-06-07 06:16:30 -0400 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2013-10-25 17:17:05 -0400 |
commit | 3ce1217d6cd5dfa82a9db5c2a999cc1bb01490d9 (patch) | |
tree | 4645a20eaa70b3dc5dd4654fa31a7cf132291fd5 | |
parent | adf53a778a0a5a5dc9103509da4a9719046e5310 (diff) |
ima: define template fields library and new helpers
This patch defines a library containing two initial template fields,
inode digest (d) and file name (n), the 'ima' template descriptor,
whose format is 'd|n', and two helper functions,
ima_write_template_field_data() and ima_show_template_field_data().
Changelog:
- replace ima_eventname_init() parameter NULL checking with BUG_ON.
(suggested by Mimi)
- include "new template fields for inode digest (d) and file name (n)"
definitions to fix a compiler warning. - Mimi
- unnecessary to prefix static function names with 'ima_'. remove
prefix to resolve Lindent formatting changes. - Mimi
- abbreviated/removed inline comments - Mimi
- always send the template field length - Mimi
Signed-off-by: Roberto Sassu <roberto.sassu@polito.it>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-rw-r--r-- | security/integrity/ima/Makefile | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 5 | ||||
-rw-r--r-- | security/integrity/ima/ima_fs.c | 4 | ||||
-rw-r--r-- | security/integrity/ima/ima_template.c | 15 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 193 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.h | 31 |
6 files changed, 242 insertions, 8 deletions
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 7fe4ae37dbea..d79263d2fdbf 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile | |||
@@ -6,5 +6,5 @@ | |||
6 | obj-$(CONFIG_IMA) += ima.o | 6 | obj-$(CONFIG_IMA) += ima.o |
7 | 7 | ||
8 | ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ | 8 | ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ |
9 | ima_policy.o ima_template.o | 9 | ima_policy.o ima_template.o ima_template_lib.o |
10 | ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o | 10 | ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index c85718f1f623..e1f081d65dbf 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -39,6 +39,9 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; | |||
39 | #define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16 | 39 | #define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16 |
40 | #define IMA_TEMPLATE_NUM_FIELDS_MAX 15 | 40 | #define IMA_TEMPLATE_NUM_FIELDS_MAX 15 |
41 | 41 | ||
42 | #define IMA_TEMPLATE_IMA_NAME "ima" | ||
43 | #define IMA_TEMPLATE_IMA_FMT "d|n" | ||
44 | |||
42 | /* set during initialization */ | 45 | /* set during initialization */ |
43 | extern int ima_initialized; | 46 | extern int ima_initialized; |
44 | extern int ima_used_chip; | 47 | extern int ima_used_chip; |
@@ -105,6 +108,8 @@ int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); | |||
105 | void ima_add_violation(struct file *file, const unsigned char *filename, | 108 | void ima_add_violation(struct file *file, const unsigned char *filename, |
106 | const char *op, const char *cause); | 109 | const char *op, const char *cause); |
107 | int ima_init_crypto(void); | 110 | int ima_init_crypto(void); |
111 | void ima_putc(struct seq_file *m, void *data, int datalen); | ||
112 | void ima_print_digest(struct seq_file *m, u8 *digest, int size); | ||
108 | 113 | ||
109 | int ima_init_template(void); | 114 | int ima_init_template(void); |
110 | 115 | ||
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index c35cfb5b3c5e..414862e1904b 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c | |||
@@ -99,7 +99,7 @@ static void ima_measurements_stop(struct seq_file *m, void *v) | |||
99 | { | 99 | { |
100 | } | 100 | } |
101 | 101 | ||
102 | static void ima_putc(struct seq_file *m, void *data, int datalen) | 102 | void ima_putc(struct seq_file *m, void *data, int datalen) |
103 | { | 103 | { |
104 | while (datalen--) | 104 | while (datalen--) |
105 | seq_putc(m, *(char *)data++); | 105 | seq_putc(m, *(char *)data++); |
@@ -167,7 +167,7 @@ static const struct file_operations ima_measurements_ops = { | |||
167 | .release = seq_release, | 167 | .release = seq_release, |
168 | }; | 168 | }; |
169 | 169 | ||
170 | static void ima_print_digest(struct seq_file *m, u8 *digest, int size) | 170 | void ima_print_digest(struct seq_file *m, u8 *digest, int size) |
171 | { | 171 | { |
172 | int i; | 172 | int i; |
173 | 173 | ||
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 7e86783ccf51..810042264396 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c | |||
@@ -13,15 +13,20 @@ | |||
13 | * Helpers to manage template descriptors. | 13 | * Helpers to manage template descriptors. |
14 | */ | 14 | */ |
15 | #include "ima.h" | 15 | #include "ima.h" |
16 | #include "ima_template_lib.h" | ||
16 | 17 | ||
17 | static struct ima_template_desc defined_templates[] = { | 18 | static struct ima_template_desc defined_templates[] = { |
19 | {.name = IMA_TEMPLATE_IMA_NAME,.fmt = IMA_TEMPLATE_IMA_FMT}, | ||
18 | }; | 20 | }; |
19 | 21 | ||
20 | static struct ima_template_field supported_fields[] = { | 22 | static struct ima_template_field supported_fields[] = { |
23 | {.field_id = "d",.field_init = ima_eventdigest_init, | ||
24 | .field_show = ima_show_template_digest}, | ||
25 | {.field_id = "n",.field_init = ima_eventname_init, | ||
26 | .field_show = ima_show_template_string}, | ||
21 | }; | 27 | }; |
22 | 28 | ||
23 | static struct ima_template_field *ima_lookup_template_field( | 29 | static struct ima_template_field *lookup_template_field(const char *field_id) |
24 | const char *field_id) | ||
25 | { | 30 | { |
26 | int i; | 31 | int i; |
27 | 32 | ||
@@ -32,7 +37,7 @@ static struct ima_template_field *ima_lookup_template_field( | |||
32 | return NULL; | 37 | return NULL; |
33 | } | 38 | } |
34 | 39 | ||
35 | static int ima_template_fmt_size(char *template_fmt) | 40 | static int template_fmt_size(char *template_fmt) |
36 | { | 41 | { |
37 | char c; | 42 | char c; |
38 | int template_fmt_len = strlen(template_fmt); | 43 | int template_fmt_len = strlen(template_fmt); |
@@ -53,7 +58,7 @@ static int template_desc_init_fields(char *template_fmt, | |||
53 | int *num_fields) | 58 | int *num_fields) |
54 | { | 59 | { |
55 | char *c, *template_fmt_ptr = template_fmt; | 60 | char *c, *template_fmt_ptr = template_fmt; |
56 | int template_num_fields = ima_template_fmt_size(template_fmt); | 61 | int template_num_fields = template_fmt_size(template_fmt); |
57 | int i, result = 0; | 62 | int i, result = 0; |
58 | 63 | ||
59 | if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) | 64 | if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) |
@@ -66,7 +71,7 @@ static int template_desc_init_fields(char *template_fmt, | |||
66 | } | 71 | } |
67 | for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL && | 72 | for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL && |
68 | i < template_num_fields; i++) { | 73 | i < template_num_fields; i++) { |
69 | struct ima_template_field *f = ima_lookup_template_field(c); | 74 | struct ima_template_field *f = lookup_template_field(c); |
70 | 75 | ||
71 | if (!f) { | 76 | if (!f) { |
72 | result = -ENOENT; | 77 | result = -ENOENT; |
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c new file mode 100644 index 000000000000..e13fc7c04ebc --- /dev/null +++ b/security/integrity/ima/ima_template_lib.c | |||
@@ -0,0 +1,193 @@ | |||
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_lib.c | ||
13 | * Library of supported template fields. | ||
14 | */ | ||
15 | #include "ima_template_lib.h" | ||
16 | |||
17 | enum data_formats { DATA_FMT_DIGEST = 0, DATA_FMT_EVENT_NAME, DATA_FMT_STRING }; | ||
18 | static int ima_write_template_field_data(const void *data, const u32 datalen, | ||
19 | enum data_formats datafmt, | ||
20 | struct ima_field_data *field_data) | ||
21 | { | ||
22 | u8 *buf, *buf_ptr; | ||
23 | u32 buflen; | ||
24 | |||
25 | switch (datafmt) { | ||
26 | case DATA_FMT_EVENT_NAME: | ||
27 | buflen = IMA_EVENT_NAME_LEN_MAX + 1; | ||
28 | break; | ||
29 | case DATA_FMT_STRING: | ||
30 | buflen = datalen + 1; | ||
31 | break; | ||
32 | default: | ||
33 | buflen = datalen; | ||
34 | } | ||
35 | |||
36 | buf = kzalloc(buflen, GFP_KERNEL); | ||
37 | if (!buf) | ||
38 | return -ENOMEM; | ||
39 | |||
40 | memcpy(buf, data, datalen); | ||
41 | |||
42 | /* | ||
43 | * Replace all space characters with underscore for event names and | ||
44 | * strings. This avoid that, during the parsing of a measurements list, | ||
45 | * filenames with spaces or that end with the suffix ' (deleted)' are | ||
46 | * split into multiple template fields (the space is the delimitator | ||
47 | * character for measurements lists in ASCII format). | ||
48 | */ | ||
49 | if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) { | ||
50 | for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++) | ||
51 | if (*buf_ptr == ' ') | ||
52 | *buf_ptr = '_'; | ||
53 | } | ||
54 | |||
55 | field_data->data = buf; | ||
56 | field_data->len = buflen; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static void ima_show_template_data_ascii(struct seq_file *m, | ||
61 | enum ima_show_type show, | ||
62 | enum data_formats datafmt, | ||
63 | struct ima_field_data *field_data) | ||
64 | { | ||
65 | switch (datafmt) { | ||
66 | case DATA_FMT_DIGEST: | ||
67 | ima_print_digest(m, field_data->data, field_data->len); | ||
68 | break; | ||
69 | case DATA_FMT_STRING: | ||
70 | seq_printf(m, "%s", field_data->data); | ||
71 | break; | ||
72 | default: | ||
73 | break; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | static void ima_show_template_data_binary(struct seq_file *m, | ||
78 | enum ima_show_type show, | ||
79 | enum data_formats datafmt, | ||
80 | struct ima_field_data *field_data) | ||
81 | { | ||
82 | ima_putc(m, &field_data->len, sizeof(u32)); | ||
83 | if (!field_data->len) | ||
84 | return; | ||
85 | ima_putc(m, field_data->data, field_data->len); | ||
86 | } | ||
87 | |||
88 | static void ima_show_template_field_data(struct seq_file *m, | ||
89 | enum ima_show_type show, | ||
90 | enum data_formats datafmt, | ||
91 | struct ima_field_data *field_data) | ||
92 | { | ||
93 | switch (show) { | ||
94 | case IMA_SHOW_ASCII: | ||
95 | ima_show_template_data_ascii(m, show, datafmt, field_data); | ||
96 | break; | ||
97 | case IMA_SHOW_BINARY: | ||
98 | ima_show_template_data_binary(m, show, datafmt, field_data); | ||
99 | break; | ||
100 | default: | ||
101 | break; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, | ||
106 | struct ima_field_data *field_data) | ||
107 | { | ||
108 | ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data); | ||
109 | } | ||
110 | |||
111 | void ima_show_template_string(struct seq_file *m, enum ima_show_type show, | ||
112 | struct ima_field_data *field_data) | ||
113 | { | ||
114 | ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * This function writes the digest of an event. | ||
119 | */ | ||
120 | int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, | ||
121 | const unsigned char *filename, | ||
122 | struct ima_field_data *field_data) | ||
123 | { | ||
124 | struct { | ||
125 | struct ima_digest_data hdr; | ||
126 | char digest[IMA_MAX_DIGEST_SIZE]; | ||
127 | } hash; | ||
128 | u8 *cur_digest = hash.hdr.digest; | ||
129 | u32 cur_digestsize = IMA_DIGEST_SIZE; | ||
130 | struct inode *inode; | ||
131 | int result; | ||
132 | |||
133 | memset(&hash, 0, sizeof(hash)); | ||
134 | |||
135 | if (!iint) /* recording a violation. */ | ||
136 | goto out; | ||
137 | |||
138 | if (iint->ima_hash->algo == ima_hash_algo) { | ||
139 | cur_digest = iint->ima_hash->digest; | ||
140 | cur_digestsize = iint->ima_hash->length; | ||
141 | goto out; | ||
142 | } | ||
143 | |||
144 | if (!file) /* missing info to re-calculate the digest */ | ||
145 | return -EINVAL; | ||
146 | |||
147 | inode = file_inode(file); | ||
148 | hash.hdr.algo = ima_hash_algo; | ||
149 | result = ima_calc_file_hash(file, &hash.hdr); | ||
150 | if (result) { | ||
151 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, | ||
152 | filename, "collect_data", | ||
153 | "failed", result, 0); | ||
154 | return result; | ||
155 | } | ||
156 | out: | ||
157 | return ima_write_template_field_data(cur_digest, cur_digestsize, | ||
158 | DATA_FMT_DIGEST, field_data); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * This function writes the name of an event. | ||
163 | */ | ||
164 | int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, | ||
165 | const unsigned char *filename, | ||
166 | struct ima_field_data *field_data) | ||
167 | { | ||
168 | const char *cur_filename = NULL; | ||
169 | u32 cur_filename_len = 0; | ||
170 | |||
171 | BUG_ON(filename == NULL && file == NULL); | ||
172 | |||
173 | if (filename) { | ||
174 | cur_filename = filename; | ||
175 | cur_filename_len = strlen(filename); | ||
176 | |||
177 | if (cur_filename_len <= IMA_EVENT_NAME_LEN_MAX) | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | if (file) { | ||
182 | cur_filename = file->f_dentry->d_name.name; | ||
183 | cur_filename_len = strlen(cur_filename); | ||
184 | } else | ||
185 | /* | ||
186 | * Truncate filename if the latter is too long and | ||
187 | * the file descriptor is not available. | ||
188 | */ | ||
189 | cur_filename_len = IMA_EVENT_NAME_LEN_MAX; | ||
190 | out: | ||
191 | return ima_write_template_field_data(cur_filename, cur_filename_len, | ||
192 | DATA_FMT_EVENT_NAME, field_data); | ||
193 | } | ||
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h new file mode 100644 index 000000000000..2cecc83a928d --- /dev/null +++ b/security/integrity/ima/ima_template_lib.h | |||
@@ -0,0 +1,31 @@ | |||
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_lib.h | ||
13 | * Header for the library of supported template fields. | ||
14 | */ | ||
15 | #ifndef __LINUX_IMA_TEMPLATE_LIB_H | ||
16 | #define __LINUX_IMA_TEMPLATE_LIB_H | ||
17 | |||
18 | #include <linux/seq_file.h> | ||
19 | #include "ima.h" | ||
20 | |||
21 | void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, | ||
22 | struct ima_field_data *field_data); | ||
23 | void ima_show_template_string(struct seq_file *m, enum ima_show_type show, | ||
24 | struct ima_field_data *field_data); | ||
25 | int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, | ||
26 | const unsigned char *filename, | ||
27 | struct ima_field_data *field_data); | ||
28 | int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, | ||
29 | const unsigned char *filename, | ||
30 | struct ima_field_data *field_data); | ||
31 | #endif /* __LINUX_IMA_TEMPLATE_LIB_H */ | ||