Skip to content

Commit bab7393

Browse files
Mimi ZoharJames Morris
Mimi Zohar
authored and
James Morris
committed
integrity: IMA display
Make the measurement lists available through securityfs. - removed test for NULL return code from securityfs_create_file/dir Signed-off-by: Mimi Zohar <[email protected]> Acked-by: Serge Hallyn <[email protected]> Signed-off-by: James Morris <[email protected]>
1 parent 3323eec commit bab7393

File tree

5 files changed

+314
-2
lines changed

5 files changed

+314
-2
lines changed

security/integrity/ima/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55

66
obj-$(CONFIG_IMA) += ima.o
77

8-
ima-y := 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 \
99
ima_policy.o ima_iint.o ima_audit.o

security/integrity/ima/ima.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
6767
/* Internal IMA function definitions */
6868
void ima_iintcache_init(void);
6969
int ima_init(void);
70+
void ima_cleanup(void);
71+
int ima_fs_init(void);
72+
void ima_fs_cleanup(void);
7073
int ima_add_template_entry(struct ima_template_entry *entry, int violation,
7174
const char *op, struct inode *inode);
7275
int ima_calc_hash(struct file *file, char *digest);
@@ -115,6 +118,8 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
115118
const unsigned char *filename);
116119
int ima_store_template(struct ima_template_entry *entry, int violation,
117120
struct inode *inode);
121+
void ima_template_show(struct seq_file *m, void *e,
122+
enum ima_show_type show);
118123

