xref: /linux/security/integrity/ima/ima_fs.c (revision 4af4662fa4a9dc62289c580337ae2506339c4729)
1 /*
2  * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3  *
4  * Authors:
5  * Kylene Hall <kjhall@us.ibm.com>
6  * Reiner Sailer <sailer@us.ibm.com>
7  * Mimi Zohar <zohar@us.ibm.com>
8  *
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
11  * published by the Free Software Foundation, version 2 of the
12  * License.
13  *
14  * File: ima_fs.c
15  *	implemenents security file system for reporting
16  *	current measurement list and IMA statistics
17  */
18 #include <linux/module.h>
19 #include <linux/seq_file.h>
20 #include <linux/rculist.h>
21 #include <linux/rcupdate.h>
22 #include <linux/parser.h>
23 
24 #include "ima.h"
25 
26 static int valid_policy = 1;
27 #define TMPBUFLEN 12
28 static ssize_t ima_show_htable_value(char __user *buf, size_t count,
29 				     loff_t *ppos, atomic_long_t *val)
30 {
31 	char tmpbuf[TMPBUFLEN];
32 	ssize_t len;
33 
34 	len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
35 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
36 }
37 
38 static ssize_t ima_show_htable_violations(struct file *filp,
39 					  char __user *buf,
40 					  size_t count, loff_t *ppos)
41 {
42 	return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
43 }
44 
45 static struct file_operations ima_htable_violations_ops = {
46 	.read = ima_show_htable_violations
47 };
48 
49 static ssize_t ima_show_measurements_count(struct file *filp,
50 					   char __user *buf,
51 					   size_t count, loff_t *ppos)
52 {
53 	return ima_show_htable_value(buf, count, ppos, &ima_htable.len);
54 
55 }
56 
57 static struct file_operations ima_measurements_count_ops = {
58 	.read = ima_show_measurements_count
59 };
60 
61 /* returns pointer to hlist_node */
62 static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
63 {
64 	loff_t l = *pos;
65 	struct ima_queue_entry *qe;
66 
67 	/* we need a lock since pos could point beyond last element */
68 	rcu_read_lock();
69 	list_for_each_entry_rcu(qe, &ima_measurements, later) {
70 		if (!l--) {
71 			rcu_read_unlock();
72 			return qe;
73 		}
74 	}
75 	rcu_read_unlock();
76 	return NULL;
77 }
78 
79 static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
80 {
81 	struct ima_queue_entry *qe = v;
82 
83 	/* lock protects when reading beyond last element
84 	 * against concurrent list-extension
85 	 */
86 	rcu_read_lock();
87 	qe = list_entry(rcu_dereference(qe->later.next),
88 			struct ima_queue_entry, later);
89 	rcu_read_unlock();
90 	(*pos)++;
91 
92 	return (&qe->later == &ima_measurements) ? NULL : qe;
93 }
94 
95 static void ima_measurements_stop(struct seq_file *m, void *v)
96 {
97 }
98 
99 static void ima_putc(struct seq_file *m, void *data, int datalen)
100 {
101 	while (datalen--)
102 		seq_putc(m, *(char *)data++);
103 }
104 
105 /* print format:
106  *       32bit-le=pcr#
107  *       char[20]=template digest
108  *       32bit-le=template name size
109  *       char[n]=template name
110  *       eventdata[n]=template specific data
111  */
112 static int ima_measurements_show(struct seq_file *m, void *v)
113 {
114 	/* the list never shrinks, so we don't need a lock here */
115 	struct ima_queue_entry *qe = v;
116 	struct ima_template_entry *e;
117 	int namelen;
118 	u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
119 
120 	/* get entry */
121 	e = qe->entry;
122 	if (e == NULL)
123 		return -1;
124 
125 	/*
126 	 * 1st: PCRIndex
127 	 * PCR used is always the same (config option) in
128 	 * little-endian format
129 	 */
130 	ima_putc(m, &pcr, sizeof pcr);
131 
132 	/* 2nd: template digest */
133 	ima_putc(m, e->digest, IMA_DIGEST_SIZE);
134 
135 	/* 3rd: template name size */
136 	namelen = strlen(e->template_name);
137 	ima_putc(m, &namelen, sizeof namelen);
138 
139 	/* 4th:  template name */
140 	ima_putc(m, e->template_name, namelen);
141 
142 	/* 5th:  template specific data */
143 	ima_template_show(m, (struct ima_template_data *)&e->template,
144 			  IMA_SHOW_BINARY);
145 	return 0;
146 }
147 
148 static struct seq_operations ima_measurments_seqops = {
149 	.start = ima_measurements_start,
150 	.next = ima_measurements_next,
151 	.stop = ima_measurements_stop,
152 	.show = ima_measurements_show
153 };
154 
155 static int ima_measurements_open(struct inode *inode, struct file *file)
156 {
157 	return seq_open(file, &ima_measurments_seqops);
158 }
159 
160 static struct file_operations ima_measurements_ops = {
161 	.open = ima_measurements_open,
162 	.read = seq_read,
163 	.llseek = seq_lseek,
164 	.release = seq_release,
165 };
166 
167 static void ima_print_digest(struct seq_file *m, u8 *digest)
168 {
169 	int i;
170 
171 	for (i = 0; i < IMA_DIGEST_SIZE; i++)
172 		seq_printf(m, "%02x", *(digest + i));
173 }
174 
175 void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
176 {
177 	struct ima_template_data *entry = e;
178 	int namelen;
179 
180 	switch (show) {
181 	case IMA_SHOW_ASCII:
182 		ima_print_digest(m, entry->digest);
183 		seq_printf(m, " %s\n", entry->file_name);
184 		break;
185 	case IMA_SHOW_BINARY:
186 		ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
187 
188 		namelen = strlen(entry->file_name);
189 		ima_putc(m, &namelen, sizeof namelen);
190 		ima_putc(m, entry->file_name, namelen);
191 	default:
192 		break;
193 	}
194 }
195 
196 /* print in ascii */
197 static int ima_ascii_measurements_show(struct seq_file *m, void *v)
198 {
199 	/* the list never shrinks, so we don't need a lock here */
200 	struct ima_queue_entry *qe = v;
201 	struct ima_template_entry *e;
202 
203 	/* get entry */
204 	e = qe->entry;
205 	if (e == NULL)
206 		return -1;
207 
208 	/* 1st: PCR used (config option) */
209 	seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
210 
211 	/* 2nd: SHA1 template hash */
212 	ima_print_digest(m, e->digest);
213 
214 	/* 3th:  template name */
215 	seq_printf(m, " %s ", e->template_name);
216 
217 	/* 4th:  template specific data */
218 	ima_template_show(m, (struct ima_template_data *)&e->template,
219 			  IMA_SHOW_ASCII);
220 	return 0;
221 }
222 
223 static struct seq_operations ima_ascii_measurements_seqops = {
224 	.start = ima_measurements_start,
225 	.next = ima_measurements_next,
226 	.stop = ima_measurements_stop,
227 	.show = ima_ascii_measurements_show
228 };
229 
230 static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
231 {
232 	return seq_open(file, &ima_ascii_measurements_seqops);
233 }
234 
235 static struct file_operations ima_ascii_measurements_ops = {
236 	.open = ima_ascii_measurements_open,
237 	.read = seq_read,
238 	.llseek = seq_lseek,
239 	.release = seq_release,
240 };
241 
242 static ssize_t ima_write_policy(struct file *file, const char __user *buf,
243 				size_t datalen, loff_t *ppos)
244 {
245 	char *data;
246 	int rc;
247 
248 	if (datalen >= PAGE_SIZE)
249 		return -ENOMEM;
250 	if (*ppos != 0) {
251 		/* No partial writes. */
252 		return -EINVAL;
253 	}
254 	data = kmalloc(datalen + 1, GFP_KERNEL);
255 	if (!data)
256 		return -ENOMEM;
257 
258 	if (copy_from_user(data, buf, datalen)) {
259 		kfree(data);
260 		return -EFAULT;
261 	}
262 	*(data + datalen) = '\0';
263 	rc = ima_parse_add_rule(data);
264 	if (rc < 0) {
265 		datalen = -EINVAL;
266 		valid_policy = 0;
267 	}
268 
269 	kfree(data);
270 	return datalen;
271 }
272 
273 static struct dentry *ima_dir;
274 static struct dentry *binary_runtime_measurements;
275 static struct dentry *ascii_runtime_measurements;
276 static struct dentry *runtime_measurements_count;
277 static struct dentry *violations;
278 static struct dentry *ima_policy;
279 
280 /*
281  * ima_release_policy - start using the new measure policy rules.
282  *
283  * Initially, ima_measure points to the default policy rules, now
284  * point to the new policy rules, and remove the securityfs policy file.
285  */
286 static int ima_release_policy(struct inode *inode, struct file *file)
287 {
288 	if (!valid_policy) {
289 		ima_delete_rules();
290 		return 0;
291 	}
292 	ima_update_policy();
293 	securityfs_remove(ima_policy);
294 	ima_policy = NULL;
295 	return 0;
296 }
297 
298 static struct file_operations ima_measure_policy_ops = {
299 	.write = ima_write_policy,
300 	.release = ima_release_policy
301 };
302 
303 int ima_fs_init(void)
304 {
305 	ima_dir = securityfs_create_dir("ima", NULL);
306 	if (IS_ERR(ima_dir))
307 		return -1;
308 
309 	binary_runtime_measurements =
310 	    securityfs_create_file("binary_runtime_measurements",
311 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
312 				   &ima_measurements_ops);
313 	if (IS_ERR(binary_runtime_measurements))
314 		goto out;
315 
316 	ascii_runtime_measurements =
317 	    securityfs_create_file("ascii_runtime_measurements",
318 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
319 				   &ima_ascii_measurements_ops);
320 	if (IS_ERR(ascii_runtime_measurements))
321 		goto out;
322 
323 	runtime_measurements_count =
324 	    securityfs_create_file("runtime_measurements_count",
325 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
326 				   &ima_measurements_count_ops);
327 	if (IS_ERR(runtime_measurements_count))
328 		goto out;
329 
330 	violations =
331 	    securityfs_create_file("violations", S_IRUSR | S_IRGRP,
332 				   ima_dir, NULL, &ima_htable_violations_ops);
333 	if (IS_ERR(violations))
334 		goto out;
335 
336 	ima_policy = securityfs_create_file("policy",
337 					    S_IRUSR | S_IRGRP | S_IWUSR,
338 					    ima_dir, NULL,
339 					    &ima_measure_policy_ops);
340 	if (IS_ERR(ima_policy))
341 		goto out;
342 
343 	return 0;
344 out:
345 	securityfs_remove(runtime_measurements_count);
346 	securityfs_remove(ascii_runtime_measurements);
347 	securityfs_remove(binary_runtime_measurements);
348 	securityfs_remove(ima_dir);
349 	securityfs_remove(ima_policy);
350 	return -1;
351 }
352 
353 void __exit ima_fs_cleanup(void)
354 {
355 	securityfs_remove(violations);
356 	securityfs_remove(runtime_measurements_count);
357 	securityfs_remove(ascii_runtime_measurements);
358 	securityfs_remove(binary_runtime_measurements);
359 	securityfs_remove(ima_dir);
360 	securityfs_remove(ima_policy);
361 }
362