Commit 3ce1217d6cd5dfa82a9db5c2a999cc1bb01490d9
Committed by
Mimi Zohar
1 parent
adf53a778a
Exists in
master
and in
16 other branches
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>
Showing 6 changed files with 242 additions and 8 deletions Side-by-side Diff
security/integrity/ima/Makefile
security/integrity/ima/ima.h
... | ... | @@ -39,6 +39,9 @@ |
39 | 39 | #define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16 |
40 | 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 | 45 | /* set during initialization */ |
43 | 46 | extern int ima_initialized; |
44 | 47 | extern int ima_used_chip; |
... | ... | @@ -105,6 +108,8 @@ |
105 | 108 | void ima_add_violation(struct file *file, const unsigned char *filename, |
106 | 109 | const char *op, const char *cause); |
107 | 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 | 114 | int ima_init_template(void); |
110 | 115 |
security/integrity/ima/ima_fs.c
... | ... | @@ -99,7 +99,7 @@ |
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 | 104 | while (datalen--) |
105 | 105 | seq_putc(m, *(char *)data++); |
... | ... | @@ -167,7 +167,7 @@ |
167 | 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 | 172 | int i; |
173 | 173 |
security/integrity/ima/ima_template.c
... | ... | @@ -13,15 +13,20 @@ |
13 | 13 | * Helpers to manage template descriptors. |
14 | 14 | */ |
15 | 15 | #include "ima.h" |
16 | +#include "ima_template_lib.h" | |
16 | 17 | |
17 | 18 | static struct ima_template_desc defined_templates[] = { |
19 | + {.name = IMA_TEMPLATE_IMA_NAME,.fmt = IMA_TEMPLATE_IMA_FMT}, | |
18 | 20 | }; |
19 | 21 | |
20 | 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( | |
24 | - const char *field_id) | |
29 | +static struct ima_template_field *lookup_template_field(const char *field_id) | |
25 | 30 | { |
26 | 31 | int i; |
27 | 32 | |
... | ... | @@ -32,7 +37,7 @@ |
32 | 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 | 42 | char c; |
38 | 43 | int template_fmt_len = strlen(template_fmt); |
... | ... | @@ -53,7 +58,7 @@ |
53 | 58 | int *num_fields) |
54 | 59 | { |
55 | 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 | 62 | int i, result = 0; |
58 | 63 | |
59 | 64 | if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) |
... | ... | @@ -66,7 +71,7 @@ |
66 | 71 | } |
67 | 72 | for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL && |
68 | 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 | 76 | if (!f) { |
72 | 77 | result = -ENOENT; |
security/integrity/ima/ima_template_lib.c
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 | +} |
security/integrity/ima/ima_template_lib.h
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 */ |