119124
/* radix tree calls to lookup, insert, delete
120125
* integrity data associated with an inode.

security/integrity/ima/ima_fs.c

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*
2+
* Copyright (C) 2005,2006,2007,2008 IBM Corporation
3+
*
4+
* Authors:
5+
* Kylene Hall <[email protected]>
6+
* Reiner Sailer <[email protected]>
7+
* Mimi Zohar <[email protected]>
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+
23+
#include "ima.h"
24+
25+
#define TMPBUFLEN 12
26+
static ssize_t ima_show_htable_value(char __user *buf, size_t count,
27+
loff_t *ppos, atomic_long_t *val)
28+
{
29+
char tmpbuf[TMPBUFLEN];
30+
ssize_t len;
31+
32+
len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
33+
return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
34+
}
35+
36+
static ssize_t ima_show_htable_violations(struct file *filp,
37+
char __user *buf,
38+
size_t count, loff_t *ppos)
39+
{
40+
return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
41+
}
42+
43+
static struct file_operations ima_htable_violations_ops = {
44+
.read = ima_show_htable_violations
45+
};
46+
47+
static ssize_t ima_show_measurements_count(struct file *filp,
48+
char __user *buf,
49+
size_t count, loff_t *ppos)
50+
{
51+
return ima_show_htable_value(buf, count, ppos, &ima_htable.len);
52+
53+
}
54+
55+
static struct file_operations ima_measurements_count_ops = {
56+
.read = ima_show_measurements_count
57+
};
58+
59+
/* returns pointer to hlist_node */
60+
static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
61+
{
62+
loff_t l = *pos;
63+
struct ima_queue_entry *qe;
64+
65+
/* we need a lock since pos could point beyond last element */
66+
rcu_read_lock();
67+
list_for_each_entry_rcu(qe, &ima_measurements, later) {
68+
if (!l--) {
69+
rcu_read_unlock();
70+
return qe;
71+
}
72+
}
73+
rcu_read_unlock();
74+
return NULL;
75+
}
76+
77+
static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
78+
{
79+
struct ima_queue_entry *qe = v;
80+
81+
/* lock protects when reading beyond last element
82+
* against concurrent list-extension
83+
*/
84+
rcu_read_lock();
85+
qe = list_entry(rcu_dereference(qe->later.next),
86+
struct ima_queue_entry, later);
87+
rcu_read_unlock();
88+
(*pos)++;
89+
90+
return (&qe->later == &ima_measurements) ? NULL : qe;
91+
}
92+
93+
static void ima_measurements_stop(struct seq_file *m, void *v)
94+
{
95+
}
96+
97+
static void ima_putc(struct seq_file *m, void *data, int datalen)
98+
{
99+
while (datalen--)
100+
seq_putc(m, *(char *)data++);
101+
}
102+
103+
/* print format:
104+
* 32bit-le=pcr#
105+
* char[20]=template digest
106+
* 32bit-le=template name size
107+
* char[n]=template name
108+
* eventdata[n]=template specific data
109+
*/
110+
static int ima_measurements_show(struct seq_file *m, void *v)
111+
{
112+
/* the list never shrinks, so we don't need a lock here */
113+
struct ima_queue_entry *qe = v;
114+
struct ima_template_entry *e;
115+
int namelen;
116+
u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
117+
118+
/* get entry */
119+
e = qe->entry;
120+
if (e == NULL)
121+
return -1;
122+
123+
/*
124+
* 1st: PCRIndex
125+
* PCR used is always the same (config option) in
126+
* little-endian format
127+
*/
128+
ima_putc(m, &pcr, sizeof pcr);
129+
130+
/* 2nd: template digest */
131+
ima_putc(m, e->digest, IMA_DIGEST_SIZE);
132+
133+
/* 3rd: template name size */
134+
namelen = strlen(e->template_name);
135+
ima_putc(m, &namelen, sizeof namelen);
136+
137+
/* 4th: template name */
138+
ima_putc(m, e->template_name, namelen);
139+
140+
/* 5th: template specific data */
141+
ima_template_show(m, (struct ima_template_data *)&e->template,
142+
IMA_SHOW_BINARY);
143+
return 0;
144+
}
145+
146+
static struct seq_operations ima_measurments_seqops = {
147+
.start = ima_measurements_start,
148+
.next = ima_measurements_next,
149+
.stop = ima_measurements_stop,
150+
.show = ima_measurements_show
151+
};
152+
153+
static int ima_measurements_open(struct inode *inode, struct file *file)
154+
{
155+
return seq_open(file, &ima_measurments_seqops);
156+
}
157+
158+
static struct file_operations ima_measurements_ops = {
159+
.open = ima_measurements_open,
160+
.read = seq_read,
161+
.llseek = seq_lseek,
162+
.release = seq_release,
163+
};
164+
165+
static void ima_print_digest(struct seq_file *m, u8 *digest)
166+
{
167+
int i;
168+
169+
for (i = 0; i < IMA_DIGEST_SIZE; i++)
170+
seq_printf(m, "%02x", *(digest + i));
171+
}
172+
173+
void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
174+
{
175+
struct ima_template_data *entry = e;
176+
int namelen;
177+
178+
switch (show) {
179+
case IMA_SHOW_ASCII:
180+
ima_print_digest(m, entry->digest);
181+
seq_printf(m, " %s\n", entry->file_name);
182+
break;
183+
case IMA_SHOW_BINARY:
184+
ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
185+
186+
namelen = strlen(entry->file_name);
187+
ima_putc(m, &namelen, sizeof namelen);
188+
ima_putc(m, entry->file_name, namelen);
189+
default:
190+
break;
191+
}
192+
}
193+
194+
/* print in ascii */
195+
static int ima_ascii_measurements_show(struct seq_file *m, void *v)
196+
{
197+
/* the list never shrinks, so we don't need a lock here */
198+
struct ima_queue_entry *qe = v;
199+
struct ima_template_entry *e;
200+
201+
/* get entry */
202+
e = qe->entry;
203+
if (e == NULL)
204+
return -1;
205+
206+
/* 1st: PCR used (config option) */
207+
seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
208+
209+
/* 2nd: SHA1 template hash */
210+
ima_print_digest(m, e->digest);
211+
212+
/* 3th: template name */
213+
seq_printf(m, " %s ", e->template_name);
214+
215+
/* 4th: template specific data */
216+
ima_template_show(m, (struct ima_template_data *)&e->template,
217+
IMA_SHOW_ASCII);
218+
return 0;
219+
}
220+
221+
static struct seq_operations ima_ascii_measurements_seqops = {
222+
.start = ima_measurements_start,
223+
.next = ima_measurements_next,
224+
.stop = ima_measurements_stop,
225+
.show = ima_ascii_measurements_show
226+
};
227+
228+
static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
229+
{
230+
return seq_open(file, &ima_ascii_measurements_seqops);
231+
}
232+
233+
static struct file_operations ima_ascii_measurements_ops = {
234+
.open = ima_ascii_measurements_open,
235+
.read = seq_read,
236+
.llseek = seq_lseek,
237+
.release = seq_release,
238+
};
239+
240+
static struct dentry *ima_dir;
241+
static struct dentry *binary_runtime_measurements;
242+
static struct dentry *ascii_runtime_measurements;
243+
static struct dentry *runtime_measurements_count;
244+
static struct dentry *violations;
245+
246+
int ima_fs_init(void)
247+
{
248+
ima_dir = securityfs_create_dir("ima", NULL);
249+
if (IS_ERR(ima_dir))
250+
return -1;
251+
252+
binary_runtime_measurements =
253+
securityfs_create_file("binary_runtime_measurements",
254+
S_IRUSR | S_IRGRP, ima_dir, NULL,
255+
&ima_measurements_ops);
256+
if (IS_ERR(binary_runtime_measurements))
257+
goto out;
258+
259+
ascii_runtime_measurements =
260+
securityfs_create_file("ascii_runtime_measurements",
261+
S_IRUSR | S_IRGRP, ima_dir, NULL,
262+
&ima_ascii_measurements_ops);
263+
if (IS_ERR(ascii_runtime_measurements))
264+
goto out;
265+
266+
runtime_measurements_count =
267+
securityfs_create_file("runtime_measurements_count",
268+
S_IRUSR | S_IRGRP, ima_dir, NULL,
269+
&ima_measurements_count_ops);
270+
if (IS_ERR(runtime_measurements_count))
271+
goto out;
272+
273+
violations =
274+
securityfs_create_file("violations", S_IRUSR | S_IRGRP,
275+
ima_dir, NULL, &ima_htable_violations_ops);
276+
if (IS_ERR(violations))
277+
goto out;
278+
279+
return 0;
280+
281+
out:
282+
securityfs_remove(runtime_measurements_count);
283+
securityfs_remove(ascii_runtime_measurements);
284+
securityfs_remove(binary_runtime_measurements);
285+
securityfs_remove(ima_dir);
286+
return -1;
287+
}
288+
289+
void __exit ima_fs_cleanup(void)
290+
{
291+
securityfs_remove(violations);
292+
securityfs_remove(runtime_measurements_count);
293+
securityfs_remove(ascii_runtime_measurements);
294+
securityfs_remove(binary_runtime_measurements);
295+
securityfs_remove(ima_dir);
296+
}

security/integrity/ima/ima_init.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,11 @@ int ima_init(void)
8686

8787
ima_add_boot_aggregate(); /* boot aggregate must be first entry */
8888
ima_init_policy();
89-
return 0;
89+
90+
return ima_fs_init();
91+
}
92+
93+
void __exit ima_cleanup(void)
94+
{
95+
ima_fs_cleanup();
9096
}

security/integrity/ima/ima_main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,11 @@ static int __init init_ima(void)
274274
return error;
275275
}
276276

277+
static void __exit cleanup_ima(void)
278+
{
279+
ima_cleanup();
280+
}
281+
277282
late_initcall(init_ima); /* Start IMA after the TPM is available */
278283

279284
MODULE_DESCRIPTION("Integrity Measurement Architecture");

0 commit comments

Comments
 (0)