1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/module.h>
16
17#include "ima.h"
18static const char *IMA_TEMPLATE_NAME = "ima";
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36int ima_store_template(struct ima_template_entry *entry,
37 int violation, struct inode *inode)
38{
39 const char *op = "add_template_measure";
40 const char *audit_cause = "hashing_error";
41 int result;
42
43 memset(entry->digest, 0, sizeof(entry->digest));
44 entry->template_name = IMA_TEMPLATE_NAME;
45 entry->template_len = sizeof(entry->template);
46
47 if (!violation) {
48 result = ima_calc_template_hash(entry->template_len,
49 &entry->template,
50 entry->digest);
51 if (result < 0) {
52 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
53 entry->template_name, op,
54 audit_cause, result, 0);
55 return result;
56 }
57 }
58 result = ima_add_template_entry(entry, violation, op, inode);
59 return result;
60}
61
62
63
64
65
66
67
68
69void ima_add_violation(struct inode *inode, const unsigned char *filename,
70 const char *op, const char *cause)
71{
72 struct ima_template_entry *entry;
73 int violation = 1;
74 int result;
75
76
77 atomic_long_inc(&ima_htable.violations);
78
79 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
80 if (!entry) {
81 result = -ENOMEM;
82 goto err_out;
83 }
84 memset(&entry->template, 0, sizeof(entry->template));
85 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
86 result = ima_store_template(entry, violation, inode);
87 if (result < 0)
88 kfree(entry);
89err_out:
90 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
91 op, cause, result, 0);
92}
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
114 int mask, int function)
115{
116 int must_measure;
117
118 if (iint->flags & IMA_MEASURED)
119 return 1;
120
121 must_measure = ima_match_policy(inode, function, mask);
122 return must_measure ? 0 : -EACCES;
123}
124
125
126
127
128
129
130
131
132
133
134
135int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file)
136{
137 int result = -EEXIST;
138
139 if (!(iint->flags & IMA_MEASURED)) {
140 u64 i_version = file->f_dentry->d_inode->i_version;
141
142 memset(iint->digest, 0, IMA_DIGEST_SIZE);
143 result = ima_calc_hash(file, iint->digest);
144 if (!result)
145 iint->version = i_version;
146 }
147 return result;
148}
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
166 const unsigned char *filename)
167{
168 const char *op = "add_template_measure";
169 const char *audit_cause = "ENOMEM";
170 int result = -ENOMEM;
171 struct inode *inode = file->f_dentry->d_inode;
172 struct ima_template_entry *entry;
173 int violation = 0;
174
175 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
176 if (!entry) {
177 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
178 op, audit_cause, result, 0);
179 return;
180 }
181 memset(&entry->template, 0, sizeof(entry->template));
182 memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
183 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
184
185 result = ima_store_template(entry, violation, inode);
186 if (!result)
187 iint->flags |= IMA_MEASURED;
188 else
189 kfree(entry);
190}
191