Commit | Line | Data |
---|---|---|
b886d83c | 1 | // SPDX-License-Identifier: GPL-2.0-only |
3323eec9 | 2 | /* |
4f83d5ea PG |
3 | * Integrity Measurement Architecture |
4 | * | |
3323eec9 MZ |
5 | * Copyright (C) 2005,2006,2007,2008 IBM Corporation |
6 | * | |
7 | * Authors: | |
8 | * Reiner Sailer <sailer@watson.ibm.com> | |
9 | * Serge Hallyn <serue@us.ibm.com> | |
10 | * Kylene Hall <kylene@us.ibm.com> | |
11 | * Mimi Zohar <zohar@us.ibm.com> | |
12 | * | |
3323eec9 | 13 | * File: ima_main.c |
e0d5bd2a | 14 | * implements the IMA hooks: ima_bprm_check, ima_file_mmap, |
9bbb6cad | 15 | * and ima_file_check. |
3323eec9 | 16 | */ |
ab60368a | 17 | |
b49d5643 | 18 | #include <linux/module.h> |
3323eec9 MZ |
19 | #include <linux/file.h> |
20 | #include <linux/binfmts.h> | |
b89999d0 | 21 | #include <linux/kernel_read_file.h> |
3323eec9 MZ |
22 | #include <linux/mount.h> |
23 | #include <linux/mman.h> | |
5a0e3ad6 | 24 | #include <linux/slab.h> |
2fe5d6de | 25 | #include <linux/xattr.h> |
d5813a57 | 26 | #include <linux/ima.h> |
d77ccdc6 | 27 | #include <linux/fs.h> |
b836c4d2 | 28 | #include <linux/iversion.h> |
3323eec9 MZ |
29 | |
30 | #include "ima.h" | |
31 | ||
2fe5d6de MZ |
32 | #ifdef CONFIG_IMA_APPRAISE |
33 | int ima_appraise = IMA_APPRAISE_ENFORCE; | |
34 | #else | |
35 | int ima_appraise; | |
36 | #endif | |
37 | ||
5d1ef2ce | 38 | int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1; |
e7a2ad7e | 39 | static int hash_setup_done; |
c7c8bb23 | 40 | |
b1694245 JK |
41 | static struct notifier_block ima_lsm_policy_notifier = { |
42 | .notifier_call = ima_lsm_policy_change, | |
43 | }; | |
44 | ||
3323eec9 MZ |
45 | static int __init hash_setup(char *str) |
46 | { | |
e7a2ad7e MZ |
47 | struct ima_template_desc *template_desc = ima_template_desc_current(); |
48 | int i; | |
49 | ||
50 | if (hash_setup_done) | |
51 | return 1; | |
52 | ||
53 | if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) { | |
7fe2bb7e | 54 | if (strncmp(str, "sha1", 4) == 0) { |
e7a2ad7e | 55 | ima_hash_algo = HASH_ALGO_SHA1; |
7fe2bb7e | 56 | } else if (strncmp(str, "md5", 3) == 0) { |
e7a2ad7e | 57 | ima_hash_algo = HASH_ALGO_MD5; |
7fe2bb7e BM |
58 | } else { |
59 | pr_err("invalid hash algorithm \"%s\" for template \"%s\"", | |
60 | str, IMA_TEMPLATE_IMA_NAME); | |
ebe7c0a7 | 61 | return 1; |
7fe2bb7e | 62 | } |
e7a2ad7e MZ |
63 | goto out; |
64 | } | |
65 | ||
b4df8608 | 66 | i = match_string(hash_algo_name, HASH_ALGO__LAST, str); |
7fe2bb7e BM |
67 | if (i < 0) { |
68 | pr_err("invalid hash algorithm \"%s\"", str); | |
ebe7c0a7 | 69 | return 1; |
7fe2bb7e | 70 | } |
b4df8608 YX |
71 | |
72 | ima_hash_algo = i; | |
e7a2ad7e MZ |
73 | out: |
74 | hash_setup_done = 1; | |
3323eec9 MZ |
75 | return 1; |
76 | } | |
77 | __setup("ima_hash=", hash_setup); | |
78 | ||
5d1ef2ce RS |
79 | enum hash_algo ima_get_current_hash_algo(void) |
80 | { | |
81 | return ima_hash_algo; | |
82 | } | |
83 | ||
2cd4737b MZ |
84 | /* Prevent mmap'ing a file execute that is already mmap'ed write */ |
85 | static int mmap_violation_check(enum ima_hooks func, struct file *file, | |
86 | char **pathbuf, const char **pathname, | |
87 | char *filename) | |
88 | { | |
89 | struct inode *inode; | |
90 | int rc = 0; | |
91 | ||
4958db32 RS |
92 | if ((func == MMAP_CHECK || func == MMAP_CHECK_REQPROT) && |
93 | mapping_writably_mapped(file->f_mapping)) { | |
2cd4737b MZ |
94 | rc = -ETXTBSY; |
95 | inode = file_inode(file); | |
96 | ||
97 | if (!*pathbuf) /* ima_rdwr_violation possibly pre-fetched */ | |
98 | *pathname = ima_d_path(&file->f_path, pathbuf, | |
99 | filename); | |
100 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, *pathname, | |
101 | "mmap_file", "mmapped_writers", rc, 0); | |
102 | } | |
103 | return rc; | |
104 | } | |
105 | ||
8eb988c7 | 106 | /* |
890275b5 | 107 | * ima_rdwr_violation_check |
8eb988c7 | 108 | * |
890275b5 | 109 | * Only invalidate the PCR for measured files: |
2bb930ab | 110 | * - Opening a file for write when already open for read, |
8eb988c7 MZ |
111 | * results in a time of measure, time of use (ToMToU) error. |
112 | * - Opening a file for read when already open for write, | |
2bb930ab | 113 | * could result in a file measurement error. |
8eb988c7 MZ |
114 | * |
115 | */ | |
f7a859ff RS |
116 | static void ima_rdwr_violation_check(struct file *file, |
117 | struct integrity_iint_cache *iint, | |
1b68bdf9 | 118 | int must_measure, |
f7a859ff | 119 | char **pathbuf, |
4e8581ee RS |
120 | const char **pathname, |
121 | char *filename) | |
8eb988c7 | 122 | { |
c77cecee | 123 | struct inode *inode = file_inode(file); |
8eb988c7 | 124 | fmode_t mode = file->f_mode; |
ad16ad00 | 125 | bool send_tomtou = false, send_writers = false; |
a178d202 | 126 | |
8eb988c7 | 127 | if (mode & FMODE_WRITE) { |
14503eb9 | 128 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { |
f7a859ff RS |
129 | if (!iint) |
130 | iint = integrity_iint_find(inode); | |
14503eb9 | 131 | /* IMA_MEASURE is set from reader side */ |
0d73a552 DK |
132 | if (iint && test_bit(IMA_MUST_MEASURE, |
133 | &iint->atomic_flags)) | |
14503eb9 DK |
134 | send_tomtou = true; |
135 | } | |
b882fae2 | 136 | } else { |
0d73a552 DK |
137 | if (must_measure) |
138 | set_bit(IMA_MUST_MEASURE, &iint->atomic_flags); | |
eed9de3b | 139 | if (inode_is_open_for_write(inode) && must_measure) |
b882fae2 | 140 | send_writers = true; |
8eb988c7 | 141 | } |
ad16ad00 | 142 | |
08e1b76a MZ |
143 | if (!send_tomtou && !send_writers) |
144 | return; | |
145 | ||
bc15ed66 | 146 | *pathname = ima_d_path(&file->f_path, pathbuf, filename); |
ea1046d4 | 147 | |
ad16ad00 | 148 | if (send_tomtou) |
8d94eb9b RS |
149 | ima_add_violation(file, *pathname, iint, |
150 | "invalid_pcr", "ToMToU"); | |
ad16ad00 | 151 | if (send_writers) |
8d94eb9b | 152 | ima_add_violation(file, *pathname, iint, |
08e1b76a | 153 | "invalid_pcr", "open_writers"); |
8eb988c7 MZ |
154 | } |
155 | ||
f381c272 | 156 | static void ima_check_last_writer(struct integrity_iint_cache *iint, |
2fe5d6de | 157 | struct inode *inode, struct file *file) |
bc7d2a3e | 158 | { |
4b2a2c67 | 159 | fmode_t mode = file->f_mode; |
0d73a552 | 160 | bool update; |
bc7d2a3e | 161 | |
2fe5d6de MZ |
162 | if (!(mode & FMODE_WRITE)) |
163 | return; | |
164 | ||
0d73a552 | 165 | mutex_lock(&iint->mutex); |
b151d6b0 | 166 | if (atomic_read(&inode->i_writecount) == 1) { |
db1d1e8b JL |
167 | struct kstat stat; |
168 | ||
0d73a552 DK |
169 | update = test_and_clear_bit(IMA_UPDATE_XATTR, |
170 | &iint->atomic_flags); | |
db1d1e8b JL |
171 | if ((iint->flags & IMA_NEW_FILE) || |
172 | vfs_getattr_nosec(&file->f_path, &stat, | |
173 | STATX_CHANGE_COOKIE, | |
174 | AT_STATX_SYNC_AS_STAT) || | |
175 | !(stat.result_mask & STATX_CHANGE_COOKIE) || | |
176 | stat.change_cookie != iint->version) { | |
b151d6b0 | 177 | iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); |
a422638d | 178 | iint->measured_pcrs = 0; |
0d73a552 | 179 | if (update) |
b151d6b0 DK |
180 | ima_update_xattr(iint, file); |
181 | } | |
2fe5d6de | 182 | } |
0d73a552 | 183 | mutex_unlock(&iint->mutex); |
bc7d2a3e EP |
184 | } |
185 | ||
3323eec9 MZ |
186 | /** |
187 | * ima_file_free - called on __fput() | |
188 | * @file: pointer to file structure being freed | |
189 | * | |
890275b5 | 190 | * Flag files that changed, based on i_version |
3323eec9 | 191 | */ |
cd3cec0a | 192 | static void ima_file_free(struct file *file) |
3323eec9 | 193 | { |
496ad9aa | 194 | struct inode *inode = file_inode(file); |
f381c272 | 195 | struct integrity_iint_cache *iint; |
3323eec9 | 196 | |
0f34a006 | 197 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
3323eec9 | 198 | return; |
196f5181 | 199 | |
f381c272 | 200 | iint = integrity_iint_find(inode); |
854fdd55 MZ |
201 | if (!iint) |
202 | return; | |
3323eec9 | 203 | |
854fdd55 | 204 | ima_check_last_writer(iint, inode, file); |
3323eec9 MZ |
205 | } |
206 | ||
d906c10d MG |
207 | static int process_measurement(struct file *file, const struct cred *cred, |
208 | u32 secid, char *buf, loff_t size, int mask, | |
6035a27b | 209 | enum ima_hooks func) |
3323eec9 | 210 | { |
b836c4d2 | 211 | struct inode *backing_inode, *inode = file_inode(file); |
f7a859ff | 212 | struct integrity_iint_cache *iint = NULL; |
19453ce0 | 213 | struct ima_template_desc *template_desc = NULL; |
ea1046d4 | 214 | char *pathbuf = NULL; |
bc15ed66 | 215 | char filename[NAME_MAX]; |
ea1046d4 | 216 | const char *pathname = NULL; |
0d73a552 | 217 | int rc = 0, action, must_appraise = 0; |
725de7fa | 218 | int pcr = CONFIG_IMA_MEASURE_PCR_IDX; |
1525b06d | 219 | struct evm_ima_xattr_data *xattr_value = NULL; |
39b07096 | 220 | struct modsig *modsig = NULL; |
d3634d0f | 221 | int xattr_len = 0; |
f7a859ff | 222 | bool violation_check; |
1525b06d | 223 | enum hash_algo hash_algo; |
1624dc00 | 224 | unsigned int allowed_algos = 0; |
3323eec9 | 225 | |
a756024e | 226 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
3323eec9 | 227 | return 0; |
bc7d2a3e | 228 | |
d79d72e0 MZ |
229 | /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action |
230 | * bitmask based on the appraise/audit/measurement policy. | |
231 | * Included is the appraise submask. | |
232 | */ | |
39f60c1c | 233 | action = ima_get_action(file_mnt_idmap(file), inode, cred, secid, |
1624dc00 TS |
234 | mask, func, &pcr, &template_desc, NULL, |
235 | &allowed_algos); | |
4958db32 RS |
236 | violation_check = ((func == FILE_CHECK || func == MMAP_CHECK || |
237 | func == MMAP_CHECK_REQPROT) && | |
f7a859ff RS |
238 | (ima_policy_flag & IMA_MEASURE)); |
239 | if (!action && !violation_check) | |
2fe5d6de MZ |
240 | return 0; |
241 | ||
2fe5d6de | 242 | must_appraise = action & IMA_APPRAISE; |
bc7d2a3e | 243 | |
5a73fcfa | 244 | /* Is the appraise rule hook specific? */ |
3a8a2ead | 245 | if (action & IMA_FILE_APPRAISE) |
4ad87a3d | 246 | func = FILE_CHECK; |
5a73fcfa | 247 | |
5955102c | 248 | inode_lock(inode); |
2fe5d6de | 249 | |
f7a859ff RS |
250 | if (action) { |
251 | iint = integrity_inode_get(inode); | |
252 | if (!iint) | |
0d73a552 | 253 | rc = -ENOMEM; |
f7a859ff RS |
254 | } |
255 | ||
0d73a552 | 256 | if (!rc && violation_check) |
1b68bdf9 | 257 | ima_rdwr_violation_check(file, iint, action & IMA_MEASURE, |
4e8581ee | 258 | &pathbuf, &pathname, filename); |
0d73a552 DK |
259 | |
260 | inode_unlock(inode); | |
261 | ||
262 | if (rc) | |
263 | goto out; | |
264 | if (!action) | |
265 | goto out; | |
266 | ||
267 | mutex_lock(&iint->mutex); | |
268 | ||
269 | if (test_and_clear_bit(IMA_CHANGE_ATTR, &iint->atomic_flags)) | |
270 | /* reset appraisal flags if ima_inode_post_setattr was called */ | |
271 | iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED | | |
272 | IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | | |
aae6ccbd | 273 | IMA_NONACTION_FLAGS); |
0d73a552 | 274 | |
d77ccdc6 MZ |
275 | /* |
276 | * Re-evaulate the file if either the xattr has changed or the | |
277 | * kernel has no way of detecting file change on the filesystem. | |
278 | * (Limited to privileged mounted filesystems.) | |
279 | */ | |
280 | if (test_and_clear_bit(IMA_CHANGE_XATTR, &iint->atomic_flags) || | |
281 | ((inode->i_sb->s_iflags & SB_I_IMA_UNVERIFIABLE_SIGNATURE) && | |
9e67028e MZ |
282 | !(inode->i_sb->s_iflags & SB_I_UNTRUSTED_MOUNTER) && |
283 | !(action & IMA_FAIL_UNVERIFIABLE_SIGS))) { | |
0d73a552 | 284 | iint->flags &= ~IMA_DONE_MASK; |
d77ccdc6 MZ |
285 | iint->measured_pcrs = 0; |
286 | } | |
bf2276d1 | 287 | |
b836c4d2 MZ |
288 | /* Detect and re-evaluate changes made to the backing file. */ |
289 | backing_inode = d_real_inode(file_dentry(file)); | |
290 | if (backing_inode != inode && | |
291 | (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) { | |
292 | if (!IS_I_VERSION(backing_inode) || | |
293 | backing_inode->i_sb->s_dev != iint->real_dev || | |
294 | backing_inode->i_ino != iint->real_ino || | |
295 | !inode_eq_iversion(backing_inode, iint->version)) { | |
296 | iint->flags &= ~IMA_DONE_MASK; | |
297 | iint->measured_pcrs = 0; | |
298 | } | |
299 | } | |
300 | ||
2fe5d6de | 301 | /* Determine if already appraised/measured based on bitmask |
d79d72e0 MZ |
302 | * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, |
303 | * IMA_AUDIT, IMA_AUDITED) | |
304 | */ | |
2fe5d6de | 305 | iint->flags |= action; |
0e5a247c | 306 | action &= IMA_DO_MASK; |
a422638d ER |
307 | action &= ~((iint->flags & (IMA_DONE_MASK ^ IMA_MEASURED)) >> 1); |
308 | ||
309 | /* If target pcr is already measured, unset IMA_MEASURE action */ | |
310 | if ((action & IMA_MEASURE) && (iint->measured_pcrs & (0x1 << pcr))) | |
311 | action ^= IMA_MEASURE; | |
2fe5d6de | 312 | |
da1b0029 MZ |
313 | /* HASH sets the digital signature and update flags, nothing else */ |
314 | if ((action & IMA_HASH) && | |
315 | !(test_bit(IMA_DIGSIG, &iint->atomic_flags))) { | |
f6fbd8cb PM |
316 | xattr_len = ima_read_xattr(file_dentry(file), |
317 | &xattr_value, xattr_len); | |
da1b0029 MZ |
318 | if ((xattr_value && xattr_len > 2) && |
319 | (xattr_value->type == EVM_IMA_XATTR_DIGSIG)) | |
320 | set_bit(IMA_DIGSIG, &iint->atomic_flags); | |
321 | iint->flags |= IMA_HASHED; | |
322 | action ^= IMA_HASH; | |
323 | set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); | |
324 | } | |
325 | ||
2fe5d6de MZ |
326 | /* Nothing to do, just return existing appraised status */ |
327 | if (!action) { | |
2cd4737b MZ |
328 | if (must_appraise) { |
329 | rc = mmap_violation_check(func, file, &pathbuf, | |
330 | &pathname, filename); | |
331 | if (!rc) | |
332 | rc = ima_get_cache_status(iint, func); | |
333 | } | |
0d73a552 | 334 | goto out_locked; |
2fe5d6de | 335 | } |
3323eec9 | 336 | |
f68c05f4 | 337 | if ((action & IMA_APPRAISE_SUBMASK) || |
39b07096 | 338 | strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) { |
1525b06d | 339 | /* read 'security.ima' */ |
f6fbd8cb PM |
340 | xattr_len = ima_read_xattr(file_dentry(file), |
341 | &xattr_value, xattr_len); | |
d3634d0f | 342 | |
e5092255 TJB |
343 | /* |
344 | * Read the appended modsig if allowed by the policy, and allow | |
345 | * an additional measurement list entry, if needed, based on the | |
346 | * template format and whether the file was already measured. | |
347 | */ | |
348 | if (iint->flags & IMA_MODSIG_ALLOWED) { | |
349 | rc = ima_read_modsig(func, buf, size, &modsig); | |
350 | ||
351 | if (!rc && ima_template_has_modsig(template_desc) && | |
352 | iint->flags & IMA_MEASURED) | |
353 | action |= IMA_MEASURE; | |
354 | } | |
39b07096 TJB |
355 | } |
356 | ||
1525b06d DK |
357 | hash_algo = ima_get_hash_algo(xattr_value, xattr_len); |
358 | ||
15588227 | 359 | rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig); |
6dc387d5 | 360 | if (rc != 0 && rc != -EBADF && rc != -EINVAL) |
0d73a552 | 361 | goto out_locked; |
08e1b76a | 362 | |
bc15ed66 MZ |
363 | if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */ |
364 | pathname = ima_d_path(&file->f_path, &pathbuf, filename); | |
08e1b76a | 365 | |
2fe5d6de | 366 | if (action & IMA_MEASURE) |
bcbc9b0c | 367 | ima_store_measurement(iint, file, pathname, |
3878d505 | 368 | xattr_value, xattr_len, modsig, pcr, |
19453ce0 | 369 | template_desc); |
0d73a552 | 370 | if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { |
273df864 NJ |
371 | rc = ima_check_blacklist(iint, modsig, pcr); |
372 | if (rc != -EPERM) { | |
373 | inode_lock(inode); | |
374 | rc = ima_appraise_measurement(func, iint, file, | |
375 | pathname, xattr_value, | |
376 | xattr_len, modsig); | |
377 | inode_unlock(inode); | |
378 | } | |
2cd4737b MZ |
379 | if (!rc) |
380 | rc = mmap_violation_check(func, file, &pathbuf, | |
381 | &pathname, filename); | |
0d73a552 | 382 | } |
e7c568e0 | 383 | if (action & IMA_AUDIT) |
ea1046d4 | 384 | ima_audit_measurement(iint, pathname); |
f7a859ff | 385 | |
f3cc6b25 MZ |
386 | if ((file->f_flags & O_DIRECT) && (iint->flags & IMA_PERMIT_DIRECTIO)) |
387 | rc = 0; | |
1624dc00 TS |
388 | |
389 | /* Ensure the digest was generated using an allowed algorithm */ | |
390 | if (rc == 0 && must_appraise && allowed_algos != 0 && | |
391 | (allowed_algos & (1U << hash_algo)) == 0) { | |
392 | rc = -EACCES; | |
393 | ||
394 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, file_inode(file), | |
395 | pathname, "collect_data", | |
396 | "denied-hash-algorithm", rc, 0); | |
397 | } | |
0d73a552 DK |
398 | out_locked: |
399 | if ((mask & MAY_WRITE) && test_bit(IMA_DIGSIG, &iint->atomic_flags) && | |
05d1a717 | 400 | !(iint->flags & IMA_NEW_FILE)) |
a175b8bb | 401 | rc = -EACCES; |
0d73a552 | 402 | mutex_unlock(&iint->mutex); |
f7a859ff | 403 | kfree(xattr_value); |
39b07096 | 404 | ima_free_modsig(modsig); |
0d73a552 | 405 | out: |
456f5fd3 DK |
406 | if (pathbuf) |
407 | __putname(pathbuf); | |
0d73a552 DK |
408 | if (must_appraise) { |
409 | if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE)) | |
410 | return -EACCES; | |
411 | if (file->f_mode & FMODE_WRITE) | |
412 | set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); | |
413 | } | |
750943a3 | 414 | return 0; |
3323eec9 MZ |
415 | } |
416 | ||
417 | /** | |
418 | * ima_file_mmap - based on policy, collect/store measurement. | |
419 | * @file: pointer to the file to be measured (May be NULL) | |
4971c268 RS |
420 | * @reqprot: protection requested by the application |
421 | * @prot: protection that will be applied by the kernel | |
422 | * @flags: operational flags | |
3323eec9 MZ |
423 | * |
424 | * Measure files being mmapped executable based on the ima_must_measure() | |
425 | * policy decision. | |
426 | * | |
750943a3 DK |
427 | * On success return 0. On integrity appraisal error, assuming the file |
428 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
3323eec9 | 429 | */ |
cd3cec0a RS |
430 | static int ima_file_mmap(struct file *file, unsigned long reqprot, |
431 | unsigned long prot, unsigned long flags) | |
3323eec9 | 432 | { |
d906c10d | 433 | u32 secid; |
4958db32 | 434 | int ret; |
d906c10d | 435 | |
4958db32 RS |
436 | if (!file) |
437 | return 0; | |
438 | ||
439 | security_current_getsecid_subj(&secid); | |
440 | ||
441 | if (reqprot & PROT_EXEC) { | |
442 | ret = process_measurement(file, current_cred(), secid, NULL, | |
443 | 0, MAY_EXEC, MMAP_CHECK_REQPROT); | |
444 | if (ret) | |
445 | return ret; | |
446 | } | |
447 | ||
448 | if (prot & PROT_EXEC) | |
d906c10d | 449 | return process_measurement(file, current_cred(), secid, NULL, |
6035a27b | 450 | 0, MAY_EXEC, MMAP_CHECK); |
d906c10d | 451 | |
750943a3 | 452 | return 0; |
3323eec9 MZ |
453 | } |
454 | ||
8eb613c0 MZ |
455 | /** |
456 | * ima_file_mprotect - based on policy, limit mprotect change | |
bae60eef | 457 | * @vma: vm_area_struct protection is set to |
0298c5a9 RS |
458 | * @reqprot: protection requested by the application |
459 | * @prot: protection that will be applied by the kernel | |
8eb613c0 MZ |
460 | * |
461 | * Files can be mmap'ed read/write and later changed to execute to circumvent | |
462 | * IMA's mmap appraisal policy rules. Due to locking issues (mmap semaphore | |
463 | * would be taken before i_mutex), files can not be measured or appraised at | |
464 | * this point. Eliminate this integrity gap by denying the mprotect | |
465 | * PROT_EXECUTE change, if an mmap appraise policy rule exists. | |
466 | * | |
467 | * On mprotect change success, return 0. On failure, return -EACESS. | |
468 | */ | |
cd3cec0a RS |
469 | static int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
470 | unsigned long prot) | |
8eb613c0 | 471 | { |
dea87d08 | 472 | struct ima_template_desc *template = NULL; |
29d1c2b4 | 473 | struct file *file; |
8eb613c0 MZ |
474 | char filename[NAME_MAX]; |
475 | char *pathbuf = NULL; | |
476 | const char *pathname = NULL; | |
477 | struct inode *inode; | |
478 | int result = 0; | |
479 | int action; | |
480 | u32 secid; | |
481 | int pcr; | |
482 | ||
483 | /* Is mprotect making an mmap'ed file executable? */ | |
4235b1a4 MZ |
484 | if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file || |
485 | !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC)) | |
8eb613c0 MZ |
486 | return 0; |
487 | ||
6326948f | 488 | security_current_getsecid_subj(&secid); |
8eb613c0 | 489 | inode = file_inode(vma->vm_file); |
39f60c1c | 490 | action = ima_get_action(file_mnt_idmap(vma->vm_file), inode, |
a2d2329e | 491 | current_cred(), secid, MAY_EXEC, MMAP_CHECK, |
1624dc00 | 492 | &pcr, &template, NULL, NULL); |
67e2dcff | 493 | action |= ima_get_action(file_mnt_idmap(vma->vm_file), inode, |
4958db32 RS |
494 | current_cred(), secid, MAY_EXEC, |
495 | MMAP_CHECK_REQPROT, &pcr, &template, NULL, | |
496 | NULL); | |
8eb613c0 MZ |
497 | |
498 | /* Is the mmap'ed file in policy? */ | |
499 | if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) | |
500 | return 0; | |
501 | ||
502 | if (action & IMA_APPRAISE_SUBMASK) | |
503 | result = -EPERM; | |
504 | ||
505 | file = vma->vm_file; | |
506 | pathname = ima_d_path(&file->f_path, &pathbuf, filename); | |
507 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, pathname, | |
508 | "collect_data", "failed-mprotect", result, 0); | |
509 | if (pathbuf) | |
510 | __putname(pathbuf); | |
511 | ||
512 | return result; | |
513 | } | |
514 | ||
3323eec9 MZ |
515 | /** |
516 | * ima_bprm_check - based on policy, collect/store measurement. | |
517 | * @bprm: contains the linux_binprm structure | |
518 | * | |
519 | * The OS protects against an executable file, already open for write, | |
520 | * from being executed in deny_write_access() and an executable file, | |
521 | * already open for execute, from being modified in get_write_access(). | |
522 | * So we can be certain that what we verify and measure here is actually | |
523 | * what is being executed. | |
524 | * | |
750943a3 DK |
525 | * On success return 0. On integrity appraisal error, assuming the file |
526 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
3323eec9 | 527 | */ |
cd3cec0a | 528 | static int ima_bprm_check(struct linux_binprm *bprm) |
3323eec9 | 529 | { |
d906c10d MG |
530 | int ret; |
531 | u32 secid; | |
532 | ||
6326948f | 533 | security_current_getsecid_subj(&secid); |
d906c10d | 534 | ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, |
6035a27b | 535 | MAY_EXEC, BPRM_CHECK); |
d906c10d MG |
536 | if (ret) |
537 | return ret; | |
538 | ||
539 | security_cred_getsecid(bprm->cred, &secid); | |
540 | return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, | |
6035a27b | 541 | MAY_EXEC, CREDS_CHECK); |
3323eec9 MZ |
542 | } |
543 | ||
8eb988c7 | 544 | /** |
41d75dd9 | 545 | * ima_file_check - based on policy, collect/store measurement. |
8eb988c7 | 546 | * @file: pointer to the file to be measured |
20f482ab | 547 | * @mask: contains MAY_READ, MAY_WRITE, MAY_EXEC or MAY_APPEND |
8eb988c7 MZ |
548 | * |
549 | * Measure files based on the ima_must_measure() policy decision. | |
550 | * | |
750943a3 DK |
551 | * On success return 0. On integrity appraisal error, assuming the file |
552 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
8eb988c7 | 553 | */ |
cd3cec0a | 554 | static int ima_file_check(struct file *file, int mask) |
8eb988c7 | 555 | { |
d906c10d MG |
556 | u32 secid; |
557 | ||
6326948f | 558 | security_current_getsecid_subj(&secid); |
d906c10d | 559 | return process_measurement(file, current_cred(), secid, NULL, 0, |
20f482ab | 560 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC | |
6035a27b | 561 | MAY_APPEND), FILE_CHECK); |
8eb988c7 | 562 | } |
8eb988c7 | 563 | |
280fe836 RS |
564 | static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, |
565 | size_t buf_size) | |
6beea7af | 566 | { |
280fe836 RS |
567 | struct integrity_iint_cache *iint = NULL, tmp_iint; |
568 | int rc, hash_algo; | |
6beea7af | 569 | |
280fe836 RS |
570 | if (ima_policy_flag) { |
571 | iint = integrity_iint_find(inode); | |
572 | if (iint) | |
573 | mutex_lock(&iint->mutex); | |
574 | } | |
575 | ||
576 | if ((!iint || !(iint->flags & IMA_COLLECTED)) && file) { | |
577 | if (iint) | |
578 | mutex_unlock(&iint->mutex); | |
579 | ||
580 | memset(&tmp_iint, 0, sizeof(tmp_iint)); | |
581 | tmp_iint.inode = inode; | |
582 | mutex_init(&tmp_iint.mutex); | |
583 | ||
584 | rc = ima_collect_measurement(&tmp_iint, file, NULL, 0, | |
585 | ima_hash_algo, NULL); | |
8c1d6a05 RS |
586 | if (rc < 0) { |
587 | /* ima_hash could be allocated in case of failure. */ | |
588 | if (rc != -ENOMEM) | |
589 | kfree(tmp_iint.ima_hash); | |
590 | ||
280fe836 | 591 | return -EOPNOTSUPP; |
8c1d6a05 | 592 | } |
280fe836 RS |
593 | |
594 | iint = &tmp_iint; | |
595 | mutex_lock(&iint->mutex); | |
596 | } | |
6beea7af | 597 | |
6beea7af FR |
598 | if (!iint) |
599 | return -EOPNOTSUPP; | |
600 | ||
aa662fc0 KS |
601 | /* |
602 | * ima_file_hash can be called when ima_collect_measurement has still | |
603 | * not been called, we might not always have a hash. | |
604 | */ | |
62622dab | 605 | if (!iint->ima_hash || !(iint->flags & IMA_COLLECTED)) { |
aa662fc0 KS |
606 | mutex_unlock(&iint->mutex); |
607 | return -EOPNOTSUPP; | |
608 | } | |
609 | ||
6beea7af FR |
610 | if (buf) { |
611 | size_t copied_size; | |
612 | ||
613 | copied_size = min_t(size_t, iint->ima_hash->length, buf_size); | |
614 | memcpy(buf, iint->ima_hash->digest, copied_size); | |
615 | } | |
616 | hash_algo = iint->ima_hash->algo; | |
617 | mutex_unlock(&iint->mutex); | |
618 | ||
280fe836 RS |
619 | if (iint == &tmp_iint) |
620 | kfree(iint->ima_hash); | |
621 | ||
6beea7af FR |
622 | return hash_algo; |
623 | } | |
403319be KS |
624 | |
625 | /** | |
280fe836 | 626 | * ima_file_hash - return a measurement of the file |
403319be KS |
627 | * @file: pointer to the file |
628 | * @buf: buffer in which to store the hash | |
629 | * @buf_size: length of the buffer | |
630 | * | |
631 | * On success, return the hash algorithm (as defined in the enum hash_algo). | |
632 | * If buf is not NULL, this function also outputs the hash into buf. | |
633 | * If the hash is larger than buf_size, then only buf_size bytes will be copied. | |
634 | * It generally just makes sense to pass a buffer capable of holding the largest | |
635 | * possible hash: IMA_MAX_DIGEST_SIZE. | |
636 | * The file hash returned is based on the entire file, including the appended | |
637 | * signature. | |
638 | * | |
280fe836 | 639 | * If the measurement cannot be performed, return -EOPNOTSUPP. |
403319be KS |
640 | * If the parameters are incorrect, return -EINVAL. |
641 | */ | |
642 | int ima_file_hash(struct file *file, char *buf, size_t buf_size) | |
643 | { | |
644 | if (!file) | |
645 | return -EINVAL; | |
646 | ||
280fe836 | 647 | return __ima_inode_hash(file_inode(file), file, buf, buf_size); |
403319be | 648 | } |
6beea7af FR |
649 | EXPORT_SYMBOL_GPL(ima_file_hash); |
650 | ||
403319be KS |
651 | /** |
652 | * ima_inode_hash - return the stored measurement if the inode has been hashed | |
653 | * and is in the iint cache. | |
654 | * @inode: pointer to the inode | |
655 | * @buf: buffer in which to store the hash | |
656 | * @buf_size: length of the buffer | |
657 | * | |
658 | * On success, return the hash algorithm (as defined in the enum hash_algo). | |
659 | * If buf is not NULL, this function also outputs the hash into buf. | |
660 | * If the hash is larger than buf_size, then only buf_size bytes will be copied. | |
661 | * It generally just makes sense to pass a buffer capable of holding the largest | |
662 | * possible hash: IMA_MAX_DIGEST_SIZE. | |
663 | * The hash returned is based on the entire contents, including the appended | |
664 | * signature. | |
665 | * | |
666 | * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. | |
667 | * If the parameters are incorrect, return -EINVAL. | |
668 | */ | |
669 | int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) | |
670 | { | |
671 | if (!inode) | |
672 | return -EINVAL; | |
673 | ||
280fe836 | 674 | return __ima_inode_hash(inode, NULL, buf, buf_size); |
403319be KS |
675 | } |
676 | EXPORT_SYMBOL_GPL(ima_inode_hash); | |
677 | ||
fdb2410f MZ |
678 | /** |
679 | * ima_post_create_tmpfile - mark newly created tmpfile as new | |
39f60c1c | 680 | * @idmap: idmap of the mount the inode was found from |
bae60eef | 681 | * @inode: inode of the newly created tmpfile |
fdb2410f MZ |
682 | * |
683 | * No measuring, appraising or auditing of newly created tmpfiles is needed. | |
684 | * Skip calling process_measurement(), but indicate which newly, created | |
685 | * tmpfiles are in policy. | |
686 | */ | |
cd3cec0a RS |
687 | static void ima_post_create_tmpfile(struct mnt_idmap *idmap, |
688 | struct inode *inode) | |
689 | ||
fdb2410f MZ |
690 | { |
691 | struct integrity_iint_cache *iint; | |
692 | int must_appraise; | |
693 | ||
f873b28f MZ |
694 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
695 | return; | |
696 | ||
39f60c1c | 697 | must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS, |
a2d2329e | 698 | FILE_CHECK); |
fdb2410f MZ |
699 | if (!must_appraise) |
700 | return; | |
701 | ||
702 | /* Nothing to do if we can't allocate memory */ | |
703 | iint = integrity_inode_get(inode); | |
704 | if (!iint) | |
705 | return; | |
706 | ||
707 | /* needed for writing the security xattrs */ | |
708 | set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); | |
709 | iint->ima_file_status = INTEGRITY_PASS; | |
710 | } | |
711 | ||
05d1a717 MZ |
712 | /** |
713 | * ima_post_path_mknod - mark as a new inode | |
39f60c1c | 714 | * @idmap: idmap of the mount the inode was found from |
05d1a717 MZ |
715 | * @dentry: newly created dentry |
716 | * | |
717 | * Mark files created via the mknodat syscall as new, so that the | |
718 | * file data can be written later. | |
719 | */ | |
cd3cec0a | 720 | static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) |
05d1a717 MZ |
721 | { |
722 | struct integrity_iint_cache *iint; | |
723 | struct inode *inode = dentry->d_inode; | |
724 | int must_appraise; | |
725 | ||
f873b28f MZ |
726 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
727 | return; | |
728 | ||
39f60c1c | 729 | must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS, |
a2d2329e | 730 | FILE_CHECK); |
05d1a717 MZ |
731 | if (!must_appraise) |
732 | return; | |
733 | ||
fdb2410f | 734 | /* Nothing to do if we can't allocate memory */ |
05d1a717 | 735 | iint = integrity_inode_get(inode); |
fdb2410f MZ |
736 | if (!iint) |
737 | return; | |
738 | ||
739 | /* needed for re-opening empty files */ | |
740 | iint->flags |= IMA_NEW_FILE; | |
05d1a717 MZ |
741 | } |
742 | ||
39eeb4fb MZ |
743 | /** |
744 | * ima_read_file - pre-measure/appraise hook decision based on policy | |
745 | * @file: pointer to the file to be measured/appraised/audit | |
746 | * @read_id: caller identifier | |
2039bda1 | 747 | * @contents: whether a subsequent call will be made to ima_post_read_file() |
39eeb4fb MZ |
748 | * |
749 | * Permit reading a file based on policy. The policy rules are written | |
750 | * in terms of the policy identifier. Appraising the integrity of | |
751 | * a file requires a file descriptor. | |
752 | * | |
753 | * For permission return 0, otherwise return -EACCES. | |
754 | */ | |
cd3cec0a RS |
755 | static int ima_read_file(struct file *file, enum kernel_read_file_id read_id, |
756 | bool contents) | |
39eeb4fb | 757 | { |
34736dae SB |
758 | enum ima_hooks func; |
759 | u32 secid; | |
2039bda1 | 760 | |
4f0496d8 | 761 | /* |
4f0496d8 MZ |
762 | * Do devices using pre-allocated memory run the risk of the |
763 | * firmware being accessible to the device prior to the completion | |
764 | * of IMA's signature verification any more than when using two | |
c307459b KC |
765 | * buffers? It may be desirable to include the buffer address |
766 | * in this API and walk all the dma_map_single() mappings to check. | |
4f0496d8 | 767 | */ |
34736dae SB |
768 | |
769 | /* | |
770 | * There will be a call made to ima_post_read_file() with | |
771 | * a filled buffer, so we don't need to perform an extra | |
772 | * read early here. | |
773 | */ | |
774 | if (contents) | |
775 | return 0; | |
776 | ||
777 | /* Read entire file for all partial reads. */ | |
778 | func = read_idmap[read_id] ?: FILE_CHECK; | |
6326948f | 779 | security_current_getsecid_subj(&secid); |
34736dae SB |
780 | return process_measurement(file, current_cred(), secid, NULL, |
781 | 0, MAY_READ, func); | |
39eeb4fb MZ |
782 | } |
783 | ||
29d3c1c8 | 784 | const int read_idmap[READING_MAX_ID] = { |
d9ddf077 MZ |
785 | [READING_FIRMWARE] = FIRMWARE_CHECK, |
786 | [READING_MODULE] = MODULE_CHECK, | |
787 | [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, | |
788 | [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, | |
19f8a847 | 789 | [READING_POLICY] = POLICY_CHECK |
d9ddf077 MZ |
790 | }; |
791 | ||
cf222217 MZ |
792 | /** |
793 | * ima_post_read_file - in memory collect/appraise/audit measurement | |
794 | * @file: pointer to the file to be measured/appraised/audit | |
795 | * @buf: pointer to in memory file contents | |
796 | * @size: size of in memory file contents | |
797 | * @read_id: caller identifier | |
798 | * | |
799 | * Measure/appraise/audit in memory file based on policy. Policy rules | |
800 | * are written in terms of a policy identifier. | |
801 | * | |
802 | * On success return 0. On integrity appraisal error, assuming the file | |
803 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
804 | */ | |
cd3cec0a RS |
805 | static int ima_post_read_file(struct file *file, char *buf, loff_t size, |
806 | enum kernel_read_file_id read_id) | |
cf222217 | 807 | { |
d9ddf077 | 808 | enum ima_hooks func; |
d906c10d | 809 | u32 secid; |
cf222217 | 810 | |
a7d3d039 CH |
811 | /* permit signed certs */ |
812 | if (!file && read_id == READING_X509_CERTIFICATE) | |
813 | return 0; | |
814 | ||
cf222217 MZ |
815 | if (!file || !buf || size == 0) { /* should never happen */ |
816 | if (ima_appraise & IMA_APPRAISE_ENFORCE) | |
817 | return -EACCES; | |
818 | return 0; | |
819 | } | |
820 | ||
d9ddf077 | 821 | func = read_idmap[read_id] ?: FILE_CHECK; |
6326948f | 822 | security_current_getsecid_subj(&secid); |
d906c10d | 823 | return process_measurement(file, current_cred(), secid, buf, size, |
6035a27b | 824 | MAY_READ, func); |
5a9196d7 MZ |
825 | } |
826 | ||
16c267aa MZ |
827 | /** |
828 | * ima_load_data - appraise decision based on policy | |
829 | * @id: kernel load data caller identifier | |
b64fcae7 KC |
830 | * @contents: whether the full contents will be available in a later |
831 | * call to ima_post_load_data(). | |
16c267aa MZ |
832 | * |
833 | * Callers of this LSM hook can not measure, appraise, or audit the | |
65603435 | 834 | * data provided by userspace. Enforce policy rules requiring a file |
16c267aa MZ |
835 | * signature (eg. kexec'ed kernel image). |
836 | * | |
837 | * For permission return 0, otherwise return -EACCES. | |
838 | */ | |
cd3cec0a | 839 | static int ima_load_data(enum kernel_load_data_id id, bool contents) |
16c267aa | 840 | { |
b5ca1173 | 841 | bool ima_enforce, sig_enforce; |
c77b8cdf | 842 | |
b5ca1173 NJ |
843 | ima_enforce = |
844 | (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE; | |
16c267aa MZ |
845 | |
846 | switch (id) { | |
847 | case LOADING_KEXEC_IMAGE: | |
99d5cadf | 848 | if (IS_ENABLED(CONFIG_KEXEC_SIG) |
b5ca1173 NJ |
849 | && arch_ima_get_secureboot()) { |
850 | pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); | |
851 | return -EACCES; | |
852 | } | |
853 | ||
854 | if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) { | |
16c267aa MZ |
855 | pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); |
856 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
857 | } | |
fed2512a MZ |
858 | break; |
859 | case LOADING_FIRMWARE: | |
4f2d99b0 | 860 | if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) { |
fed2512a MZ |
861 | pr_err("Prevent firmware sysfs fallback loading.\n"); |
862 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
863 | } | |
c77b8cdf MZ |
864 | break; |
865 | case LOADING_MODULE: | |
866 | sig_enforce = is_module_sig_enforced(); | |
867 | ||
b5ca1173 NJ |
868 | if (ima_enforce && (!sig_enforce |
869 | && (ima_appraise & IMA_APPRAISE_MODULES))) { | |
c77b8cdf MZ |
870 | pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); |
871 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
872 | } | |
28073eb0 | 873 | break; |
16c267aa MZ |
874 | default: |
875 | break; | |
876 | } | |
877 | return 0; | |
878 | } | |
879 | ||
b64fcae7 KC |
880 | /** |
881 | * ima_post_load_data - appraise decision based on policy | |
882 | * @buf: pointer to in memory file contents | |
883 | * @size: size of in memory file contents | |
bae60eef RS |
884 | * @load_id: kernel load data caller identifier |
885 | * @description: @load_id-specific description of contents | |
b64fcae7 KC |
886 | * |
887 | * Measure/appraise/audit in memory buffer based on policy. Policy rules | |
888 | * are written in terms of a policy identifier. | |
889 | * | |
890 | * On success return 0. On integrity appraisal error, assuming the file | |
891 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
892 | */ | |
cd3cec0a RS |
893 | static int ima_post_load_data(char *buf, loff_t size, |
894 | enum kernel_load_data_id load_id, | |
895 | char *description) | |
b64fcae7 | 896 | { |
4f2d99b0 KC |
897 | if (load_id == LOADING_FIRMWARE) { |
898 | if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && | |
899 | (ima_appraise & IMA_APPRAISE_ENFORCE)) { | |
900 | pr_err("Prevent firmware loading_store.\n"); | |
901 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
902 | } | |
903 | return 0; | |
904 | } | |
905 | ||
b64fcae7 KC |
906 | return 0; |
907 | } | |
908 | ||
ce5bb5a8 | 909 | /** |
291af651 | 910 | * process_buffer_measurement - Measure the buffer or the buffer data hash |
39f60c1c | 911 | * @idmap: idmap of the mount the inode was found from |
4834177e | 912 | * @inode: inode associated with the object being measured (NULL for KEY_CHECK) |
b0935123 PS |
913 | * @buf: pointer to the buffer that needs to be added to the log. |
914 | * @size: size of buffer(in bytes). | |
915 | * @eventname: event name to be used for the buffer entry. | |
e14555e3 NJ |
916 | * @func: IMA hook |
917 | * @pcr: pcr to extend the measurement | |
2b4a2474 | 918 | * @func_data: func specific data, may be NULL |
291af651 | 919 | * @buf_hash: measure buffer data hash |
ca3c9bdb RS |
920 | * @digest: buffer digest will be written to |
921 | * @digest_len: buffer length | |
b0935123 | 922 | * |
291af651 | 923 | * Based on policy, either the buffer data or buffer data hash is measured |
ce5bb5a8 | 924 | * |
ca3c9bdb RS |
925 | * Return: 0 if the buffer has been successfully measured, 1 if the digest |
926 | * has been written to the passed location but not added to a measurement entry, | |
927 | * a negative value otherwise. | |
b0935123 | 928 | */ |
39f60c1c | 929 | int process_buffer_measurement(struct mnt_idmap *idmap, |
ce5bb5a8 RS |
930 | struct inode *inode, const void *buf, int size, |
931 | const char *eventname, enum ima_hooks func, | |
932 | int pcr, const char *func_data, | |
ca3c9bdb | 933 | bool buf_hash, u8 *digest, size_t digest_len) |
b0935123 PS |
934 | { |
935 | int ret = 0; | |
34e980bb | 936 | const char *audit_cause = "ENOMEM"; |
b0935123 PS |
937 | struct ima_template_entry *entry = NULL; |
938 | struct integrity_iint_cache iint = {}; | |
939 | struct ima_event_data event_data = {.iint = &iint, | |
86b4da8c PS |
940 | .filename = eventname, |
941 | .buf = buf, | |
942 | .buf_len = size}; | |
dea87d08 | 943 | struct ima_template_desc *template; |
8c54135e | 944 | struct ima_max_digest_data hash; |
291af651 TS |
945 | char digest_hash[IMA_MAX_DIGEST_SIZE]; |
946 | int digest_hash_len = hash_digest_size[ima_hash_algo]; | |
b0935123 | 947 | int violation = 0; |
b0935123 | 948 | int action = 0; |
e14555e3 | 949 | u32 secid; |
b0935123 | 950 | |
ca3c9bdb RS |
951 | if (digest && digest_len < digest_hash_len) |
952 | return -EINVAL; | |
953 | ||
954 | if (!ima_policy_flag && !digest) | |
ce5bb5a8 | 955 | return -ENOENT; |
c5563bad | 956 | |
dea87d08 LR |
957 | template = ima_template_desc_buf(); |
958 | if (!template) { | |
959 | ret = -EINVAL; | |
960 | audit_cause = "ima_template_desc_buf"; | |
961 | goto out; | |
962 | } | |
963 | ||
e14555e3 NJ |
964 | /* |
965 | * Both LSM hooks and auxilary based buffer measurements are | |
966 | * based on policy. To avoid code duplication, differentiate | |
967 | * between the LSM hooks and auxilary buffer measurements, | |
968 | * retrieving the policy rule information only for the LSM hook | |
969 | * buffer measurements. | |
970 | */ | |
971 | if (func) { | |
6326948f | 972 | security_current_getsecid_subj(&secid); |
39f60c1c | 973 | action = ima_get_action(idmap, inode, current_cred(), |
a2d2329e | 974 | secid, 0, func, &pcr, &template, |
1624dc00 | 975 | func_data, NULL); |
ca3c9bdb | 976 | if (!(action & IMA_MEASURE) && !digest) |
ce5bb5a8 | 977 | return -ENOENT; |
e14555e3 NJ |
978 | } |
979 | ||
980 | if (!pcr) | |
981 | pcr = CONFIG_IMA_MEASURE_PCR_IDX; | |
982 | ||
b0935123 PS |
983 | iint.ima_hash = &hash.hdr; |
984 | iint.ima_hash->algo = ima_hash_algo; | |
985 | iint.ima_hash->length = hash_digest_size[ima_hash_algo]; | |
986 | ||
987 | ret = ima_calc_buffer_hash(buf, size, iint.ima_hash); | |
34e980bb LR |
988 | if (ret < 0) { |
989 | audit_cause = "hashing_error"; | |
b0935123 | 990 | goto out; |
34e980bb | 991 | } |
b0935123 | 992 | |
291af651 TS |
993 | if (buf_hash) { |
994 | memcpy(digest_hash, hash.hdr.digest, digest_hash_len); | |
995 | ||
996 | ret = ima_calc_buffer_hash(digest_hash, digest_hash_len, | |
997 | iint.ima_hash); | |
998 | if (ret < 0) { | |
999 | audit_cause = "hashing_error"; | |
1000 | goto out; | |
1001 | } | |
1002 | ||
1003 | event_data.buf = digest_hash; | |
1004 | event_data.buf_len = digest_hash_len; | |
1005 | } | |
1006 | ||
ca3c9bdb RS |
1007 | if (digest) |
1008 | memcpy(digest, iint.ima_hash->digest, digest_hash_len); | |
1009 | ||
1010 | if (!ima_policy_flag || (func && !(action & IMA_MEASURE))) | |
1011 | return 1; | |
1012 | ||
e14555e3 | 1013 | ret = ima_alloc_init_template(&event_data, &entry, template); |
34e980bb LR |
1014 | if (ret < 0) { |
1015 | audit_cause = "alloc_entry"; | |
b0935123 | 1016 | goto out; |
34e980bb | 1017 | } |
b0935123 | 1018 | |
291af651 | 1019 | ret = ima_store_template(entry, violation, NULL, event_data.buf, pcr); |
34e980bb LR |
1020 | if (ret < 0) { |
1021 | audit_cause = "store_entry"; | |
b0935123 | 1022 | ima_free_template_entry(entry); |
34e980bb | 1023 | } |
b0935123 PS |
1024 | |
1025 | out: | |
72ec611c | 1026 | if (ret < 0) |
34e980bb LR |
1027 | integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL, eventname, |
1028 | func_measure_str(func), | |
1029 | audit_cause, ret, 0, ret); | |
72ec611c | 1030 | |
ce5bb5a8 | 1031 | return ret; |
b0935123 PS |
1032 | } |
1033 | ||
1034 | /** | |
1035 | * ima_kexec_cmdline - measure kexec cmdline boot args | |
4834177e | 1036 | * @kernel_fd: file descriptor of the kexec kernel being loaded |
b0935123 PS |
1037 | * @buf: pointer to buffer |
1038 | * @size: size of buffer | |
1039 | * | |
1040 | * Buffers can only be measured, not appraised. | |
1041 | */ | |
4834177e | 1042 | void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) |
b0935123 | 1043 | { |
4834177e TH |
1044 | struct fd f; |
1045 | ||
1046 | if (!buf || !size) | |
1047 | return; | |
1048 | ||
1049 | f = fdget(kernel_fd); | |
1050 | if (!f.file) | |
1051 | return; | |
1052 | ||
39f60c1c | 1053 | process_buffer_measurement(file_mnt_idmap(f.file), file_inode(f.file), |
a2d2329e | 1054 | buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0, |
ca3c9bdb | 1055 | NULL, false, NULL, 0); |
4834177e | 1056 | fdput(f); |
b0935123 PS |
1057 | } |
1058 | ||
d6e64501 TS |
1059 | /** |
1060 | * ima_measure_critical_data - measure kernel integrity critical data | |
9f5d7d23 | 1061 | * @event_label: unique event label for grouping and limiting critical data |
d6e64501 TS |
1062 | * @event_name: event name for the record in the IMA measurement list |
1063 | * @buf: pointer to buffer data | |
1064 | * @buf_len: length of buffer data (in bytes) | |
1065 | * @hash: measure buffer data hash | |
ca3c9bdb RS |
1066 | * @digest: buffer digest will be written to |
1067 | * @digest_len: buffer length | |
d6e64501 TS |
1068 | * |
1069 | * Measure data critical to the integrity of the kernel into the IMA log | |
1070 | * and extend the pcr. Examples of critical data could be various data | |
1071 | * structures, policies, and states stored in kernel memory that can | |
1072 | * impact the integrity of the system. | |
ce5bb5a8 | 1073 | * |
ca3c9bdb RS |
1074 | * Return: 0 if the buffer has been successfully measured, 1 if the digest |
1075 | * has been written to the passed location but not added to a measurement entry, | |
1076 | * a negative value otherwise. | |
d6e64501 | 1077 | */ |
ce5bb5a8 RS |
1078 | int ima_measure_critical_data(const char *event_label, |
1079 | const char *event_name, | |
1080 | const void *buf, size_t buf_len, | |
ca3c9bdb | 1081 | bool hash, u8 *digest, size_t digest_len) |
d6e64501 | 1082 | { |
9f5d7d23 | 1083 | if (!event_name || !event_label || !buf || !buf_len) |
ce5bb5a8 | 1084 | return -ENOPARAM; |
d6e64501 | 1085 | |
39f60c1c | 1086 | return process_buffer_measurement(&nop_mnt_idmap, NULL, buf, buf_len, |
ce5bb5a8 | 1087 | event_name, CRITICAL_DATA, 0, |
ca3c9bdb RS |
1088 | event_label, hash, digest, |
1089 | digest_len); | |
d6e64501 | 1090 | } |
91ccbbac | 1091 | EXPORT_SYMBOL_GPL(ima_measure_critical_data); |
d6e64501 | 1092 | |
06cca511 RS |
1093 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS |
1094 | ||
1095 | /** | |
1096 | * ima_kernel_module_request - Prevent crypto-pkcs1pad(rsa,*) requests | |
1097 | * @kmod_name: kernel module name | |
1098 | * | |
1099 | * Avoid a verification loop where verifying the signature of the modprobe | |
1100 | * binary requires executing modprobe itself. Since the modprobe iint->mutex | |
1101 | * is already held when the signature verification is performed, a deadlock | |
1102 | * occurs as soon as modprobe is executed within the critical region, since | |
1103 | * the same lock cannot be taken again. | |
1104 | * | |
1105 | * This happens when public_key_verify_signature(), in case of RSA algorithm, | |
1106 | * use alg_name to store internal information in order to construct an | |
1107 | * algorithm on the fly, but crypto_larval_lookup() will try to use alg_name | |
1108 | * in order to load a kernel module with same name. | |
1109 | * | |
1110 | * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, | |
1111 | * we are safe to fail such module request from crypto_larval_lookup(), and | |
1112 | * avoid the verification loop. | |
1113 | * | |
1114 | * Return: Zero if it is safe to load the kernel module, -EINVAL otherwise. | |
1115 | */ | |
cd3cec0a | 1116 | static int ima_kernel_module_request(char *kmod_name) |
06cca511 RS |
1117 | { |
1118 | if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) | |
1119 | return -EINVAL; | |
1120 | ||
1121 | return 0; | |
1122 | } | |
1123 | ||
1124 | #endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ | |
1125 | ||
3323eec9 MZ |
1126 | static int __init init_ima(void) |
1127 | { | |
1128 | int error; | |
1129 | ||
b000d5cb | 1130 | ima_appraise_parse_cmdline(); |
3f23d624 | 1131 | ima_init_template_list(); |
e7a2ad7e | 1132 | hash_setup(CONFIG_IMA_DEFAULT_HASH); |
3323eec9 | 1133 | error = ima_init(); |
ab60368a PV |
1134 | |
1135 | if (error && strcmp(hash_algo_name[ima_hash_algo], | |
1136 | CONFIG_IMA_DEFAULT_HASH) != 0) { | |
1137 | pr_info("Allocating %s failed, going to use default hash algorithm %s\n", | |
1138 | hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH); | |
1139 | hash_setup_done = 0; | |
1140 | hash_setup(CONFIG_IMA_DEFAULT_HASH); | |
1141 | error = ima_init(); | |
1142 | } | |
1143 | ||
e144d6b2 RS |
1144 | if (error) |
1145 | return error; | |
1146 | ||
b1694245 JK |
1147 | error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier); |
1148 | if (error) | |
1149 | pr_warn("Couldn't register LSM notifier, error %d\n", error); | |
1150 | ||
4ecd9934 | 1151 | if (!error) |
4f2946aa | 1152 | ima_update_policy_flags(); |
4ecd9934 | 1153 | |
3323eec9 MZ |
1154 | return error; |
1155 | } | |
1156 | ||
cd3cec0a RS |
1157 | static struct security_hook_list ima_hooks[] __ro_after_init = { |
1158 | LSM_HOOK_INIT(bprm_check_security, ima_bprm_check), | |
1159 | LSM_HOOK_INIT(file_post_open, ima_file_check), | |
1160 | LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile), | |
1161 | LSM_HOOK_INIT(file_release, ima_file_free), | |
1162 | LSM_HOOK_INIT(mmap_file, ima_file_mmap), | |
1163 | LSM_HOOK_INIT(file_mprotect, ima_file_mprotect), | |
1164 | LSM_HOOK_INIT(kernel_load_data, ima_load_data), | |
1165 | LSM_HOOK_INIT(kernel_post_load_data, ima_post_load_data), | |
1166 | LSM_HOOK_INIT(kernel_read_file, ima_read_file), | |
1167 | LSM_HOOK_INIT(kernel_post_read_file, ima_post_read_file), | |
1168 | LSM_HOOK_INIT(path_post_mknod, ima_post_path_mknod), | |
1169 | #ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS | |
1170 | LSM_HOOK_INIT(key_post_create_or_update, ima_post_key_create_or_update), | |
1171 | #endif | |
1172 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS | |
1173 | LSM_HOOK_INIT(kernel_module_request, ima_kernel_module_request), | |
1174 | #endif | |
1175 | }; | |
1176 | ||
1177 | static const struct lsm_id ima_lsmid = { | |
1178 | .name = "ima", | |
1179 | .id = LSM_ID_IMA, | |
1180 | }; | |
1181 | ||
1182 | static int __init init_ima_lsm(void) | |
1183 | { | |
1184 | security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid); | |
84594c9e | 1185 | init_ima_appraise_lsm(&ima_lsmid); |
cd3cec0a RS |
1186 | return 0; |
1187 | } | |
1188 | ||
1189 | DEFINE_LSM(ima) = { | |
1190 | .name = "ima", | |
1191 | .init = init_ima_lsm, | |
1192 | .order = LSM_ORDER_LAST, | |
1193 | }; | |
1194 | ||
3323eec9 | 1195 | late_initcall(init_ima); /* Start IMA after the TPM is available */ |