Commit c019e307ad82a8ee652b8ccbacf69ae94263b07b
Committed by
Mimi Zohar
1 parent
73a6b44a00
Exists in
master
and in
13 other branches
ima: restore the original behavior for sending data with ima template
With the new template mechanism introduced in IMA since kernel 3.13, the format of data sent through the binary_runtime_measurements interface is slightly changed. Now, for a generic measurement, the format of template data (after the template name) is: template_len | field1_len | field1 | ... | fieldN_len | fieldN In addition, fields containing a string now include the '\0' termination character. Instead, the format for the 'ima' template should be: SHA1 digest | event name length | event name It must be noted that while in the IMA 3.13 code 'event name length' is 'IMA_EVENT_NAME_LEN_MAX + 1' (256 bytes), so that the template digest is calculated correctly, and 'event name' contains '\0', in the pre 3.13 code 'event name length' is exactly the string length and 'event name' does not contain the termination character. The patch restores the behavior of the IMA code pre 3.13 for the 'ima' template so that legacy userspace tools obtain a consistent behavior when receiving data from the binary_runtime_measurements interface regardless of which kernel version is used. Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Cc: <stable@vger.kernel.org> # 3.3.13: 3ce1217 ima: define template fields library Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Showing 3 changed files with 10 additions and 4 deletions Inline Diff
security/integrity/ima/ima.h
1 | /* | 1 | /* |
2 | * Copyright (C) 2005,2006,2007,2008 IBM Corporation | 2 | * Copyright (C) 2005,2006,2007,2008 IBM Corporation |
3 | * | 3 | * |
4 | * Authors: | 4 | * Authors: |
5 | * Reiner Sailer <sailer@watson.ibm.com> | 5 | * Reiner Sailer <sailer@watson.ibm.com> |
6 | * Mimi Zohar <zohar@us.ibm.com> | 6 | * Mimi Zohar <zohar@us.ibm.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation, version 2 of the | 10 | * published by the Free Software Foundation, version 2 of the |
11 | * License. | 11 | * License. |
12 | * | 12 | * |
13 | * File: ima.h | 13 | * File: ima.h |
14 | * internal Integrity Measurement Architecture (IMA) definitions | 14 | * internal Integrity Measurement Architecture (IMA) definitions |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef __LINUX_IMA_H | 17 | #ifndef __LINUX_IMA_H |
18 | #define __LINUX_IMA_H | 18 | #define __LINUX_IMA_H |
19 | 19 | ||
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/crypto.h> | 21 | #include <linux/crypto.h> |
22 | #include <linux/security.h> | 22 | #include <linux/security.h> |
23 | #include <linux/hash.h> | 23 | #include <linux/hash.h> |
24 | #include <linux/tpm.h> | 24 | #include <linux/tpm.h> |
25 | #include <linux/audit.h> | 25 | #include <linux/audit.h> |
26 | 26 | ||
27 | #include "../integrity.h" | 27 | #include "../integrity.h" |
28 | 28 | ||
29 | enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN, | 29 | enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN, |
30 | IMA_SHOW_ASCII }; | 30 | IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII }; |
31 | enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; | 31 | enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; |
32 | 32 | ||
33 | /* digest size for IMA, fits SHA1 or MD5 */ | 33 | /* digest size for IMA, fits SHA1 or MD5 */ |
34 | #define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE | 34 | #define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE |
35 | #define IMA_EVENT_NAME_LEN_MAX 255 | 35 | #define IMA_EVENT_NAME_LEN_MAX 255 |
36 | 36 | ||
37 | #define IMA_HASH_BITS 9 | 37 | #define IMA_HASH_BITS 9 |
38 | #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) | 38 | #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) |
39 | 39 | ||
40 | #define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16 | 40 | #define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16 |
41 | #define IMA_TEMPLATE_NUM_FIELDS_MAX 15 | 41 | #define IMA_TEMPLATE_NUM_FIELDS_MAX 15 |
42 | 42 | ||
43 | #define IMA_TEMPLATE_IMA_NAME "ima" | 43 | #define IMA_TEMPLATE_IMA_NAME "ima" |
44 | #define IMA_TEMPLATE_IMA_FMT "d|n" | 44 | #define IMA_TEMPLATE_IMA_FMT "d|n" |
45 | 45 | ||
46 | /* set during initialization */ | 46 | /* set during initialization */ |
47 | extern int ima_initialized; | 47 | extern int ima_initialized; |
48 | extern int ima_used_chip; | 48 | extern int ima_used_chip; |
49 | extern int ima_hash_algo; | 49 | extern int ima_hash_algo; |
50 | extern int ima_appraise; | 50 | extern int ima_appraise; |
51 | 51 | ||
52 | /* IMA template field data definition */ | 52 | /* IMA template field data definition */ |
53 | struct ima_field_data { | 53 | struct ima_field_data { |
54 | u8 *data; | 54 | u8 *data; |
55 | u32 len; | 55 | u32 len; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | /* IMA template field definition */ | 58 | /* IMA template field definition */ |
59 | struct ima_template_field { | 59 | struct ima_template_field { |
60 | const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN]; | 60 | const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN]; |
61 | int (*field_init) (struct integrity_iint_cache *iint, struct file *file, | 61 | int (*field_init) (struct integrity_iint_cache *iint, struct file *file, |
62 | const unsigned char *filename, | 62 | const unsigned char *filename, |
63 | struct evm_ima_xattr_data *xattr_value, | 63 | struct evm_ima_xattr_data *xattr_value, |
64 | int xattr_len, struct ima_field_data *field_data); | 64 | int xattr_len, struct ima_field_data *field_data); |
65 | void (*field_show) (struct seq_file *m, enum ima_show_type show, | 65 | void (*field_show) (struct seq_file *m, enum ima_show_type show, |
66 | struct ima_field_data *field_data); | 66 | struct ima_field_data *field_data); |
67 | }; | 67 | }; |
68 | 68 | ||
69 | /* IMA template descriptor definition */ | 69 | /* IMA template descriptor definition */ |
70 | struct ima_template_desc { | 70 | struct ima_template_desc { |
71 | char *name; | 71 | char *name; |
72 | char *fmt; | 72 | char *fmt; |
73 | int num_fields; | 73 | int num_fields; |
74 | struct ima_template_field **fields; | 74 | struct ima_template_field **fields; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct ima_template_entry { | 77 | struct ima_template_entry { |
78 | u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */ | 78 | u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */ |
79 | struct ima_template_desc *template_desc; /* template descriptor */ | 79 | struct ima_template_desc *template_desc; /* template descriptor */ |
80 | u32 template_data_len; | 80 | u32 template_data_len; |
81 | struct ima_field_data template_data[0]; /* template related data */ | 81 | struct ima_field_data template_data[0]; /* template related data */ |
82 | }; | 82 | }; |
83 | 83 | ||
84 | struct ima_queue_entry { | 84 | struct ima_queue_entry { |
85 | struct hlist_node hnext; /* place in hash collision list */ | 85 | struct hlist_node hnext; /* place in hash collision list */ |
86 | struct list_head later; /* place in ima_measurements list */ | 86 | struct list_head later; /* place in ima_measurements list */ |
87 | struct ima_template_entry *entry; | 87 | struct ima_template_entry *entry; |
88 | }; | 88 | }; |
89 | extern struct list_head ima_measurements; /* list of all measurements */ | 89 | extern struct list_head ima_measurements; /* list of all measurements */ |
90 | 90 | ||
91 | /* Internal IMA function definitions */ | 91 | /* Internal IMA function definitions */ |
92 | int ima_init(void); | 92 | int ima_init(void); |
93 | void ima_cleanup(void); | 93 | void ima_cleanup(void); |
94 | int ima_fs_init(void); | 94 | int ima_fs_init(void); |
95 | void ima_fs_cleanup(void); | 95 | void ima_fs_cleanup(void); |
96 | int ima_inode_alloc(struct inode *inode); | 96 | int ima_inode_alloc(struct inode *inode); |
97 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, | 97 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, |
98 | const char *op, struct inode *inode, | 98 | const char *op, struct inode *inode, |
99 | const unsigned char *filename); | 99 | const unsigned char *filename); |
100 | int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); | 100 | int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); |
101 | int ima_calc_field_array_hash(struct ima_field_data *field_data, | 101 | int ima_calc_field_array_hash(struct ima_field_data *field_data, |
102 | struct ima_template_desc *desc, int num_fields, | 102 | struct ima_template_desc *desc, int num_fields, |
103 | struct ima_digest_data *hash); | 103 | struct ima_digest_data *hash); |
104 | int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); | 104 | int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); |
105 | void ima_add_violation(struct file *file, const unsigned char *filename, | 105 | void ima_add_violation(struct file *file, const unsigned char *filename, |
106 | const char *op, const char *cause); | 106 | const char *op, const char *cause); |
107 | int ima_init_crypto(void); | 107 | int ima_init_crypto(void); |
108 | void ima_putc(struct seq_file *m, void *data, int datalen); | 108 | void ima_putc(struct seq_file *m, void *data, int datalen); |
109 | void ima_print_digest(struct seq_file *m, u8 *digest, int size); | 109 | void ima_print_digest(struct seq_file *m, u8 *digest, int size); |
110 | struct ima_template_desc *ima_template_desc_current(void); | 110 | struct ima_template_desc *ima_template_desc_current(void); |
111 | int ima_init_template(void); | 111 | int ima_init_template(void); |
112 | 112 | ||
113 | int ima_init_template(void); | 113 | int ima_init_template(void); |
114 | 114 | ||
115 | /* | 115 | /* |
116 | * used to protect h_table and sha_table | 116 | * used to protect h_table and sha_table |
117 | */ | 117 | */ |
118 | extern spinlock_t ima_queue_lock; | 118 | extern spinlock_t ima_queue_lock; |
119 | 119 | ||
120 | struct ima_h_table { | 120 | struct ima_h_table { |
121 | atomic_long_t len; /* number of stored measurements in the list */ | 121 | atomic_long_t len; /* number of stored measurements in the list */ |
122 | atomic_long_t violations; | 122 | atomic_long_t violations; |
123 | struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; | 123 | struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; |
124 | }; | 124 | }; |
125 | extern struct ima_h_table ima_htable; | 125 | extern struct ima_h_table ima_htable; |
126 | 126 | ||
127 | static inline unsigned long ima_hash_key(u8 *digest) | 127 | static inline unsigned long ima_hash_key(u8 *digest) |
128 | { | 128 | { |
129 | return hash_long(*digest, IMA_HASH_BITS); | 129 | return hash_long(*digest, IMA_HASH_BITS); |
130 | } | 130 | } |
131 | 131 | ||
132 | /* LIM API function definitions */ | 132 | /* LIM API function definitions */ |
133 | int ima_get_action(struct inode *inode, int mask, int function); | 133 | int ima_get_action(struct inode *inode, int mask, int function); |
134 | int ima_must_measure(struct inode *inode, int mask, int function); | 134 | int ima_must_measure(struct inode *inode, int mask, int function); |
135 | int ima_collect_measurement(struct integrity_iint_cache *iint, | 135 | int ima_collect_measurement(struct integrity_iint_cache *iint, |
136 | struct file *file, | 136 | struct file *file, |
137 | struct evm_ima_xattr_data **xattr_value, | 137 | struct evm_ima_xattr_data **xattr_value, |
138 | int *xattr_len); | 138 | int *xattr_len); |
139 | void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, | 139 | void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, |
140 | const unsigned char *filename, | 140 | const unsigned char *filename, |
141 | struct evm_ima_xattr_data *xattr_value, | 141 | struct evm_ima_xattr_data *xattr_value, |
142 | int xattr_len); | 142 | int xattr_len); |
143 | void ima_audit_measurement(struct integrity_iint_cache *iint, | 143 | void ima_audit_measurement(struct integrity_iint_cache *iint, |
144 | const unsigned char *filename); | 144 | const unsigned char *filename); |
145 | int ima_alloc_init_template(struct integrity_iint_cache *iint, | 145 | int ima_alloc_init_template(struct integrity_iint_cache *iint, |
146 | struct file *file, const unsigned char *filename, | 146 | struct file *file, const unsigned char *filename, |
147 | struct evm_ima_xattr_data *xattr_value, | 147 | struct evm_ima_xattr_data *xattr_value, |
148 | int xattr_len, struct ima_template_entry **entry); | 148 | int xattr_len, struct ima_template_entry **entry); |
149 | int ima_store_template(struct ima_template_entry *entry, int violation, | 149 | int ima_store_template(struct ima_template_entry *entry, int violation, |
150 | struct inode *inode, const unsigned char *filename); | 150 | struct inode *inode, const unsigned char *filename); |
151 | void ima_free_template_entry(struct ima_template_entry *entry); | 151 | void ima_free_template_entry(struct ima_template_entry *entry); |
152 | const char *ima_d_path(struct path *path, char **pathbuf); | 152 | const char *ima_d_path(struct path *path, char **pathbuf); |
153 | 153 | ||
154 | /* rbtree tree calls to lookup, insert, delete | 154 | /* rbtree tree calls to lookup, insert, delete |
155 | * integrity data associated with an inode. | 155 | * integrity data associated with an inode. |
156 | */ | 156 | */ |
157 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | 157 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); |
158 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | 158 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); |
159 | 159 | ||
160 | /* IMA policy related functions */ | 160 | /* IMA policy related functions */ |
161 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, POST_SETATTR }; | 161 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, POST_SETATTR }; |
162 | 162 | ||
163 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | 163 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, |
164 | int flags); | 164 | int flags); |
165 | void ima_init_policy(void); | 165 | void ima_init_policy(void); |
166 | void ima_update_policy(void); | 166 | void ima_update_policy(void); |
167 | ssize_t ima_parse_add_rule(char *); | 167 | ssize_t ima_parse_add_rule(char *); |
168 | void ima_delete_rules(void); | 168 | void ima_delete_rules(void); |
169 | 169 | ||
170 | /* Appraise integrity measurements */ | 170 | /* Appraise integrity measurements */ |
171 | #define IMA_APPRAISE_ENFORCE 0x01 | 171 | #define IMA_APPRAISE_ENFORCE 0x01 |
172 | #define IMA_APPRAISE_FIX 0x02 | 172 | #define IMA_APPRAISE_FIX 0x02 |
173 | #define IMA_APPRAISE_MODULES 0x04 | 173 | #define IMA_APPRAISE_MODULES 0x04 |
174 | 174 | ||
175 | #ifdef CONFIG_IMA_APPRAISE | 175 | #ifdef CONFIG_IMA_APPRAISE |
176 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 176 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
177 | struct file *file, const unsigned char *filename, | 177 | struct file *file, const unsigned char *filename, |
178 | struct evm_ima_xattr_data *xattr_value, | 178 | struct evm_ima_xattr_data *xattr_value, |
179 | int xattr_len); | 179 | int xattr_len); |
180 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); | 180 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); |
181 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); | 181 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); |
182 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, | 182 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, |
183 | int func); | 183 | int func); |
184 | void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len, | 184 | void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len, |
185 | struct ima_digest_data *hash); | 185 | struct ima_digest_data *hash); |
186 | int ima_read_xattr(struct dentry *dentry, | 186 | int ima_read_xattr(struct dentry *dentry, |
187 | struct evm_ima_xattr_data **xattr_value); | 187 | struct evm_ima_xattr_data **xattr_value); |
188 | 188 | ||
189 | #else | 189 | #else |
190 | static inline int ima_appraise_measurement(int func, | 190 | static inline int ima_appraise_measurement(int func, |
191 | struct integrity_iint_cache *iint, | 191 | struct integrity_iint_cache *iint, |
192 | struct file *file, | 192 | struct file *file, |
193 | const unsigned char *filename, | 193 | const unsigned char *filename, |
194 | struct evm_ima_xattr_data *xattr_value, | 194 | struct evm_ima_xattr_data *xattr_value, |
195 | int xattr_len) | 195 | int xattr_len) |
196 | { | 196 | { |
197 | return INTEGRITY_UNKNOWN; | 197 | return INTEGRITY_UNKNOWN; |
198 | } | 198 | } |
199 | 199 | ||
200 | static inline int ima_must_appraise(struct inode *inode, int mask, | 200 | static inline int ima_must_appraise(struct inode *inode, int mask, |
201 | enum ima_hooks func) | 201 | enum ima_hooks func) |
202 | { | 202 | { |
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
206 | static inline void ima_update_xattr(struct integrity_iint_cache *iint, | 206 | static inline void ima_update_xattr(struct integrity_iint_cache *iint, |
207 | struct file *file) | 207 | struct file *file) |
208 | { | 208 | { |
209 | } | 209 | } |
210 | 210 | ||
211 | static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache | 211 | static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache |
212 | *iint, int func) | 212 | *iint, int func) |
213 | { | 213 | { |
214 | return INTEGRITY_UNKNOWN; | 214 | return INTEGRITY_UNKNOWN; |
215 | } | 215 | } |
216 | 216 | ||
217 | static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, | 217 | static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, |
218 | int xattr_len, | 218 | int xattr_len, |
219 | struct ima_digest_data *hash) | 219 | struct ima_digest_data *hash) |
220 | { | 220 | { |
221 | } | 221 | } |
222 | 222 | ||
223 | static inline int ima_read_xattr(struct dentry *dentry, | 223 | static inline int ima_read_xattr(struct dentry *dentry, |
224 | struct evm_ima_xattr_data **xattr_value) | 224 | struct evm_ima_xattr_data **xattr_value) |
225 | { | 225 | { |
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | #endif | 229 | #endif |
230 | 230 | ||
231 | /* LSM based policy rules require audit */ | 231 | /* LSM based policy rules require audit */ |
232 | #ifdef CONFIG_IMA_LSM_RULES | 232 | #ifdef CONFIG_IMA_LSM_RULES |
233 | 233 | ||
234 | #define security_filter_rule_init security_audit_rule_init | 234 | #define security_filter_rule_init security_audit_rule_init |
235 | #define security_filter_rule_match security_audit_rule_match | 235 | #define security_filter_rule_match security_audit_rule_match |
236 | 236 | ||
237 | #else | 237 | #else |
238 | 238 | ||
239 | static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr, | 239 | static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr, |
240 | void **lsmrule) | 240 | void **lsmrule) |
241 | { | 241 | { |
242 | return -EINVAL; | 242 | return -EINVAL; |
243 | } | 243 | } |
244 | 244 | ||
245 | static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, | 245 | static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, |
246 | void *lsmrule, | 246 | void *lsmrule, |
247 | struct audit_context *actx) | 247 | struct audit_context *actx) |
248 | { | 248 | { |
249 | return -EINVAL; | 249 | return -EINVAL; |
250 | } | 250 | } |
251 | #endif /* CONFIG_IMA_LSM_RULES */ | 251 | #endif /* CONFIG_IMA_LSM_RULES */ |
252 | #endif | 252 | #endif |
253 | 253 |
security/integrity/ima/ima_fs.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2005,2006,2007,2008 IBM Corporation | 2 | * Copyright (C) 2005,2006,2007,2008 IBM Corporation |
3 | * | 3 | * |
4 | * Authors: | 4 | * Authors: |
5 | * Kylene Hall <kjhall@us.ibm.com> | 5 | * Kylene Hall <kjhall@us.ibm.com> |
6 | * Reiner Sailer <sailer@us.ibm.com> | 6 | * Reiner Sailer <sailer@us.ibm.com> |
7 | * Mimi Zohar <zohar@us.ibm.com> | 7 | * Mimi Zohar <zohar@us.ibm.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License as | 10 | * modify it under the terms of the GNU General Public License as |
11 | * published by the Free Software Foundation, version 2 of the | 11 | * published by the Free Software Foundation, version 2 of the |
12 | * License. | 12 | * License. |
13 | * | 13 | * |
14 | * File: ima_fs.c | 14 | * File: ima_fs.c |
15 | * implemenents security file system for reporting | 15 | * implemenents security file system for reporting |
16 | * current measurement list and IMA statistics | 16 | * current measurement list and IMA statistics |
17 | */ | 17 | */ |
18 | #include <linux/fcntl.h> | 18 | #include <linux/fcntl.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
22 | #include <linux/rculist.h> | 22 | #include <linux/rculist.h> |
23 | #include <linux/rcupdate.h> | 23 | #include <linux/rcupdate.h> |
24 | #include <linux/parser.h> | 24 | #include <linux/parser.h> |
25 | 25 | ||
26 | #include "ima.h" | 26 | #include "ima.h" |
27 | 27 | ||
28 | static int valid_policy = 1; | 28 | static int valid_policy = 1; |
29 | #define TMPBUFLEN 12 | 29 | #define TMPBUFLEN 12 |
30 | static ssize_t ima_show_htable_value(char __user *buf, size_t count, | 30 | static ssize_t ima_show_htable_value(char __user *buf, size_t count, |
31 | loff_t *ppos, atomic_long_t *val) | 31 | loff_t *ppos, atomic_long_t *val) |
32 | { | 32 | { |
33 | char tmpbuf[TMPBUFLEN]; | 33 | char tmpbuf[TMPBUFLEN]; |
34 | ssize_t len; | 34 | ssize_t len; |
35 | 35 | ||
36 | len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val)); | 36 | len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val)); |
37 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); | 37 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); |
38 | } | 38 | } |
39 | 39 | ||
40 | static ssize_t ima_show_htable_violations(struct file *filp, | 40 | static ssize_t ima_show_htable_violations(struct file *filp, |
41 | char __user *buf, | 41 | char __user *buf, |
42 | size_t count, loff_t *ppos) | 42 | size_t count, loff_t *ppos) |
43 | { | 43 | { |
44 | return ima_show_htable_value(buf, count, ppos, &ima_htable.violations); | 44 | return ima_show_htable_value(buf, count, ppos, &ima_htable.violations); |
45 | } | 45 | } |
46 | 46 | ||
47 | static const struct file_operations ima_htable_violations_ops = { | 47 | static const struct file_operations ima_htable_violations_ops = { |
48 | .read = ima_show_htable_violations, | 48 | .read = ima_show_htable_violations, |
49 | .llseek = generic_file_llseek, | 49 | .llseek = generic_file_llseek, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static ssize_t ima_show_measurements_count(struct file *filp, | 52 | static ssize_t ima_show_measurements_count(struct file *filp, |
53 | char __user *buf, | 53 | char __user *buf, |
54 | size_t count, loff_t *ppos) | 54 | size_t count, loff_t *ppos) |
55 | { | 55 | { |
56 | return ima_show_htable_value(buf, count, ppos, &ima_htable.len); | 56 | return ima_show_htable_value(buf, count, ppos, &ima_htable.len); |
57 | 57 | ||
58 | } | 58 | } |
59 | 59 | ||
60 | static const struct file_operations ima_measurements_count_ops = { | 60 | static const struct file_operations ima_measurements_count_ops = { |
61 | .read = ima_show_measurements_count, | 61 | .read = ima_show_measurements_count, |
62 | .llseek = generic_file_llseek, | 62 | .llseek = generic_file_llseek, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | /* returns pointer to hlist_node */ | 65 | /* returns pointer to hlist_node */ |
66 | static void *ima_measurements_start(struct seq_file *m, loff_t *pos) | 66 | static void *ima_measurements_start(struct seq_file *m, loff_t *pos) |
67 | { | 67 | { |
68 | loff_t l = *pos; | 68 | loff_t l = *pos; |
69 | struct ima_queue_entry *qe; | 69 | struct ima_queue_entry *qe; |
70 | 70 | ||
71 | /* we need a lock since pos could point beyond last element */ | 71 | /* we need a lock since pos could point beyond last element */ |
72 | rcu_read_lock(); | 72 | rcu_read_lock(); |
73 | list_for_each_entry_rcu(qe, &ima_measurements, later) { | 73 | list_for_each_entry_rcu(qe, &ima_measurements, later) { |
74 | if (!l--) { | 74 | if (!l--) { |
75 | rcu_read_unlock(); | 75 | rcu_read_unlock(); |
76 | return qe; | 76 | return qe; |
77 | } | 77 | } |
78 | } | 78 | } |
79 | rcu_read_unlock(); | 79 | rcu_read_unlock(); |
80 | return NULL; | 80 | return NULL; |
81 | } | 81 | } |
82 | 82 | ||
83 | static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) | 83 | static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) |
84 | { | 84 | { |
85 | struct ima_queue_entry *qe = v; | 85 | struct ima_queue_entry *qe = v; |
86 | 86 | ||
87 | /* lock protects when reading beyond last element | 87 | /* lock protects when reading beyond last element |
88 | * against concurrent list-extension | 88 | * against concurrent list-extension |
89 | */ | 89 | */ |
90 | rcu_read_lock(); | 90 | rcu_read_lock(); |
91 | qe = list_entry_rcu(qe->later.next, struct ima_queue_entry, later); | 91 | qe = list_entry_rcu(qe->later.next, struct ima_queue_entry, later); |
92 | rcu_read_unlock(); | 92 | rcu_read_unlock(); |
93 | (*pos)++; | 93 | (*pos)++; |
94 | 94 | ||
95 | return (&qe->later == &ima_measurements) ? NULL : qe; | 95 | return (&qe->later == &ima_measurements) ? NULL : qe; |
96 | } | 96 | } |
97 | 97 | ||
98 | static void ima_measurements_stop(struct seq_file *m, void *v) | 98 | static void ima_measurements_stop(struct seq_file *m, void *v) |
99 | { | 99 | { |
100 | } | 100 | } |
101 | 101 | ||
102 | 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++); |
106 | } | 106 | } |
107 | 107 | ||
108 | /* print format: | 108 | /* print format: |
109 | * 32bit-le=pcr# | 109 | * 32bit-le=pcr# |
110 | * char[20]=template digest | 110 | * char[20]=template digest |
111 | * 32bit-le=template name size | 111 | * 32bit-le=template name size |
112 | * char[n]=template name | 112 | * char[n]=template name |
113 | * [eventdata length] | 113 | * [eventdata length] |
114 | * eventdata[n]=template specific data | 114 | * eventdata[n]=template specific data |
115 | */ | 115 | */ |
116 | static int ima_measurements_show(struct seq_file *m, void *v) | 116 | static int ima_measurements_show(struct seq_file *m, void *v) |
117 | { | 117 | { |
118 | /* the list never shrinks, so we don't need a lock here */ | 118 | /* the list never shrinks, so we don't need a lock here */ |
119 | struct ima_queue_entry *qe = v; | 119 | struct ima_queue_entry *qe = v; |
120 | struct ima_template_entry *e; | 120 | struct ima_template_entry *e; |
121 | int namelen; | 121 | int namelen; |
122 | u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; | 122 | u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; |
123 | bool is_ima_template = false; | 123 | bool is_ima_template = false; |
124 | int i; | 124 | int i; |
125 | 125 | ||
126 | /* get entry */ | 126 | /* get entry */ |
127 | e = qe->entry; | 127 | e = qe->entry; |
128 | if (e == NULL) | 128 | if (e == NULL) |
129 | return -1; | 129 | return -1; |
130 | 130 | ||
131 | /* | 131 | /* |
132 | * 1st: PCRIndex | 132 | * 1st: PCRIndex |
133 | * PCR used is always the same (config option) in | 133 | * PCR used is always the same (config option) in |
134 | * little-endian format | 134 | * little-endian format |
135 | */ | 135 | */ |
136 | ima_putc(m, &pcr, sizeof pcr); | 136 | ima_putc(m, &pcr, sizeof pcr); |
137 | 137 | ||
138 | /* 2nd: template digest */ | 138 | /* 2nd: template digest */ |
139 | ima_putc(m, e->digest, TPM_DIGEST_SIZE); | 139 | ima_putc(m, e->digest, TPM_DIGEST_SIZE); |
140 | 140 | ||
141 | /* 3rd: template name size */ | 141 | /* 3rd: template name size */ |
142 | namelen = strlen(e->template_desc->name); | 142 | namelen = strlen(e->template_desc->name); |
143 | ima_putc(m, &namelen, sizeof namelen); | 143 | ima_putc(m, &namelen, sizeof namelen); |
144 | 144 | ||
145 | /* 4th: template name */ | 145 | /* 4th: template name */ |
146 | ima_putc(m, e->template_desc->name, namelen); | 146 | ima_putc(m, e->template_desc->name, namelen); |
147 | 147 | ||
148 | /* 5th: template length (except for 'ima' template) */ | 148 | /* 5th: template length (except for 'ima' template) */ |
149 | if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) | 149 | if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) |
150 | is_ima_template = true; | 150 | is_ima_template = true; |
151 | 151 | ||
152 | if (!is_ima_template) | 152 | if (!is_ima_template) |
153 | ima_putc(m, &e->template_data_len, | 153 | ima_putc(m, &e->template_data_len, |
154 | sizeof(e->template_data_len)); | 154 | sizeof(e->template_data_len)); |
155 | 155 | ||
156 | /* 6th: template specific data */ | 156 | /* 6th: template specific data */ |
157 | for (i = 0; i < e->template_desc->num_fields; i++) { | 157 | for (i = 0; i < e->template_desc->num_fields; i++) { |
158 | enum ima_show_type show = IMA_SHOW_BINARY; | 158 | enum ima_show_type show = IMA_SHOW_BINARY; |
159 | struct ima_template_field *field = e->template_desc->fields[i]; | 159 | struct ima_template_field *field = e->template_desc->fields[i]; |
160 | 160 | ||
161 | if (is_ima_template && strcmp(field->field_id, "d") == 0) | 161 | if (is_ima_template && strcmp(field->field_id, "d") == 0) |
162 | show = IMA_SHOW_BINARY_NO_FIELD_LEN; | 162 | show = IMA_SHOW_BINARY_NO_FIELD_LEN; |
163 | if (is_ima_template && strcmp(field->field_id, "n") == 0) | ||
164 | show = IMA_SHOW_BINARY_OLD_STRING_FMT; | ||
163 | field->field_show(m, show, &e->template_data[i]); | 165 | field->field_show(m, show, &e->template_data[i]); |
164 | } | 166 | } |
165 | return 0; | 167 | return 0; |
166 | } | 168 | } |
167 | 169 | ||
168 | static const struct seq_operations ima_measurments_seqops = { | 170 | static const struct seq_operations ima_measurments_seqops = { |
169 | .start = ima_measurements_start, | 171 | .start = ima_measurements_start, |
170 | .next = ima_measurements_next, | 172 | .next = ima_measurements_next, |
171 | .stop = ima_measurements_stop, | 173 | .stop = ima_measurements_stop, |
172 | .show = ima_measurements_show | 174 | .show = ima_measurements_show |
173 | }; | 175 | }; |
174 | 176 | ||
175 | static int ima_measurements_open(struct inode *inode, struct file *file) | 177 | static int ima_measurements_open(struct inode *inode, struct file *file) |
176 | { | 178 | { |
177 | return seq_open(file, &ima_measurments_seqops); | 179 | return seq_open(file, &ima_measurments_seqops); |
178 | } | 180 | } |
179 | 181 | ||
180 | static const struct file_operations ima_measurements_ops = { | 182 | static const struct file_operations ima_measurements_ops = { |
181 | .open = ima_measurements_open, | 183 | .open = ima_measurements_open, |
182 | .read = seq_read, | 184 | .read = seq_read, |
183 | .llseek = seq_lseek, | 185 | .llseek = seq_lseek, |
184 | .release = seq_release, | 186 | .release = seq_release, |
185 | }; | 187 | }; |
186 | 188 | ||
187 | void ima_print_digest(struct seq_file *m, u8 *digest, int size) | 189 | void ima_print_digest(struct seq_file *m, u8 *digest, int size) |
188 | { | 190 | { |
189 | int i; | 191 | int i; |
190 | 192 | ||
191 | for (i = 0; i < size; i++) | 193 | for (i = 0; i < size; i++) |
192 | seq_printf(m, "%02x", *(digest + i)); | 194 | seq_printf(m, "%02x", *(digest + i)); |
193 | } | 195 | } |
194 | 196 | ||
195 | /* print in ascii */ | 197 | /* print in ascii */ |
196 | static int ima_ascii_measurements_show(struct seq_file *m, void *v) | 198 | static int ima_ascii_measurements_show(struct seq_file *m, void *v) |
197 | { | 199 | { |
198 | /* the list never shrinks, so we don't need a lock here */ | 200 | /* the list never shrinks, so we don't need a lock here */ |
199 | struct ima_queue_entry *qe = v; | 201 | struct ima_queue_entry *qe = v; |
200 | struct ima_template_entry *e; | 202 | struct ima_template_entry *e; |
201 | int i; | 203 | int i; |
202 | 204 | ||
203 | /* get entry */ | 205 | /* get entry */ |
204 | e = qe->entry; | 206 | e = qe->entry; |
205 | if (e == NULL) | 207 | if (e == NULL) |
206 | return -1; | 208 | return -1; |
207 | 209 | ||
208 | /* 1st: PCR used (config option) */ | 210 | /* 1st: PCR used (config option) */ |
209 | seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX); | 211 | seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX); |
210 | 212 | ||
211 | /* 2nd: SHA1 template hash */ | 213 | /* 2nd: SHA1 template hash */ |
212 | ima_print_digest(m, e->digest, TPM_DIGEST_SIZE); | 214 | ima_print_digest(m, e->digest, TPM_DIGEST_SIZE); |
213 | 215 | ||
214 | /* 3th: template name */ | 216 | /* 3th: template name */ |
215 | seq_printf(m, " %s", e->template_desc->name); | 217 | seq_printf(m, " %s", e->template_desc->name); |
216 | 218 | ||
217 | /* 4th: template specific data */ | 219 | /* 4th: template specific data */ |
218 | for (i = 0; i < e->template_desc->num_fields; i++) { | 220 | for (i = 0; i < e->template_desc->num_fields; i++) { |
219 | seq_puts(m, " "); | 221 | seq_puts(m, " "); |
220 | if (e->template_data[i].len == 0) | 222 | if (e->template_data[i].len == 0) |
221 | continue; | 223 | continue; |
222 | 224 | ||
223 | e->template_desc->fields[i]->field_show(m, IMA_SHOW_ASCII, | 225 | e->template_desc->fields[i]->field_show(m, IMA_SHOW_ASCII, |
224 | &e->template_data[i]); | 226 | &e->template_data[i]); |
225 | } | 227 | } |
226 | seq_puts(m, "\n"); | 228 | seq_puts(m, "\n"); |
227 | return 0; | 229 | return 0; |
228 | } | 230 | } |
229 | 231 | ||
230 | static const struct seq_operations ima_ascii_measurements_seqops = { | 232 | static const struct seq_operations ima_ascii_measurements_seqops = { |
231 | .start = ima_measurements_start, | 233 | .start = ima_measurements_start, |
232 | .next = ima_measurements_next, | 234 | .next = ima_measurements_next, |
233 | .stop = ima_measurements_stop, | 235 | .stop = ima_measurements_stop, |
234 | .show = ima_ascii_measurements_show | 236 | .show = ima_ascii_measurements_show |
235 | }; | 237 | }; |
236 | 238 | ||
237 | static int ima_ascii_measurements_open(struct inode *inode, struct file *file) | 239 | static int ima_ascii_measurements_open(struct inode *inode, struct file *file) |
238 | { | 240 | { |
239 | return seq_open(file, &ima_ascii_measurements_seqops); | 241 | return seq_open(file, &ima_ascii_measurements_seqops); |
240 | } | 242 | } |
241 | 243 | ||
242 | static const struct file_operations ima_ascii_measurements_ops = { | 244 | static const struct file_operations ima_ascii_measurements_ops = { |
243 | .open = ima_ascii_measurements_open, | 245 | .open = ima_ascii_measurements_open, |
244 | .read = seq_read, | 246 | .read = seq_read, |
245 | .llseek = seq_lseek, | 247 | .llseek = seq_lseek, |
246 | .release = seq_release, | 248 | .release = seq_release, |
247 | }; | 249 | }; |
248 | 250 | ||
249 | static ssize_t ima_write_policy(struct file *file, const char __user *buf, | 251 | static ssize_t ima_write_policy(struct file *file, const char __user *buf, |
250 | size_t datalen, loff_t *ppos) | 252 | size_t datalen, loff_t *ppos) |
251 | { | 253 | { |
252 | char *data = NULL; | 254 | char *data = NULL; |
253 | ssize_t result; | 255 | ssize_t result; |
254 | 256 | ||
255 | if (datalen >= PAGE_SIZE) | 257 | if (datalen >= PAGE_SIZE) |
256 | datalen = PAGE_SIZE - 1; | 258 | datalen = PAGE_SIZE - 1; |
257 | 259 | ||
258 | /* No partial writes. */ | 260 | /* No partial writes. */ |
259 | result = -EINVAL; | 261 | result = -EINVAL; |
260 | if (*ppos != 0) | 262 | if (*ppos != 0) |
261 | goto out; | 263 | goto out; |
262 | 264 | ||
263 | result = -ENOMEM; | 265 | result = -ENOMEM; |
264 | data = kmalloc(datalen + 1, GFP_KERNEL); | 266 | data = kmalloc(datalen + 1, GFP_KERNEL); |
265 | if (!data) | 267 | if (!data) |
266 | goto out; | 268 | goto out; |
267 | 269 | ||
268 | *(data + datalen) = '\0'; | 270 | *(data + datalen) = '\0'; |
269 | 271 | ||
270 | result = -EFAULT; | 272 | result = -EFAULT; |
271 | if (copy_from_user(data, buf, datalen)) | 273 | if (copy_from_user(data, buf, datalen)) |
272 | goto out; | 274 | goto out; |
273 | 275 | ||
274 | result = ima_parse_add_rule(data); | 276 | result = ima_parse_add_rule(data); |
275 | out: | 277 | out: |
276 | if (result < 0) | 278 | if (result < 0) |
277 | valid_policy = 0; | 279 | valid_policy = 0; |
278 | kfree(data); | 280 | kfree(data); |
279 | return result; | 281 | return result; |
280 | } | 282 | } |
281 | 283 | ||
282 | static struct dentry *ima_dir; | 284 | static struct dentry *ima_dir; |
283 | static struct dentry *binary_runtime_measurements; | 285 | static struct dentry *binary_runtime_measurements; |
284 | static struct dentry *ascii_runtime_measurements; | 286 | static struct dentry *ascii_runtime_measurements; |
285 | static struct dentry *runtime_measurements_count; | 287 | static struct dentry *runtime_measurements_count; |
286 | static struct dentry *violations; | 288 | static struct dentry *violations; |
287 | static struct dentry *ima_policy; | 289 | static struct dentry *ima_policy; |
288 | 290 | ||
289 | static atomic_t policy_opencount = ATOMIC_INIT(1); | 291 | static atomic_t policy_opencount = ATOMIC_INIT(1); |
290 | /* | 292 | /* |
291 | * ima_open_policy: sequentialize access to the policy file | 293 | * ima_open_policy: sequentialize access to the policy file |
292 | */ | 294 | */ |
293 | static int ima_open_policy(struct inode * inode, struct file * filp) | 295 | static int ima_open_policy(struct inode * inode, struct file * filp) |
294 | { | 296 | { |
295 | /* No point in being allowed to open it if you aren't going to write */ | 297 | /* No point in being allowed to open it if you aren't going to write */ |
296 | if (!(filp->f_flags & O_WRONLY)) | 298 | if (!(filp->f_flags & O_WRONLY)) |
297 | return -EACCES; | 299 | return -EACCES; |
298 | if (atomic_dec_and_test(&policy_opencount)) | 300 | if (atomic_dec_and_test(&policy_opencount)) |
299 | return 0; | 301 | return 0; |
300 | return -EBUSY; | 302 | return -EBUSY; |
301 | } | 303 | } |
302 | 304 | ||
303 | /* | 305 | /* |
304 | * ima_release_policy - start using the new measure policy rules. | 306 | * ima_release_policy - start using the new measure policy rules. |
305 | * | 307 | * |
306 | * Initially, ima_measure points to the default policy rules, now | 308 | * Initially, ima_measure points to the default policy rules, now |
307 | * point to the new policy rules, and remove the securityfs policy file, | 309 | * point to the new policy rules, and remove the securityfs policy file, |
308 | * assuming a valid policy. | 310 | * assuming a valid policy. |
309 | */ | 311 | */ |
310 | static int ima_release_policy(struct inode *inode, struct file *file) | 312 | static int ima_release_policy(struct inode *inode, struct file *file) |
311 | { | 313 | { |
312 | if (!valid_policy) { | 314 | if (!valid_policy) { |
313 | ima_delete_rules(); | 315 | ima_delete_rules(); |
314 | valid_policy = 1; | 316 | valid_policy = 1; |
315 | atomic_set(&policy_opencount, 1); | 317 | atomic_set(&policy_opencount, 1); |
316 | return 0; | 318 | return 0; |
317 | } | 319 | } |
318 | ima_update_policy(); | 320 | ima_update_policy(); |
319 | securityfs_remove(ima_policy); | 321 | securityfs_remove(ima_policy); |
320 | ima_policy = NULL; | 322 | ima_policy = NULL; |
321 | return 0; | 323 | return 0; |
322 | } | 324 | } |
323 | 325 | ||
324 | static const struct file_operations ima_measure_policy_ops = { | 326 | static const struct file_operations ima_measure_policy_ops = { |
325 | .open = ima_open_policy, | 327 | .open = ima_open_policy, |
326 | .write = ima_write_policy, | 328 | .write = ima_write_policy, |
327 | .release = ima_release_policy, | 329 | .release = ima_release_policy, |
328 | .llseek = generic_file_llseek, | 330 | .llseek = generic_file_llseek, |
329 | }; | 331 | }; |
330 | 332 | ||
331 | int __init ima_fs_init(void) | 333 | int __init ima_fs_init(void) |
332 | { | 334 | { |
333 | ima_dir = securityfs_create_dir("ima", NULL); | 335 | ima_dir = securityfs_create_dir("ima", NULL); |
334 | if (IS_ERR(ima_dir)) | 336 | if (IS_ERR(ima_dir)) |
335 | return -1; | 337 | return -1; |
336 | 338 | ||
337 | binary_runtime_measurements = | 339 | binary_runtime_measurements = |
338 | securityfs_create_file("binary_runtime_measurements", | 340 | securityfs_create_file("binary_runtime_measurements", |
339 | S_IRUSR | S_IRGRP, ima_dir, NULL, | 341 | S_IRUSR | S_IRGRP, ima_dir, NULL, |
340 | &ima_measurements_ops); | 342 | &ima_measurements_ops); |
341 | if (IS_ERR(binary_runtime_measurements)) | 343 | if (IS_ERR(binary_runtime_measurements)) |
342 | goto out; | 344 | goto out; |
343 | 345 | ||
344 | ascii_runtime_measurements = | 346 | ascii_runtime_measurements = |
345 | securityfs_create_file("ascii_runtime_measurements", | 347 | securityfs_create_file("ascii_runtime_measurements", |
346 | S_IRUSR | S_IRGRP, ima_dir, NULL, | 348 | S_IRUSR | S_IRGRP, ima_dir, NULL, |
347 | &ima_ascii_measurements_ops); | 349 | &ima_ascii_measurements_ops); |
348 | if (IS_ERR(ascii_runtime_measurements)) | 350 | if (IS_ERR(ascii_runtime_measurements)) |
349 | goto out; | 351 | goto out; |
350 | 352 | ||
351 | runtime_measurements_count = | 353 | runtime_measurements_count = |
352 | securityfs_create_file("runtime_measurements_count", | 354 | securityfs_create_file("runtime_measurements_count", |
353 | S_IRUSR | S_IRGRP, ima_dir, NULL, | 355 | S_IRUSR | S_IRGRP, ima_dir, NULL, |
354 | &ima_measurements_count_ops); | 356 | &ima_measurements_count_ops); |
355 | if (IS_ERR(runtime_measurements_count)) | 357 | if (IS_ERR(runtime_measurements_count)) |
356 | goto out; | 358 | goto out; |
357 | 359 | ||
358 | violations = | 360 | violations = |
359 | securityfs_create_file("violations", S_IRUSR | S_IRGRP, | 361 | securityfs_create_file("violations", S_IRUSR | S_IRGRP, |
360 | ima_dir, NULL, &ima_htable_violations_ops); | 362 | ima_dir, NULL, &ima_htable_violations_ops); |
361 | if (IS_ERR(violations)) | 363 | if (IS_ERR(violations)) |
362 | goto out; | 364 | goto out; |
363 | 365 | ||
364 | ima_policy = securityfs_create_file("policy", | 366 | ima_policy = securityfs_create_file("policy", |
365 | S_IWUSR, | 367 | S_IWUSR, |
366 | ima_dir, NULL, | 368 | ima_dir, NULL, |
367 | &ima_measure_policy_ops); | 369 | &ima_measure_policy_ops); |
368 | if (IS_ERR(ima_policy)) | 370 | if (IS_ERR(ima_policy)) |
369 | goto out; | 371 | goto out; |
370 | 372 | ||
371 | return 0; | 373 | return 0; |
372 | out: | 374 | out: |
373 | securityfs_remove(violations); | 375 | securityfs_remove(violations); |
374 | securityfs_remove(runtime_measurements_count); | 376 | securityfs_remove(runtime_measurements_count); |
375 | securityfs_remove(ascii_runtime_measurements); | 377 | securityfs_remove(ascii_runtime_measurements); |
376 | securityfs_remove(binary_runtime_measurements); | 378 | securityfs_remove(binary_runtime_measurements); |
377 | securityfs_remove(ima_dir); | 379 | securityfs_remove(ima_dir); |
378 | securityfs_remove(ima_policy); | 380 | securityfs_remove(ima_policy); |
379 | return -1; | 381 | return -1; |
380 | } | 382 | } |
381 | 383 |
security/integrity/ima/ima_template_lib.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2013 Politecnico di Torino, Italy | 2 | * Copyright (C) 2013 Politecnico di Torino, Italy |
3 | * TORSEC group -- http://security.polito.it | 3 | * TORSEC group -- http://security.polito.it |
4 | * | 4 | * |
5 | * Author: Roberto Sassu <roberto.sassu@polito.it> | 5 | * Author: Roberto Sassu <roberto.sassu@polito.it> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 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 | 8 | * modify it under the terms of the GNU General Public License as |
9 | * published by the Free Software Foundation, version 2 of the | 9 | * published by the Free Software Foundation, version 2 of the |
10 | * License. | 10 | * License. |
11 | * | 11 | * |
12 | * File: ima_template_lib.c | 12 | * File: ima_template_lib.c |
13 | * Library of supported template fields. | 13 | * Library of supported template fields. |
14 | */ | 14 | */ |
15 | #include <crypto/hash_info.h> | 15 | #include <crypto/hash_info.h> |
16 | 16 | ||
17 | #include "ima_template_lib.h" | 17 | #include "ima_template_lib.h" |
18 | 18 | ||
19 | static bool ima_template_hash_algo_allowed(u8 algo) | 19 | static bool ima_template_hash_algo_allowed(u8 algo) |
20 | { | 20 | { |
21 | if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5) | 21 | if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5) |
22 | return true; | 22 | return true; |
23 | 23 | ||
24 | return false; | 24 | return false; |
25 | } | 25 | } |
26 | 26 | ||
27 | enum data_formats { | 27 | enum data_formats { |
28 | DATA_FMT_DIGEST = 0, | 28 | DATA_FMT_DIGEST = 0, |
29 | DATA_FMT_DIGEST_WITH_ALGO, | 29 | DATA_FMT_DIGEST_WITH_ALGO, |
30 | DATA_FMT_EVENT_NAME, | 30 | DATA_FMT_EVENT_NAME, |
31 | DATA_FMT_STRING, | 31 | DATA_FMT_STRING, |
32 | DATA_FMT_HEX | 32 | DATA_FMT_HEX |
33 | }; | 33 | }; |
34 | 34 | ||
35 | static int ima_write_template_field_data(const void *data, const u32 datalen, | 35 | static int ima_write_template_field_data(const void *data, const u32 datalen, |
36 | enum data_formats datafmt, | 36 | enum data_formats datafmt, |
37 | struct ima_field_data *field_data) | 37 | struct ima_field_data *field_data) |
38 | { | 38 | { |
39 | u8 *buf, *buf_ptr; | 39 | u8 *buf, *buf_ptr; |
40 | u32 buflen; | 40 | u32 buflen; |
41 | 41 | ||
42 | switch (datafmt) { | 42 | switch (datafmt) { |
43 | case DATA_FMT_EVENT_NAME: | 43 | case DATA_FMT_EVENT_NAME: |
44 | buflen = IMA_EVENT_NAME_LEN_MAX + 1; | 44 | buflen = IMA_EVENT_NAME_LEN_MAX + 1; |
45 | break; | 45 | break; |
46 | case DATA_FMT_STRING: | 46 | case DATA_FMT_STRING: |
47 | buflen = datalen + 1; | 47 | buflen = datalen + 1; |
48 | break; | 48 | break; |
49 | default: | 49 | default: |
50 | buflen = datalen; | 50 | buflen = datalen; |
51 | } | 51 | } |
52 | 52 | ||
53 | buf = kzalloc(buflen, GFP_KERNEL); | 53 | buf = kzalloc(buflen, GFP_KERNEL); |
54 | if (!buf) | 54 | if (!buf) |
55 | return -ENOMEM; | 55 | return -ENOMEM; |
56 | 56 | ||
57 | memcpy(buf, data, datalen); | 57 | memcpy(buf, data, datalen); |
58 | 58 | ||
59 | /* | 59 | /* |
60 | * Replace all space characters with underscore for event names and | 60 | * Replace all space characters with underscore for event names and |
61 | * strings. This avoid that, during the parsing of a measurements list, | 61 | * strings. This avoid that, during the parsing of a measurements list, |
62 | * filenames with spaces or that end with the suffix ' (deleted)' are | 62 | * filenames with spaces or that end with the suffix ' (deleted)' are |
63 | * split into multiple template fields (the space is the delimitator | 63 | * split into multiple template fields (the space is the delimitator |
64 | * character for measurements lists in ASCII format). | 64 | * character for measurements lists in ASCII format). |
65 | */ | 65 | */ |
66 | if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) { | 66 | if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) { |
67 | for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++) | 67 | for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++) |
68 | if (*buf_ptr == ' ') | 68 | if (*buf_ptr == ' ') |
69 | *buf_ptr = '_'; | 69 | *buf_ptr = '_'; |
70 | } | 70 | } |
71 | 71 | ||
72 | field_data->data = buf; | 72 | field_data->data = buf; |
73 | field_data->len = buflen; | 73 | field_data->len = buflen; |
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | static void ima_show_template_data_ascii(struct seq_file *m, | 77 | static void ima_show_template_data_ascii(struct seq_file *m, |
78 | enum ima_show_type show, | 78 | enum ima_show_type show, |
79 | enum data_formats datafmt, | 79 | enum data_formats datafmt, |
80 | struct ima_field_data *field_data) | 80 | struct ima_field_data *field_data) |
81 | { | 81 | { |
82 | u8 *buf_ptr = field_data->data, buflen = field_data->len; | 82 | u8 *buf_ptr = field_data->data, buflen = field_data->len; |
83 | 83 | ||
84 | switch (datafmt) { | 84 | switch (datafmt) { |
85 | case DATA_FMT_DIGEST_WITH_ALGO: | 85 | case DATA_FMT_DIGEST_WITH_ALGO: |
86 | buf_ptr = strnchr(field_data->data, buflen, ':'); | 86 | buf_ptr = strnchr(field_data->data, buflen, ':'); |
87 | if (buf_ptr != field_data->data) | 87 | if (buf_ptr != field_data->data) |
88 | seq_printf(m, "%s", field_data->data); | 88 | seq_printf(m, "%s", field_data->data); |
89 | 89 | ||
90 | /* skip ':' and '\0' */ | 90 | /* skip ':' and '\0' */ |
91 | buf_ptr += 2; | 91 | buf_ptr += 2; |
92 | buflen -= buf_ptr - field_data->data; | 92 | buflen -= buf_ptr - field_data->data; |
93 | case DATA_FMT_DIGEST: | 93 | case DATA_FMT_DIGEST: |
94 | case DATA_FMT_HEX: | 94 | case DATA_FMT_HEX: |
95 | if (!buflen) | 95 | if (!buflen) |
96 | break; | 96 | break; |
97 | ima_print_digest(m, buf_ptr, buflen); | 97 | ima_print_digest(m, buf_ptr, buflen); |
98 | break; | 98 | break; |
99 | case DATA_FMT_STRING: | 99 | case DATA_FMT_STRING: |
100 | seq_printf(m, "%s", buf_ptr); | 100 | seq_printf(m, "%s", buf_ptr); |
101 | break; | 101 | break; |
102 | default: | 102 | default: |
103 | break; | 103 | break; |
104 | } | 104 | } |
105 | } | 105 | } |
106 | 106 | ||
107 | static void ima_show_template_data_binary(struct seq_file *m, | 107 | static void ima_show_template_data_binary(struct seq_file *m, |
108 | enum ima_show_type show, | 108 | enum ima_show_type show, |
109 | enum data_formats datafmt, | 109 | enum data_formats datafmt, |
110 | struct ima_field_data *field_data) | 110 | struct ima_field_data *field_data) |
111 | { | 111 | { |
112 | u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ? | ||
113 | strlen(field_data->data) : field_data->len; | ||
114 | |||
112 | if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) | 115 | if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) |
113 | ima_putc(m, &field_data->len, sizeof(u32)); | 116 | ima_putc(m, &len, sizeof(len)); |
114 | 117 | ||
115 | if (!field_data->len) | 118 | if (!len) |
116 | return; | 119 | return; |
117 | 120 | ||
118 | ima_putc(m, field_data->data, field_data->len); | 121 | ima_putc(m, field_data->data, len); |
119 | } | 122 | } |
120 | 123 | ||
121 | static void ima_show_template_field_data(struct seq_file *m, | 124 | static void ima_show_template_field_data(struct seq_file *m, |
122 | enum ima_show_type show, | 125 | enum ima_show_type show, |
123 | enum data_formats datafmt, | 126 | enum data_formats datafmt, |
124 | struct ima_field_data *field_data) | 127 | struct ima_field_data *field_data) |
125 | { | 128 | { |
126 | switch (show) { | 129 | switch (show) { |
127 | case IMA_SHOW_ASCII: | 130 | case IMA_SHOW_ASCII: |
128 | ima_show_template_data_ascii(m, show, datafmt, field_data); | 131 | ima_show_template_data_ascii(m, show, datafmt, field_data); |
129 | break; | 132 | break; |
130 | case IMA_SHOW_BINARY: | 133 | case IMA_SHOW_BINARY: |
131 | case IMA_SHOW_BINARY_NO_FIELD_LEN: | 134 | case IMA_SHOW_BINARY_NO_FIELD_LEN: |
135 | case IMA_SHOW_BINARY_OLD_STRING_FMT: | ||
132 | ima_show_template_data_binary(m, show, datafmt, field_data); | 136 | ima_show_template_data_binary(m, show, datafmt, field_data); |
133 | break; | 137 | break; |
134 | default: | 138 | default: |
135 | break; | 139 | break; |
136 | } | 140 | } |
137 | } | 141 | } |
138 | 142 | ||
139 | void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, | 143 | void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, |
140 | struct ima_field_data *field_data) | 144 | struct ima_field_data *field_data) |
141 | { | 145 | { |
142 | ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data); | 146 | ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data); |
143 | } | 147 | } |
144 | 148 | ||
145 | void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, | 149 | void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, |
146 | struct ima_field_data *field_data) | 150 | struct ima_field_data *field_data) |
147 | { | 151 | { |
148 | ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO, | 152 | ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO, |
149 | field_data); | 153 | field_data); |
150 | } | 154 | } |
151 | 155 | ||
152 | void ima_show_template_string(struct seq_file *m, enum ima_show_type show, | 156 | void ima_show_template_string(struct seq_file *m, enum ima_show_type show, |
153 | struct ima_field_data *field_data) | 157 | struct ima_field_data *field_data) |
154 | { | 158 | { |
155 | ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); | 159 | ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); |
156 | } | 160 | } |
157 | 161 | ||
158 | void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, | 162 | void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, |
159 | struct ima_field_data *field_data) | 163 | struct ima_field_data *field_data) |
160 | { | 164 | { |
161 | ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data); | 165 | ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data); |
162 | } | 166 | } |
163 | 167 | ||
164 | static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, | 168 | static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, |
165 | struct ima_field_data *field_data) | 169 | struct ima_field_data *field_data) |
166 | { | 170 | { |
167 | /* | 171 | /* |
168 | * digest formats: | 172 | * digest formats: |
169 | * - DATA_FMT_DIGEST: digest | 173 | * - DATA_FMT_DIGEST: digest |
170 | * - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest, | 174 | * - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest, |
171 | * where <hash algo> is provided if the hash algoritm is not | 175 | * where <hash algo> is provided if the hash algoritm is not |
172 | * SHA1 or MD5 | 176 | * SHA1 or MD5 |
173 | */ | 177 | */ |
174 | u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 }; | 178 | u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 }; |
175 | enum data_formats fmt = DATA_FMT_DIGEST; | 179 | enum data_formats fmt = DATA_FMT_DIGEST; |
176 | u32 offset = 0; | 180 | u32 offset = 0; |
177 | 181 | ||
178 | if (hash_algo < HASH_ALGO__LAST) { | 182 | if (hash_algo < HASH_ALGO__LAST) { |
179 | fmt = DATA_FMT_DIGEST_WITH_ALGO; | 183 | fmt = DATA_FMT_DIGEST_WITH_ALGO; |
180 | offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s", | 184 | offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s", |
181 | hash_algo_name[hash_algo]); | 185 | hash_algo_name[hash_algo]); |
182 | buffer[offset] = ':'; | 186 | buffer[offset] = ':'; |
183 | offset += 2; | 187 | offset += 2; |
184 | } | 188 | } |
185 | 189 | ||
186 | if (digest) | 190 | if (digest) |
187 | memcpy(buffer + offset, digest, digestsize); | 191 | memcpy(buffer + offset, digest, digestsize); |
188 | else | 192 | else |
189 | /* | 193 | /* |
190 | * If digest is NULL, the event being recorded is a violation. | 194 | * If digest is NULL, the event being recorded is a violation. |
191 | * Make room for the digest by increasing the offset of | 195 | * Make room for the digest by increasing the offset of |
192 | * IMA_DIGEST_SIZE. | 196 | * IMA_DIGEST_SIZE. |
193 | */ | 197 | */ |
194 | offset += IMA_DIGEST_SIZE; | 198 | offset += IMA_DIGEST_SIZE; |
195 | 199 | ||
196 | return ima_write_template_field_data(buffer, offset + digestsize, | 200 | return ima_write_template_field_data(buffer, offset + digestsize, |
197 | fmt, field_data); | 201 | fmt, field_data); |
198 | } | 202 | } |
199 | 203 | ||
200 | /* | 204 | /* |
201 | * This function writes the digest of an event (with size limit). | 205 | * This function writes the digest of an event (with size limit). |
202 | */ | 206 | */ |
203 | int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, | 207 | int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, |
204 | const unsigned char *filename, | 208 | const unsigned char *filename, |
205 | struct evm_ima_xattr_data *xattr_value, int xattr_len, | 209 | struct evm_ima_xattr_data *xattr_value, int xattr_len, |
206 | struct ima_field_data *field_data) | 210 | struct ima_field_data *field_data) |
207 | { | 211 | { |
208 | struct { | 212 | struct { |
209 | struct ima_digest_data hdr; | 213 | struct ima_digest_data hdr; |
210 | char digest[IMA_MAX_DIGEST_SIZE]; | 214 | char digest[IMA_MAX_DIGEST_SIZE]; |
211 | } hash; | 215 | } hash; |
212 | u8 *cur_digest = NULL; | 216 | u8 *cur_digest = NULL; |
213 | u32 cur_digestsize = 0; | 217 | u32 cur_digestsize = 0; |
214 | struct inode *inode; | 218 | struct inode *inode; |
215 | int result; | 219 | int result; |
216 | 220 | ||
217 | memset(&hash, 0, sizeof(hash)); | 221 | memset(&hash, 0, sizeof(hash)); |
218 | 222 | ||
219 | if (!iint) /* recording a violation. */ | 223 | if (!iint) /* recording a violation. */ |
220 | goto out; | 224 | goto out; |
221 | 225 | ||
222 | if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) { | 226 | if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) { |
223 | cur_digest = iint->ima_hash->digest; | 227 | cur_digest = iint->ima_hash->digest; |
224 | cur_digestsize = iint->ima_hash->length; | 228 | cur_digestsize = iint->ima_hash->length; |
225 | goto out; | 229 | goto out; |
226 | } | 230 | } |
227 | 231 | ||
228 | if (!file) /* missing info to re-calculate the digest */ | 232 | if (!file) /* missing info to re-calculate the digest */ |
229 | return -EINVAL; | 233 | return -EINVAL; |
230 | 234 | ||
231 | inode = file_inode(file); | 235 | inode = file_inode(file); |
232 | hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ? | 236 | hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ? |
233 | ima_hash_algo : HASH_ALGO_SHA1; | 237 | ima_hash_algo : HASH_ALGO_SHA1; |
234 | result = ima_calc_file_hash(file, &hash.hdr); | 238 | result = ima_calc_file_hash(file, &hash.hdr); |
235 | if (result) { | 239 | if (result) { |
236 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, | 240 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, |
237 | filename, "collect_data", | 241 | filename, "collect_data", |
238 | "failed", result, 0); | 242 | "failed", result, 0); |
239 | return result; | 243 | return result; |
240 | } | 244 | } |
241 | cur_digest = hash.hdr.digest; | 245 | cur_digest = hash.hdr.digest; |
242 | cur_digestsize = hash.hdr.length; | 246 | cur_digestsize = hash.hdr.length; |
243 | out: | 247 | out: |
244 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, | 248 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, |
245 | HASH_ALGO__LAST, field_data); | 249 | HASH_ALGO__LAST, field_data); |
246 | } | 250 | } |
247 | 251 | ||
248 | /* | 252 | /* |
249 | * This function writes the digest of an event (without size limit). | 253 | * This function writes the digest of an event (without size limit). |
250 | */ | 254 | */ |
251 | int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, | 255 | int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, |
252 | struct file *file, const unsigned char *filename, | 256 | struct file *file, const unsigned char *filename, |
253 | struct evm_ima_xattr_data *xattr_value, | 257 | struct evm_ima_xattr_data *xattr_value, |
254 | int xattr_len, struct ima_field_data *field_data) | 258 | int xattr_len, struct ima_field_data *field_data) |
255 | { | 259 | { |
256 | u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1; | 260 | u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1; |
257 | u32 cur_digestsize = 0; | 261 | u32 cur_digestsize = 0; |
258 | 262 | ||
259 | /* If iint is NULL, we are recording a violation. */ | 263 | /* If iint is NULL, we are recording a violation. */ |
260 | if (!iint) | 264 | if (!iint) |
261 | goto out; | 265 | goto out; |
262 | 266 | ||
263 | cur_digest = iint->ima_hash->digest; | 267 | cur_digest = iint->ima_hash->digest; |
264 | cur_digestsize = iint->ima_hash->length; | 268 | cur_digestsize = iint->ima_hash->length; |
265 | 269 | ||
266 | hash_algo = iint->ima_hash->algo; | 270 | hash_algo = iint->ima_hash->algo; |
267 | out: | 271 | out: |
268 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, | 272 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, |
269 | hash_algo, field_data); | 273 | hash_algo, field_data); |
270 | } | 274 | } |
271 | 275 | ||
272 | static int ima_eventname_init_common(struct integrity_iint_cache *iint, | 276 | static int ima_eventname_init_common(struct integrity_iint_cache *iint, |
273 | struct file *file, | 277 | struct file *file, |
274 | const unsigned char *filename, | 278 | const unsigned char *filename, |
275 | struct ima_field_data *field_data, | 279 | struct ima_field_data *field_data, |
276 | bool size_limit) | 280 | bool size_limit) |
277 | { | 281 | { |
278 | const char *cur_filename = NULL; | 282 | const char *cur_filename = NULL; |
279 | u32 cur_filename_len = 0; | 283 | u32 cur_filename_len = 0; |
280 | enum data_formats fmt = size_limit ? | 284 | enum data_formats fmt = size_limit ? |
281 | DATA_FMT_EVENT_NAME : DATA_FMT_STRING; | 285 | DATA_FMT_EVENT_NAME : DATA_FMT_STRING; |
282 | 286 | ||
283 | BUG_ON(filename == NULL && file == NULL); | 287 | BUG_ON(filename == NULL && file == NULL); |
284 | 288 | ||
285 | if (filename) { | 289 | if (filename) { |
286 | cur_filename = filename; | 290 | cur_filename = filename; |
287 | cur_filename_len = strlen(filename); | 291 | cur_filename_len = strlen(filename); |
288 | 292 | ||
289 | if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX) | 293 | if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX) |
290 | goto out; | 294 | goto out; |
291 | } | 295 | } |
292 | 296 | ||
293 | if (file) { | 297 | if (file) { |
294 | cur_filename = file->f_dentry->d_name.name; | 298 | cur_filename = file->f_dentry->d_name.name; |
295 | cur_filename_len = strlen(cur_filename); | 299 | cur_filename_len = strlen(cur_filename); |
296 | } else | 300 | } else |
297 | /* | 301 | /* |
298 | * Truncate filename if the latter is too long and | 302 | * Truncate filename if the latter is too long and |
299 | * the file descriptor is not available. | 303 | * the file descriptor is not available. |
300 | */ | 304 | */ |
301 | cur_filename_len = IMA_EVENT_NAME_LEN_MAX; | 305 | cur_filename_len = IMA_EVENT_NAME_LEN_MAX; |
302 | out: | 306 | out: |
303 | return ima_write_template_field_data(cur_filename, cur_filename_len, | 307 | return ima_write_template_field_data(cur_filename, cur_filename_len, |
304 | fmt, field_data); | 308 | fmt, field_data); |
305 | } | 309 | } |
306 | 310 | ||
307 | /* | 311 | /* |
308 | * This function writes the name of an event (with size limit). | 312 | * This function writes the name of an event (with size limit). |
309 | */ | 313 | */ |
310 | int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, | 314 | int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, |
311 | const unsigned char *filename, | 315 | const unsigned char *filename, |
312 | struct evm_ima_xattr_data *xattr_value, int xattr_len, | 316 | struct evm_ima_xattr_data *xattr_value, int xattr_len, |
313 | struct ima_field_data *field_data) | 317 | struct ima_field_data *field_data) |
314 | { | 318 | { |
315 | return ima_eventname_init_common(iint, file, filename, | 319 | return ima_eventname_init_common(iint, file, filename, |
316 | field_data, true); | 320 | field_data, true); |
317 | } | 321 | } |
318 | 322 | ||
319 | /* | 323 | /* |
320 | * This function writes the name of an event (without size limit). | 324 | * This function writes the name of an event (without size limit). |
321 | */ | 325 | */ |
322 | int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file, | 326 | int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file, |
323 | const unsigned char *filename, | 327 | const unsigned char *filename, |
324 | struct evm_ima_xattr_data *xattr_value, int xattr_len, | 328 | struct evm_ima_xattr_data *xattr_value, int xattr_len, |
325 | struct ima_field_data *field_data) | 329 | struct ima_field_data *field_data) |
326 | { | 330 | { |
327 | return ima_eventname_init_common(iint, file, filename, | 331 | return ima_eventname_init_common(iint, file, filename, |
328 | field_data, false); | 332 | field_data, false); |
329 | } | 333 | } |
330 | 334 | ||
331 | /* | 335 | /* |
332 | * ima_eventsig_init - include the file signature as part of the template data | 336 | * ima_eventsig_init - include the file signature as part of the template data |
333 | */ | 337 | */ |
334 | int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file, | 338 | int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file, |
335 | const unsigned char *filename, | 339 | const unsigned char *filename, |
336 | struct evm_ima_xattr_data *xattr_value, int xattr_len, | 340 | struct evm_ima_xattr_data *xattr_value, int xattr_len, |
337 | struct ima_field_data *field_data) | 341 | struct ima_field_data *field_data) |
338 | { | 342 | { |
339 | enum data_formats fmt = DATA_FMT_HEX; | 343 | enum data_formats fmt = DATA_FMT_HEX; |
340 | int rc = 0; | 344 | int rc = 0; |
341 | 345 | ||
342 | if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG)) | 346 | if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG)) |
343 | goto out; | 347 | goto out; |
344 | 348 | ||
345 | rc = ima_write_template_field_data(xattr_value, xattr_len, fmt, | 349 | rc = ima_write_template_field_data(xattr_value, xattr_len, fmt, |
346 | field_data); | 350 | field_data); |
347 | out: | 351 | out: |
348 | return rc; | 352 | return rc; |
349 | } | 353 | } |
350 | 354 |