aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_api.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 00:38:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 00:38:48 -0400
commit88265322c14cce39f7afbc416726ef4fac413298 (patch)
treee4956f905ef617971f87788d8f8a09dbb66b70a3 /security/integrity/ima/ima_api.c
parent65b99c74fdd325d1ffa2e5663295888704712604 (diff)
parentbf5308344527d015ac9a6d2bda4ad4d40fd7d943 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - Integrity: add local fs integrity verification to detect offline attacks - Integrity: add digital signature verification - Simple stacking of Yama with other LSMs (per LSS discussions) - IBM vTPM support on ppc64 - Add new driver for Infineon I2C TIS TPM - Smack: add rule revocation for subject labels" Fixed conflicts with the user namespace support in kernel/auditsc.c and security/integrity/ima/ima_policy.c. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (39 commits) Documentation: Update git repository URL for Smack userland tools ima: change flags container data type Smack: setprocattr memory leak fix Smack: implement revoking all rules for a subject label Smack: remove task_wait() hook. ima: audit log hashes ima: generic IMA action flag handling ima: rename ima_must_appraise_or_measure audit: export audit_log_task_info tpm: fix tpm_acpi sparse warning on different address spaces samples/seccomp: fix 31 bit build on s390 ima: digital signature verification support ima: add support for different security.ima data types ima: add ima_inode_setxattr/removexattr function and calls ima: add inode_post_setattr call ima: replace iint spinblock with rwlock/read_lock ima: allocating iint improvements ima: add appraise action keywords and default rules ima: integrity appraisal extension vfs: move ima_file_free before releasing the file ...
Diffstat (limited to 'security/integrity/ima/ima_api.c')
-rw-r--r--security/integrity/ima/ima_api.c86
1 files changed, 69 insertions, 17 deletions
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 032ff03ad907..b356884fb3ef 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -9,13 +9,17 @@
9 * License. 9 * License.
10 * 10 *
11 * File: ima_api.c 11 * File: ima_api.c
12 * Implements must_measure, collect_measurement, store_measurement, 12 * Implements must_appraise_or_measure, collect_measurement,
13 * and store_template. 13 * appraise_measurement, store_measurement and store_template.
14 */ 14 */
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17 17#include <linux/file.h>
18#include <linux/fs.h>
19#include <linux/xattr.h>
20#include <linux/evm.h>
18#include "ima.h" 21#include "ima.h"
22
19static const char *IMA_TEMPLATE_NAME = "ima"; 23static const char *IMA_TEMPLATE_NAME = "ima";
20 24
21/* 25/*
@@ -93,7 +97,7 @@ err_out:
93} 97}
94 98
95/** 99/**
96 * ima_must_measure - measure decision based on policy. 100 * ima_get_action - appraise & measure decision based on policy.
97 * @inode: pointer to inode to measure 101 * @inode: pointer to inode to measure
98 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) 102 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
99 * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) 103 * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
@@ -105,15 +109,22 @@ err_out:
105 * mask: contains the permission mask 109 * mask: contains the permission mask
106 * fsmagic: hex value 110 * fsmagic: hex value
107 * 111 *
108 * Return 0 to measure. For matching a DONT_MEASURE policy, no policy, 112 * Returns IMA_MEASURE, IMA_APPRAISE mask.
109 * or other error, return an error code. 113 *
110*/ 114 */
111int ima_must_measure(struct inode *inode, int mask, int function) 115int ima_get_action(struct inode *inode, int mask, int function)
112{ 116{
113 int must_measure; 117 int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
118
119 if (!ima_appraise)
120 flags &= ~IMA_APPRAISE;
114 121
115 must_measure = ima_match_policy(inode, function, mask); 122 return ima_match_policy(inode, function, mask, flags);
116 return must_measure ? 0 : -EACCES; 123}
124
125int ima_must_measure(struct inode *inode, int mask, int function)
126{
127 return ima_match_policy(inode, function, mask, IMA_MEASURE);
117} 128}
118 129
119/* 130/*
@@ -129,16 +140,24 @@ int ima_must_measure(struct inode *inode, int mask, int function)
129int ima_collect_measurement(struct integrity_iint_cache *iint, 140int ima_collect_measurement(struct integrity_iint_cache *iint,
130 struct file *file) 141 struct file *file)
131{ 142{
132 int result = -EEXIST; 143 struct inode *inode = file->f_dentry->d_inode;
144 const char *filename = file->f_dentry->d_name.name;
145 int result = 0;
133 146
134 if (!(iint->flags & IMA_MEASURED)) { 147 if (!(iint->flags & IMA_COLLECTED)) {
135 u64 i_version = file->f_dentry->d_inode->i_version; 148 u64 i_version = file->f_dentry->d_inode->i_version;
136 149
137 memset(iint->digest, 0, IMA_DIGEST_SIZE); 150 iint->ima_xattr.type = IMA_XATTR_DIGEST;
138 result = ima_calc_hash(file, iint->digest); 151 result = ima_calc_hash(file, iint->ima_xattr.digest);
139 if (!result) 152 if (!result) {
140 iint->version = i_version; 153 iint->version = i_version;
154 iint->flags |= IMA_COLLECTED;
155 }
141 } 156 }
157 if (result)
158 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
159 filename, "collect_data", "failed",
160 result, 0);
142 return result; 161 return result;
143} 162}
144 163
@@ -167,6 +186,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
167 struct ima_template_entry *entry; 186 struct ima_template_entry *entry;
168 int violation = 0; 187 int violation = 0;
169 188
189 if (iint->flags & IMA_MEASURED)
190 return;
191
170 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 192 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
171 if (!entry) { 193 if (!entry) {
172 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, 194 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
@@ -174,7 +196,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
174 return; 196 return;
175 } 197 }
176 memset(&entry->template, 0, sizeof(entry->template)); 198 memset(&entry->template, 0, sizeof(entry->template));
177 memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE); 199 memcpy(entry->template.digest, iint->ima_xattr.digest, IMA_DIGEST_SIZE);
178 strcpy(entry->template.file_name, 200 strcpy(entry->template.file_name,
179 (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ? 201 (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
180 file->f_dentry->d_name.name : filename); 202 file->f_dentry->d_name.name : filename);
@@ -185,3 +207,33 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
185 if (result < 0) 207 if (result < 0)
186 kfree(entry); 208 kfree(entry);
187} 209}
210
211void ima_audit_measurement(struct integrity_iint_cache *iint,
212 const unsigned char *filename)
213{
214 struct audit_buffer *ab;
215 char hash[(IMA_DIGEST_SIZE * 2) + 1];
216 int i;
217
218 if (iint->flags & IMA_AUDITED)
219 return;
220
221 for (i = 0; i < IMA_DIGEST_SIZE; i++)
222 hex_byte_pack(hash + (i * 2), iint->ima_xattr.digest[i]);
223 hash[i * 2] = '\0';
224
225 ab = audit_log_start(current->audit_context, GFP_KERNEL,
226 AUDIT_INTEGRITY_RULE);
227 if (!ab)
228 return;
229
230 audit_log_format(ab, "file=");
231 audit_log_untrustedstring(ab, filename);
232 audit_log_format(ab, " hash=");
233 audit_log_untrustedstring(ab, hash);
234
235 audit_log_task_info(ab, current);
236 audit_log_end(ab);
237
238 iint->flags |= IMA_AUDITED;
239}