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