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 | 116 | static void ima_rdwr_violation_check(struct file *file, |
4de2f084 | 117 | struct ima_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 | 129 | if (!iint) |
4de2f084 | 130 | iint = ima_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 | ||
4de2f084 | 156 | static void ima_check_last_writer(struct ima_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); |
4de2f084 | 195 | struct ima_iint_cache *iint; |
3323eec9 | 196 | |
0f34a006 | 197 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
3323eec9 | 198 | return; |
196f5181 | 199 | |
4de2f084 | 200 | iint = ima_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 | { |
c21632b6 | 211 | struct inode *real_inode, *inode = file_inode(file); |
4de2f084 | 212 | struct ima_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 | 250 | if (action) { |
4de2f084 | 251 | iint = ima_inode_get(inode); |
f7a859ff | 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 | |
c21632b6 SB |
288 | /* |
289 | * On stacked filesystems, detect and re-evaluate file data changes. | |
290 | */ | |
291 | real_inode = d_real_inode(file_dentry(file)); | |
292 | if (real_inode != inode && | |
b836c4d2 | 293 | (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) { |
c21632b6 SB |
294 | if (!IS_I_VERSION(real_inode) || |
295 | real_inode->i_sb->s_dev != iint->real_dev || | |
296 | real_inode->i_ino != iint->real_ino || | |
297 | !inode_eq_iversion(real_inode, iint->version)) { | |
b836c4d2 MZ |
298 | iint->flags &= ~IMA_DONE_MASK; |
299 | iint->measured_pcrs = 0; | |
300 | } | |
301 | } | |
302 | ||
2fe5d6de | 303 | /* Determine if already appraised/measured based on bitmask |
d79d72e0 MZ |
304 | * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, |
305 | * IMA_AUDIT, IMA_AUDITED) | |
306 | */ | |
2fe5d6de | 307 | iint->flags |= action; |
0e5a247c | 308 | action &= IMA_DO_MASK; |
a422638d ER |
309 | action &= ~((iint->flags & (IMA_DONE_MASK ^ IMA_MEASURED)) >> 1); |
310 | ||
311 | /* If target pcr is already measured, unset IMA_MEASURE action */ | |
312 | if ((action & IMA_MEASURE) && (iint->measured_pcrs & (0x1 << pcr))) | |
313 | action ^= IMA_MEASURE; | |
2fe5d6de | 314 | |
da1b0029 MZ |
315 | /* HASH sets the digital signature and update flags, nothing else */ |
316 | if ((action & IMA_HASH) && | |
317 | !(test_bit(IMA_DIGSIG, &iint->atomic_flags))) { | |
f6fbd8cb PM |
318 | xattr_len = ima_read_xattr(file_dentry(file), |
319 | &xattr_value, xattr_len); | |
da1b0029 MZ |
320 | if ((xattr_value && xattr_len > 2) && |
321 | (xattr_value->type == EVM_IMA_XATTR_DIGSIG)) | |
322 | set_bit(IMA_DIGSIG, &iint->atomic_flags); | |
323 | iint->flags |= IMA_HASHED; | |
324 | action ^= IMA_HASH; | |
325 | set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); | |
326 | } | |
327 | ||
2fe5d6de MZ |
328 | /* Nothing to do, just return existing appraised status */ |
329 | if (!action) { | |
2cd4737b MZ |
330 | if (must_appraise) { |
331 | rc = mmap_violation_check(func, file, &pathbuf, | |
332 | &pathname, filename); | |
333 | if (!rc) | |
334 | rc = ima_get_cache_status(iint, func); | |
335 | } | |
0d73a552 | 336 | goto out_locked; |
2fe5d6de | 337 | } |
3323eec9 | 338 | |
f68c05f4 | 339 | if ((action & IMA_APPRAISE_SUBMASK) || |
39b07096 | 340 | strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) { |
1525b06d | 341 | /* read 'security.ima' */ |
f6fbd8cb PM |
342 | xattr_len = ima_read_xattr(file_dentry(file), |
343 | &xattr_value, xattr_len); | |
d3634d0f | 344 | |
e5092255 TJB |
345 | /* |
346 | * Read the appended modsig if allowed by the policy, and allow | |
347 | * an additional measurement list entry, if needed, based on the | |
348 | * template format and whether the file was already measured. | |
349 | */ | |
350 | if (iint->flags & IMA_MODSIG_ALLOWED) { | |
351 | rc = ima_read_modsig(func, buf, size, &modsig); | |
352 | ||
353 | if (!rc && ima_template_has_modsig(template_desc) && | |
354 | iint->flags & IMA_MEASURED) | |
355 | action |= IMA_MEASURE; | |
356 | } | |
39b07096 TJB |
357 | } |
358 | ||
1525b06d DK |
359 | hash_algo = ima_get_hash_algo(xattr_value, xattr_len); |
360 | ||
15588227 | 361 | rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig); |
6dc387d5 | 362 | if (rc != 0 && rc != -EBADF && rc != -EINVAL) |
0d73a552 | 363 | goto out_locked; |
08e1b76a | 364 | |
bc15ed66 MZ |
365 | if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */ |
366 | pathname = ima_d_path(&file->f_path, &pathbuf, filename); | |
08e1b76a | 367 | |
2fe5d6de | 368 | if (action & IMA_MEASURE) |
bcbc9b0c | 369 | ima_store_measurement(iint, file, pathname, |
3878d505 | 370 | xattr_value, xattr_len, modsig, pcr, |
19453ce0 | 371 | template_desc); |
0d73a552 | 372 | if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { |
273df864 NJ |
373 | rc = ima_check_blacklist(iint, modsig, pcr); |
374 | if (rc != -EPERM) { | |
375 | inode_lock(inode); | |
376 | rc = ima_appraise_measurement(func, iint, file, | |
377 | pathname, xattr_value, | |
378 | xattr_len, modsig); | |
379 | inode_unlock(inode); | |
380 | } | |
2cd4737b MZ |
381 | if (!rc) |
382 | rc = mmap_violation_check(func, file, &pathbuf, | |
383 | &pathname, filename); | |
0d73a552 | 384 | } |
e7c568e0 | 385 | if (action & IMA_AUDIT) |
ea1046d4 | 386 | ima_audit_measurement(iint, pathname); |
f7a859ff | 387 | |
f3cc6b25 MZ |
388 | if ((file->f_flags & O_DIRECT) && (iint->flags & IMA_PERMIT_DIRECTIO)) |
389 | rc = 0; | |
1624dc00 TS |
390 | |
391 | /* Ensure the digest was generated using an allowed algorithm */ | |
392 | if (rc == 0 && must_appraise && allowed_algos != 0 && | |
393 | (allowed_algos & (1U << hash_algo)) == 0) { | |
394 | rc = -EACCES; | |
395 | ||
396 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, file_inode(file), | |
397 | pathname, "collect_data", | |
398 | "denied-hash-algorithm", rc, 0); | |
399 | } | |
0d73a552 DK |
400 | out_locked: |
401 | if ((mask & MAY_WRITE) && test_bit(IMA_DIGSIG, &iint->atomic_flags) && | |
05d1a717 | 402 | !(iint->flags & IMA_NEW_FILE)) |
a175b8bb | 403 | rc = -EACCES; |
0d73a552 | 404 | mutex_unlock(&iint->mutex); |
f7a859ff | 405 | kfree(xattr_value); |
39b07096 | 406 | ima_free_modsig(modsig); |
0d73a552 | 407 | out: |
456f5fd3 DK |
408 | if (pathbuf) |
409 | __putname(pathbuf); | |
0d73a552 DK |
410 | if (must_appraise) { |
411 | if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE)) | |
412 | return -EACCES; | |
413 | if (file->f_mode & FMODE_WRITE) | |
414 | set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); | |
415 | } | |
750943a3 | 416 | return 0; |
3323eec9 MZ |
417 | } |
418 | ||
419 | /** | |
420 | * ima_file_mmap - based on policy, collect/store measurement. | |
421 | * @file: pointer to the file to be measured (May be NULL) | |
4971c268 RS |
422 | * @reqprot: protection requested by the application |
423 | * @prot: protection that will be applied by the kernel | |
424 | * @flags: operational flags | |
3323eec9 MZ |
425 | * |
426 | * Measure files being mmapped executable based on the ima_must_measure() | |
427 | * policy decision. | |
428 | * | |
750943a3 DK |
429 | * On success return 0. On integrity appraisal error, assuming the file |
430 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
3323eec9 | 431 | */ |
cd3cec0a RS |
432 | static int ima_file_mmap(struct file *file, unsigned long reqprot, |
433 | unsigned long prot, unsigned long flags) | |
3323eec9 | 434 | { |
d906c10d | 435 | u32 secid; |
4958db32 | 436 | int ret; |
d906c10d | 437 | |
4958db32 RS |
438 | if (!file) |
439 | return 0; | |
440 | ||
441 | security_current_getsecid_subj(&secid); | |
442 | ||
443 | if (reqprot & PROT_EXEC) { | |
444 | ret = process_measurement(file, current_cred(), secid, NULL, | |
445 | 0, MAY_EXEC, MMAP_CHECK_REQPROT); | |
446 | if (ret) | |
447 | return ret; | |
448 | } | |
449 | ||
450 | if (prot & PROT_EXEC) | |
d906c10d | 451 | return process_measurement(file, current_cred(), secid, NULL, |
6035a27b | 452 | 0, MAY_EXEC, MMAP_CHECK); |
d906c10d | 453 | |
750943a3 | 454 | return 0; |
3323eec9 MZ |
455 | } |
456 | ||
8eb613c0 MZ |
457 | /** |
458 | * ima_file_mprotect - based on policy, limit mprotect change | |
bae60eef | 459 | * @vma: vm_area_struct protection is set to |
0298c5a9 RS |
460 | * @reqprot: protection requested by the application |
461 | * @prot: protection that will be applied by the kernel | |
8eb613c0 MZ |
462 | * |
463 | * Files can be mmap'ed read/write and later changed to execute to circumvent | |
464 | * IMA's mmap appraisal policy rules. Due to locking issues (mmap semaphore | |
465 | * would be taken before i_mutex), files can not be measured or appraised at | |
466 | * this point. Eliminate this integrity gap by denying the mprotect | |
467 | * PROT_EXECUTE change, if an mmap appraise policy rule exists. | |
468 | * | |
469 | * On mprotect change success, return 0. On failure, return -EACESS. | |
470 | */ | |
cd3cec0a RS |
471 | static int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
472 | unsigned long prot) | |
8eb613c0 | 473 | { |
dea87d08 | 474 | struct ima_template_desc *template = NULL; |
29d1c2b4 | 475 | struct file *file; |
8eb613c0 MZ |
476 | char filename[NAME_MAX]; |
477 | char *pathbuf = NULL; | |
478 | const char *pathname = NULL; | |
479 | struct inode *inode; | |
480 | int result = 0; | |
481 | int action; | |
482 | u32 secid; | |
483 | int pcr; | |
484 | ||
485 | /* Is mprotect making an mmap'ed file executable? */ | |
4235b1a4 MZ |
486 | if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file || |
487 | !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC)) | |
8eb613c0 MZ |
488 | return 0; |
489 | ||
6326948f | 490 | security_current_getsecid_subj(&secid); |
8eb613c0 | 491 | inode = file_inode(vma->vm_file); |
39f60c1c | 492 | action = ima_get_action(file_mnt_idmap(vma->vm_file), inode, |
a2d2329e | 493 | current_cred(), secid, MAY_EXEC, MMAP_CHECK, |
1624dc00 | 494 | &pcr, &template, NULL, NULL); |
67e2dcff | 495 | action |= ima_get_action(file_mnt_idmap(vma->vm_file), inode, |
4958db32 RS |
496 | current_cred(), secid, MAY_EXEC, |
497 | MMAP_CHECK_REQPROT, &pcr, &template, NULL, | |
498 | NULL); | |
8eb613c0 MZ |
499 | |
500 | /* Is the mmap'ed file in policy? */ | |
501 | if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) | |
502 | return 0; | |
503 | ||
504 | if (action & IMA_APPRAISE_SUBMASK) | |
505 | result = -EPERM; | |
506 | ||
507 | file = vma->vm_file; | |
508 | pathname = ima_d_path(&file->f_path, &pathbuf, filename); | |
509 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, pathname, | |
510 | "collect_data", "failed-mprotect", result, 0); | |
511 | if (pathbuf) | |
512 | __putname(pathbuf); | |
513 | ||
514 | return result; | |
515 | } | |
516 | ||
3323eec9 MZ |
517 | /** |
518 | * ima_bprm_check - based on policy, collect/store measurement. | |
519 | * @bprm: contains the linux_binprm structure | |
520 | * | |
521 | * The OS protects against an executable file, already open for write, | |
522 | * from being executed in deny_write_access() and an executable file, | |
523 | * already open for execute, from being modified in get_write_access(). | |
524 | * So we can be certain that what we verify and measure here is actually | |
525 | * what is being executed. | |
526 | * | |
750943a3 DK |
527 | * On success return 0. On integrity appraisal error, assuming the file |
528 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
3323eec9 | 529 | */ |
cd3cec0a | 530 | static int ima_bprm_check(struct linux_binprm *bprm) |
3323eec9 | 531 | { |
d906c10d MG |
532 | int ret; |
533 | u32 secid; | |
534 | ||
6326948f | 535 | security_current_getsecid_subj(&secid); |
d906c10d | 536 | ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, |
6035a27b | 537 | MAY_EXEC, BPRM_CHECK); |
d906c10d MG |
538 | if (ret) |
539 | return ret; | |
540 | ||
541 | security_cred_getsecid(bprm->cred, &secid); | |
542 | return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, | |
6035a27b | 543 | MAY_EXEC, CREDS_CHECK); |
3323eec9 MZ |
544 | } |
545 | ||
8eb988c7 | 546 | /** |
41d75dd9 | 547 | * ima_file_check - based on policy, collect/store measurement. |
8eb988c7 | 548 | * @file: pointer to the file to be measured |
20f482ab | 549 | * @mask: contains MAY_READ, MAY_WRITE, MAY_EXEC or MAY_APPEND |
8eb988c7 MZ |
550 | * |
551 | * Measure files based on the ima_must_measure() policy decision. | |
552 | * | |
750943a3 DK |
553 | * On success return 0. On integrity appraisal error, assuming the file |
554 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
8eb988c7 | 555 | */ |
cd3cec0a | 556 | static int ima_file_check(struct file *file, int mask) |
8eb988c7 | 557 | { |
d906c10d MG |
558 | u32 secid; |
559 | ||
6326948f | 560 | security_current_getsecid_subj(&secid); |
d906c10d | 561 | return process_measurement(file, current_cred(), secid, NULL, 0, |
20f482ab | 562 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC | |
6035a27b | 563 | MAY_APPEND), FILE_CHECK); |
8eb988c7 | 564 | } |
8eb988c7 | 565 | |
280fe836 RS |
566 | static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, |
567 | size_t buf_size) | |
6beea7af | 568 | { |
4de2f084 | 569 | struct ima_iint_cache *iint = NULL, tmp_iint; |
280fe836 | 570 | int rc, hash_algo; |
6beea7af | 571 | |
280fe836 | 572 | if (ima_policy_flag) { |
4de2f084 | 573 | iint = ima_iint_find(inode); |
280fe836 RS |
574 | if (iint) |
575 | mutex_lock(&iint->mutex); | |
576 | } | |
577 | ||
578 | if ((!iint || !(iint->flags & IMA_COLLECTED)) && file) { | |
579 | if (iint) | |
580 | mutex_unlock(&iint->mutex); | |
581 | ||
582 | memset(&tmp_iint, 0, sizeof(tmp_iint)); | |
280fe836 RS |
583 | mutex_init(&tmp_iint.mutex); |
584 | ||
585 | rc = ima_collect_measurement(&tmp_iint, file, NULL, 0, | |
586 | ima_hash_algo, NULL); | |
8c1d6a05 RS |
587 | if (rc < 0) { |
588 | /* ima_hash could be allocated in case of failure. */ | |
589 | if (rc != -ENOMEM) | |
590 | kfree(tmp_iint.ima_hash); | |
591 | ||
280fe836 | 592 | return -EOPNOTSUPP; |
8c1d6a05 | 593 | } |
280fe836 RS |
594 | |
595 | iint = &tmp_iint; | |
596 | mutex_lock(&iint->mutex); | |
597 | } | |
6beea7af | 598 | |
6beea7af FR |
599 | if (!iint) |
600 | return -EOPNOTSUPP; | |
601 | ||
aa662fc0 KS |
602 | /* |
603 | * ima_file_hash can be called when ima_collect_measurement has still | |
604 | * not been called, we might not always have a hash. | |
605 | */ | |
62622dab | 606 | if (!iint->ima_hash || !(iint->flags & IMA_COLLECTED)) { |
aa662fc0 KS |
607 | mutex_unlock(&iint->mutex); |
608 | return -EOPNOTSUPP; | |
609 | } | |
610 | ||
6beea7af FR |
611 | if (buf) { |
612 | size_t copied_size; | |
613 | ||
614 | copied_size = min_t(size_t, iint->ima_hash->length, buf_size); | |
615 | memcpy(buf, iint->ima_hash->digest, copied_size); | |
616 | } | |
617 | hash_algo = iint->ima_hash->algo; | |
618 | mutex_unlock(&iint->mutex); | |
619 | ||
280fe836 RS |
620 | if (iint == &tmp_iint) |
621 | kfree(iint->ima_hash); | |
622 | ||
6beea7af FR |
623 | return hash_algo; |
624 | } | |
403319be KS |
625 | |
626 | /** | |
280fe836 | 627 | * ima_file_hash - return a measurement of the file |
403319be KS |
628 | * @file: pointer to the file |
629 | * @buf: buffer in which to store the hash | |
630 | * @buf_size: length of the buffer | |
631 | * | |
632 | * On success, return the hash algorithm (as defined in the enum hash_algo). | |
633 | * If buf is not NULL, this function also outputs the hash into buf. | |
634 | * If the hash is larger than buf_size, then only buf_size bytes will be copied. | |
635 | * It generally just makes sense to pass a buffer capable of holding the largest | |
636 | * possible hash: IMA_MAX_DIGEST_SIZE. | |
637 | * The file hash returned is based on the entire file, including the appended | |
638 | * signature. | |
639 | * | |
280fe836 | 640 | * If the measurement cannot be performed, return -EOPNOTSUPP. |
403319be KS |
641 | * If the parameters are incorrect, return -EINVAL. |
642 | */ | |
643 | int ima_file_hash(struct file *file, char *buf, size_t buf_size) | |
644 | { | |
645 | if (!file) | |
646 | return -EINVAL; | |
647 | ||
280fe836 | 648 | return __ima_inode_hash(file_inode(file), file, buf, buf_size); |
403319be | 649 | } |
6beea7af FR |
650 | EXPORT_SYMBOL_GPL(ima_file_hash); |
651 | ||
403319be KS |
652 | /** |
653 | * ima_inode_hash - return the stored measurement if the inode has been hashed | |
654 | * and is in the iint cache. | |
655 | * @inode: pointer to the inode | |
656 | * @buf: buffer in which to store the hash | |
657 | * @buf_size: length of the buffer | |
658 | * | |
659 | * On success, return the hash algorithm (as defined in the enum hash_algo). | |
660 | * If buf is not NULL, this function also outputs the hash into buf. | |
661 | * If the hash is larger than buf_size, then only buf_size bytes will be copied. | |
662 | * It generally just makes sense to pass a buffer capable of holding the largest | |
663 | * possible hash: IMA_MAX_DIGEST_SIZE. | |
664 | * The hash returned is based on the entire contents, including the appended | |
665 | * signature. | |
666 | * | |
667 | * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. | |
668 | * If the parameters are incorrect, return -EINVAL. | |
669 | */ | |
670 | int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) | |
671 | { | |
672 | if (!inode) | |
673 | return -EINVAL; | |
674 | ||
280fe836 | 675 | return __ima_inode_hash(inode, NULL, buf, buf_size); |
403319be KS |
676 | } |
677 | EXPORT_SYMBOL_GPL(ima_inode_hash); | |
678 | ||
fdb2410f MZ |
679 | /** |
680 | * ima_post_create_tmpfile - mark newly created tmpfile as new | |
39f60c1c | 681 | * @idmap: idmap of the mount the inode was found from |
bae60eef | 682 | * @inode: inode of the newly created tmpfile |
fdb2410f MZ |
683 | * |
684 | * No measuring, appraising or auditing of newly created tmpfiles is needed. | |
685 | * Skip calling process_measurement(), but indicate which newly, created | |
686 | * tmpfiles are in policy. | |
687 | */ | |
cd3cec0a RS |
688 | static void ima_post_create_tmpfile(struct mnt_idmap *idmap, |
689 | struct inode *inode) | |
690 | ||
fdb2410f | 691 | { |
4de2f084 | 692 | struct ima_iint_cache *iint; |
fdb2410f MZ |
693 | int must_appraise; |
694 | ||
f873b28f MZ |
695 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
696 | return; | |
697 | ||
39f60c1c | 698 | must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS, |
a2d2329e | 699 | FILE_CHECK); |
fdb2410f MZ |
700 | if (!must_appraise) |
701 | return; | |
702 | ||
703 | /* Nothing to do if we can't allocate memory */ | |
4de2f084 | 704 | iint = ima_inode_get(inode); |
fdb2410f MZ |
705 | if (!iint) |
706 | return; | |
707 | ||
708 | /* needed for writing the security xattrs */ | |
709 | set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); | |
710 | iint->ima_file_status = INTEGRITY_PASS; | |
711 | } | |
712 | ||
05d1a717 MZ |
713 | /** |
714 | * ima_post_path_mknod - mark as a new inode | |
39f60c1c | 715 | * @idmap: idmap of the mount the inode was found from |
05d1a717 MZ |
716 | * @dentry: newly created dentry |
717 | * | |
718 | * Mark files created via the mknodat syscall as new, so that the | |
719 | * file data can be written later. | |
720 | */ | |
cd3cec0a | 721 | static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) |
05d1a717 | 722 | { |
4de2f084 | 723 | struct ima_iint_cache *iint; |
05d1a717 MZ |
724 | struct inode *inode = dentry->d_inode; |
725 | int must_appraise; | |
726 | ||
f873b28f MZ |
727 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
728 | return; | |
729 | ||
39f60c1c | 730 | must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS, |
a2d2329e | 731 | FILE_CHECK); |
05d1a717 MZ |
732 | if (!must_appraise) |
733 | return; | |
734 | ||
fdb2410f | 735 | /* Nothing to do if we can't allocate memory */ |
4de2f084 | 736 | iint = ima_inode_get(inode); |
fdb2410f MZ |
737 | if (!iint) |
738 | return; | |
739 | ||
740 | /* needed for re-opening empty files */ | |
741 | iint->flags |= IMA_NEW_FILE; | |
05d1a717 MZ |
742 | } |
743 | ||
39eeb4fb MZ |
744 | /** |
745 | * ima_read_file - pre-measure/appraise hook decision based on policy | |
746 | * @file: pointer to the file to be measured/appraised/audit | |
747 | * @read_id: caller identifier | |
2039bda1 | 748 | * @contents: whether a subsequent call will be made to ima_post_read_file() |
39eeb4fb MZ |
749 | * |
750 | * Permit reading a file based on policy. The policy rules are written | |
751 | * in terms of the policy identifier. Appraising the integrity of | |
752 | * a file requires a file descriptor. | |
753 | * | |
754 | * For permission return 0, otherwise return -EACCES. | |
755 | */ | |
cd3cec0a RS |
756 | static int ima_read_file(struct file *file, enum kernel_read_file_id read_id, |
757 | bool contents) | |
39eeb4fb | 758 | { |
34736dae SB |
759 | enum ima_hooks func; |
760 | u32 secid; | |
2039bda1 | 761 | |
4f0496d8 | 762 | /* |
4f0496d8 MZ |
763 | * Do devices using pre-allocated memory run the risk of the |
764 | * firmware being accessible to the device prior to the completion | |
765 | * of IMA's signature verification any more than when using two | |
c307459b KC |
766 | * buffers? It may be desirable to include the buffer address |
767 | * in this API and walk all the dma_map_single() mappings to check. | |
4f0496d8 | 768 | */ |
34736dae SB |
769 | |
770 | /* | |
771 | * There will be a call made to ima_post_read_file() with | |
772 | * a filled buffer, so we don't need to perform an extra | |
773 | * read early here. | |
774 | */ | |
775 | if (contents) | |
776 | return 0; | |
777 | ||
778 | /* Read entire file for all partial reads. */ | |
779 | func = read_idmap[read_id] ?: FILE_CHECK; | |
6326948f | 780 | security_current_getsecid_subj(&secid); |
34736dae SB |
781 | return process_measurement(file, current_cred(), secid, NULL, |
782 | 0, MAY_READ, func); | |
39eeb4fb MZ |
783 | } |
784 | ||
29d3c1c8 | 785 | const int read_idmap[READING_MAX_ID] = { |
d9ddf077 MZ |
786 | [READING_FIRMWARE] = FIRMWARE_CHECK, |
787 | [READING_MODULE] = MODULE_CHECK, | |
788 | [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, | |
789 | [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, | |
19f8a847 | 790 | [READING_POLICY] = POLICY_CHECK |
d9ddf077 MZ |
791 | }; |
792 | ||
cf222217 MZ |
793 | /** |
794 | * ima_post_read_file - in memory collect/appraise/audit measurement | |
795 | * @file: pointer to the file to be measured/appraised/audit | |
796 | * @buf: pointer to in memory file contents | |
797 | * @size: size of in memory file contents | |
798 | * @read_id: caller identifier | |
799 | * | |
800 | * Measure/appraise/audit in memory file based on policy. Policy rules | |
801 | * are written in terms of a policy identifier. | |
802 | * | |
803 | * On success return 0. On integrity appraisal error, assuming the file | |
804 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
805 | */ | |
cd3cec0a RS |
806 | static int ima_post_read_file(struct file *file, char *buf, loff_t size, |
807 | enum kernel_read_file_id read_id) | |
cf222217 | 808 | { |
d9ddf077 | 809 | enum ima_hooks func; |
d906c10d | 810 | u32 secid; |
cf222217 | 811 | |
a7d3d039 CH |
812 | /* permit signed certs */ |
813 | if (!file && read_id == READING_X509_CERTIFICATE) | |
814 | return 0; | |
815 | ||
cf222217 MZ |
816 | if (!file || !buf || size == 0) { /* should never happen */ |
817 | if (ima_appraise & IMA_APPRAISE_ENFORCE) | |
818 | return -EACCES; | |
819 | return 0; | |
820 | } | |
821 | ||
d9ddf077 | 822 | func = read_idmap[read_id] ?: FILE_CHECK; |
6326948f | 823 | security_current_getsecid_subj(&secid); |
d906c10d | 824 | return process_measurement(file, current_cred(), secid, buf, size, |
6035a27b | 825 | MAY_READ, func); |
5a9196d7 MZ |
826 | } |
827 | ||
16c267aa MZ |
828 | /** |
829 | * ima_load_data - appraise decision based on policy | |
830 | * @id: kernel load data caller identifier | |
b64fcae7 KC |
831 | * @contents: whether the full contents will be available in a later |
832 | * call to ima_post_load_data(). | |
16c267aa MZ |
833 | * |
834 | * Callers of this LSM hook can not measure, appraise, or audit the | |
65603435 | 835 | * data provided by userspace. Enforce policy rules requiring a file |
16c267aa MZ |
836 | * signature (eg. kexec'ed kernel image). |
837 | * | |
838 | * For permission return 0, otherwise return -EACCES. | |
839 | */ | |
cd3cec0a | 840 | static int ima_load_data(enum kernel_load_data_id id, bool contents) |
16c267aa | 841 | { |
b5ca1173 | 842 | bool ima_enforce, sig_enforce; |
c77b8cdf | 843 | |
b5ca1173 NJ |
844 | ima_enforce = |
845 | (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE; | |
16c267aa MZ |
846 | |
847 | switch (id) { | |
848 | case LOADING_KEXEC_IMAGE: | |
99d5cadf | 849 | if (IS_ENABLED(CONFIG_KEXEC_SIG) |
b5ca1173 NJ |
850 | && arch_ima_get_secureboot()) { |
851 | pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); | |
852 | return -EACCES; | |
853 | } | |
854 | ||
855 | if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) { | |
16c267aa MZ |
856 | pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); |
857 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
858 | } | |
fed2512a MZ |
859 | break; |
860 | case LOADING_FIRMWARE: | |
4f2d99b0 | 861 | if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) { |
fed2512a MZ |
862 | pr_err("Prevent firmware sysfs fallback loading.\n"); |
863 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
864 | } | |
c77b8cdf MZ |
865 | break; |
866 | case LOADING_MODULE: | |
867 | sig_enforce = is_module_sig_enforced(); | |
868 | ||
b5ca1173 NJ |
869 | if (ima_enforce && (!sig_enforce |
870 | && (ima_appraise & IMA_APPRAISE_MODULES))) { | |
c77b8cdf MZ |
871 | pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); |
872 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
873 | } | |
28073eb0 | 874 | break; |
16c267aa MZ |
875 | default: |
876 | break; | |
877 | } | |
878 | return 0; | |
879 | } | |
880 | ||
b64fcae7 KC |
881 | /** |
882 | * ima_post_load_data - appraise decision based on policy | |
883 | * @buf: pointer to in memory file contents | |
884 | * @size: size of in memory file contents | |
bae60eef RS |
885 | * @load_id: kernel load data caller identifier |
886 | * @description: @load_id-specific description of contents | |
b64fcae7 KC |
887 | * |
888 | * Measure/appraise/audit in memory buffer based on policy. Policy rules | |
889 | * are written in terms of a policy identifier. | |
890 | * | |
891 | * On success return 0. On integrity appraisal error, assuming the file | |
892 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | |
893 | */ | |
cd3cec0a RS |
894 | static int ima_post_load_data(char *buf, loff_t size, |
895 | enum kernel_load_data_id load_id, | |
896 | char *description) | |
b64fcae7 | 897 | { |
4f2d99b0 KC |
898 | if (load_id == LOADING_FIRMWARE) { |
899 | if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && | |
900 | (ima_appraise & IMA_APPRAISE_ENFORCE)) { | |
901 | pr_err("Prevent firmware loading_store.\n"); | |
902 | return -EACCES; /* INTEGRITY_UNKNOWN */ | |
903 | } | |
904 | return 0; | |
905 | } | |
906 | ||
cc293c84 MZ |
907 | /* |
908 | * Measure the init_module syscall buffer containing the ELF image. | |
909 | */ | |
910 | if (load_id == LOADING_MODULE) | |
911 | ima_measure_critical_data("modules", "init_module", | |
912 | buf, size, true, NULL, 0); | |
913 | ||
b64fcae7 KC |
914 | return 0; |
915 | } | |
916 | ||
ce5bb5a8 | 917 | /** |
291af651 | 918 | * process_buffer_measurement - Measure the buffer or the buffer data hash |
39f60c1c | 919 | * @idmap: idmap of the mount the inode was found from |
4834177e | 920 | * @inode: inode associated with the object being measured (NULL for KEY_CHECK) |
b0935123 PS |
921 | * @buf: pointer to the buffer that needs to be added to the log. |
922 | * @size: size of buffer(in bytes). | |
923 | * @eventname: event name to be used for the buffer entry. | |
e14555e3 NJ |
924 | * @func: IMA hook |
925 | * @pcr: pcr to extend the measurement | |
2b4a2474 | 926 | * @func_data: func specific data, may be NULL |
291af651 | 927 | * @buf_hash: measure buffer data hash |
ca3c9bdb RS |
928 | * @digest: buffer digest will be written to |
929 | * @digest_len: buffer length | |
b0935123 | 930 | * |
291af651 | 931 | * Based on policy, either the buffer data or buffer data hash is measured |
ce5bb5a8 | 932 | * |
ca3c9bdb RS |
933 | * Return: 0 if the buffer has been successfully measured, 1 if the digest |
934 | * has been written to the passed location but not added to a measurement entry, | |
935 | * a negative value otherwise. | |
b0935123 | 936 | */ |
39f60c1c | 937 | int process_buffer_measurement(struct mnt_idmap *idmap, |
ce5bb5a8 RS |
938 | struct inode *inode, const void *buf, int size, |
939 | const char *eventname, enum ima_hooks func, | |
940 | int pcr, const char *func_data, | |
ca3c9bdb | 941 | bool buf_hash, u8 *digest, size_t digest_len) |
b0935123 PS |
942 | { |
943 | int ret = 0; | |
34e980bb | 944 | const char *audit_cause = "ENOMEM"; |
b0935123 | 945 | struct ima_template_entry *entry = NULL; |
4de2f084 | 946 | struct ima_iint_cache iint = {}; |
b0935123 | 947 | struct ima_event_data event_data = {.iint = &iint, |
86b4da8c PS |
948 | .filename = eventname, |
949 | .buf = buf, | |
950 | .buf_len = size}; | |
dea87d08 | 951 | struct ima_template_desc *template; |
8c54135e | 952 | struct ima_max_digest_data hash; |
38aa3f5a GS |
953 | struct ima_digest_data *hash_hdr = container_of(&hash.hdr, |
954 | struct ima_digest_data, hdr); | |
291af651 TS |
955 | char digest_hash[IMA_MAX_DIGEST_SIZE]; |
956 | int digest_hash_len = hash_digest_size[ima_hash_algo]; | |
b0935123 | 957 | int violation = 0; |
b0935123 | 958 | int action = 0; |
e14555e3 | 959 | u32 secid; |
b0935123 | 960 | |
ca3c9bdb RS |
961 | if (digest && digest_len < digest_hash_len) |
962 | return -EINVAL; | |
963 | ||
964 | if (!ima_policy_flag && !digest) | |
ce5bb5a8 | 965 | return -ENOENT; |
c5563bad | 966 | |
dea87d08 LR |
967 | template = ima_template_desc_buf(); |
968 | if (!template) { | |
969 | ret = -EINVAL; | |
970 | audit_cause = "ima_template_desc_buf"; | |
971 | goto out; | |
972 | } | |
973 | ||
e14555e3 NJ |
974 | /* |
975 | * Both LSM hooks and auxilary based buffer measurements are | |
976 | * based on policy. To avoid code duplication, differentiate | |
977 | * between the LSM hooks and auxilary buffer measurements, | |
978 | * retrieving the policy rule information only for the LSM hook | |
979 | * buffer measurements. | |
980 | */ | |
981 | if (func) { | |
6326948f | 982 | security_current_getsecid_subj(&secid); |
39f60c1c | 983 | action = ima_get_action(idmap, inode, current_cred(), |
a2d2329e | 984 | secid, 0, func, &pcr, &template, |
1624dc00 | 985 | func_data, NULL); |
ca3c9bdb | 986 | if (!(action & IMA_MEASURE) && !digest) |
ce5bb5a8 | 987 | return -ENOENT; |
e14555e3 NJ |
988 | } |
989 | ||
990 | if (!pcr) | |
991 | pcr = CONFIG_IMA_MEASURE_PCR_IDX; | |
992 | ||
38aa3f5a | 993 | iint.ima_hash = hash_hdr; |
b0935123 PS |
994 | iint.ima_hash->algo = ima_hash_algo; |
995 | iint.ima_hash->length = hash_digest_size[ima_hash_algo]; | |
996 | ||
997 | ret = ima_calc_buffer_hash(buf, size, iint.ima_hash); | |
34e980bb LR |
998 | if (ret < 0) { |
999 | audit_cause = "hashing_error"; | |
b0935123 | 1000 | goto out; |
34e980bb | 1001 | } |
b0935123 | 1002 | |
291af651 | 1003 | if (buf_hash) { |
38aa3f5a | 1004 | memcpy(digest_hash, hash_hdr->digest, digest_hash_len); |
291af651 TS |
1005 | |
1006 | ret = ima_calc_buffer_hash(digest_hash, digest_hash_len, | |
1007 | iint.ima_hash); | |
1008 | if (ret < 0) { | |
1009 | audit_cause = "hashing_error"; | |
1010 | goto out; | |
1011 | } | |
1012 | ||
1013 | event_data.buf = digest_hash; | |
1014 | event_data.buf_len = digest_hash_len; | |
1015 | } | |
1016 | ||
ca3c9bdb RS |
1017 | if (digest) |
1018 | memcpy(digest, iint.ima_hash->digest, digest_hash_len); | |
1019 | ||
1020 | if (!ima_policy_flag || (func && !(action & IMA_MEASURE))) | |
1021 | return 1; | |
1022 | ||
e14555e3 | 1023 | ret = ima_alloc_init_template(&event_data, &entry, template); |
34e980bb LR |
1024 | if (ret < 0) { |
1025 | audit_cause = "alloc_entry"; | |
b0935123 | 1026 | goto out; |
34e980bb | 1027 | } |
b0935123 | 1028 | |
291af651 | 1029 | ret = ima_store_template(entry, violation, NULL, event_data.buf, pcr); |
34e980bb LR |
1030 | if (ret < 0) { |
1031 | audit_cause = "store_entry"; | |
b0935123 | 1032 | ima_free_template_entry(entry); |
34e980bb | 1033 | } |
b0935123 PS |
1034 | |
1035 | out: | |
72ec611c | 1036 | if (ret < 0) |
34e980bb LR |
1037 | integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL, eventname, |
1038 | func_measure_str(func), | |
1039 | audit_cause, ret, 0, ret); | |
72ec611c | 1040 | |
ce5bb5a8 | 1041 | return ret; |
b0935123 PS |
1042 | } |
1043 | ||
1044 | /** | |
1045 | * ima_kexec_cmdline - measure kexec cmdline boot args | |
4834177e | 1046 | * @kernel_fd: file descriptor of the kexec kernel being loaded |
b0935123 PS |
1047 | * @buf: pointer to buffer |
1048 | * @size: size of buffer | |
1049 | * | |
1050 | * Buffers can only be measured, not appraised. | |
1051 | */ | |
4834177e | 1052 | void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) |
b0935123 | 1053 | { |
4834177e TH |
1054 | struct fd f; |
1055 | ||
1056 | if (!buf || !size) | |
1057 | return; | |
1058 | ||
1059 | f = fdget(kernel_fd); | |
1060 | if (!f.file) | |
1061 | return; | |
1062 | ||
39f60c1c | 1063 | process_buffer_measurement(file_mnt_idmap(f.file), file_inode(f.file), |
a2d2329e | 1064 | buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0, |
ca3c9bdb | 1065 | NULL, false, NULL, 0); |
4834177e | 1066 | fdput(f); |
b0935123 PS |
1067 | } |
1068 | ||
d6e64501 TS |
1069 | /** |
1070 | * ima_measure_critical_data - measure kernel integrity critical data | |
9f5d7d23 | 1071 | * @event_label: unique event label for grouping and limiting critical data |
d6e64501 TS |
1072 | * @event_name: event name for the record in the IMA measurement list |
1073 | * @buf: pointer to buffer data | |
1074 | * @buf_len: length of buffer data (in bytes) | |
1075 | * @hash: measure buffer data hash | |
ca3c9bdb RS |
1076 | * @digest: buffer digest will be written to |
1077 | * @digest_len: buffer length | |
d6e64501 TS |
1078 | * |
1079 | * Measure data critical to the integrity of the kernel into the IMA log | |
1080 | * and extend the pcr. Examples of critical data could be various data | |
1081 | * structures, policies, and states stored in kernel memory that can | |
1082 | * impact the integrity of the system. | |
ce5bb5a8 | 1083 | * |
ca3c9bdb RS |
1084 | * Return: 0 if the buffer has been successfully measured, 1 if the digest |
1085 | * has been written to the passed location but not added to a measurement entry, | |
1086 | * a negative value otherwise. | |
d6e64501 | 1087 | */ |
ce5bb5a8 RS |
1088 | int ima_measure_critical_data(const char *event_label, |
1089 | const char *event_name, | |
1090 | const void *buf, size_t buf_len, | |
ca3c9bdb | 1091 | bool hash, u8 *digest, size_t digest_len) |
d6e64501 | 1092 | { |
9f5d7d23 | 1093 | if (!event_name || !event_label || !buf || !buf_len) |
ce5bb5a8 | 1094 | return -ENOPARAM; |
d6e64501 | 1095 | |
39f60c1c | 1096 | return process_buffer_measurement(&nop_mnt_idmap, NULL, buf, buf_len, |
ce5bb5a8 | 1097 | event_name, CRITICAL_DATA, 0, |
ca3c9bdb RS |
1098 | event_label, hash, digest, |
1099 | digest_len); | |
d6e64501 | 1100 | } |
91ccbbac | 1101 | EXPORT_SYMBOL_GPL(ima_measure_critical_data); |
d6e64501 | 1102 | |
06cca511 RS |
1103 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS |
1104 | ||
1105 | /** | |
1106 | * ima_kernel_module_request - Prevent crypto-pkcs1pad(rsa,*) requests | |
1107 | * @kmod_name: kernel module name | |
1108 | * | |
1109 | * Avoid a verification loop where verifying the signature of the modprobe | |
1110 | * binary requires executing modprobe itself. Since the modprobe iint->mutex | |
1111 | * is already held when the signature verification is performed, a deadlock | |
1112 | * occurs as soon as modprobe is executed within the critical region, since | |
1113 | * the same lock cannot be taken again. | |
1114 | * | |
1115 | * This happens when public_key_verify_signature(), in case of RSA algorithm, | |
1116 | * use alg_name to store internal information in order to construct an | |
1117 | * algorithm on the fly, but crypto_larval_lookup() will try to use alg_name | |
1118 | * in order to load a kernel module with same name. | |
1119 | * | |
1120 | * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, | |
1121 | * we are safe to fail such module request from crypto_larval_lookup(), and | |
1122 | * avoid the verification loop. | |
1123 | * | |
1124 | * Return: Zero if it is safe to load the kernel module, -EINVAL otherwise. | |
1125 | */ | |
cd3cec0a | 1126 | static int ima_kernel_module_request(char *kmod_name) |
06cca511 RS |
1127 | { |
1128 | if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) | |
1129 | return -EINVAL; | |
1130 | ||
1131 | return 0; | |
1132 | } | |
1133 | ||
1134 | #endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ | |
1135 | ||
3323eec9 MZ |
1136 | static int __init init_ima(void) |
1137 | { | |
1138 | int error; | |
1139 | ||
b000d5cb | 1140 | ima_appraise_parse_cmdline(); |
3f23d624 | 1141 | ima_init_template_list(); |
e7a2ad7e | 1142 | hash_setup(CONFIG_IMA_DEFAULT_HASH); |
3323eec9 | 1143 | error = ima_init(); |
ab60368a PV |
1144 | |
1145 | if (error && strcmp(hash_algo_name[ima_hash_algo], | |
1146 | CONFIG_IMA_DEFAULT_HASH) != 0) { | |
1147 | pr_info("Allocating %s failed, going to use default hash algorithm %s\n", | |
1148 | hash_algo_name[ima_hash_algo], CONFIG_IMA_DEFAULT_HASH); | |
1149 | hash_setup_done = 0; | |
1150 | hash_setup(CONFIG_IMA_DEFAULT_HASH); | |
1151 | error = ima_init(); | |
1152 | } | |
1153 | ||
e144d6b2 RS |
1154 | if (error) |
1155 | return error; | |
1156 | ||
b1694245 JK |
1157 | error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier); |
1158 | if (error) | |
1159 | pr_warn("Couldn't register LSM notifier, error %d\n", error); | |
1160 | ||
4ecd9934 | 1161 | if (!error) |
4f2946aa | 1162 | ima_update_policy_flags(); |
4ecd9934 | 1163 | |
3323eec9 MZ |
1164 | return error; |
1165 | } | |
1166 | ||
cd3cec0a RS |
1167 | static struct security_hook_list ima_hooks[] __ro_after_init = { |
1168 | LSM_HOOK_INIT(bprm_check_security, ima_bprm_check), | |
1169 | LSM_HOOK_INIT(file_post_open, ima_file_check), | |
1170 | LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile), | |
1171 | LSM_HOOK_INIT(file_release, ima_file_free), | |
1172 | LSM_HOOK_INIT(mmap_file, ima_file_mmap), | |
1173 | LSM_HOOK_INIT(file_mprotect, ima_file_mprotect), | |
1174 | LSM_HOOK_INIT(kernel_load_data, ima_load_data), | |
1175 | LSM_HOOK_INIT(kernel_post_load_data, ima_post_load_data), | |
1176 | LSM_HOOK_INIT(kernel_read_file, ima_read_file), | |
1177 | LSM_HOOK_INIT(kernel_post_read_file, ima_post_read_file), | |
1178 | LSM_HOOK_INIT(path_post_mknod, ima_post_path_mknod), | |
1179 | #ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS | |
1180 | LSM_HOOK_INIT(key_post_create_or_update, ima_post_key_create_or_update), | |
1181 | #endif | |
1182 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS | |
1183 | LSM_HOOK_INIT(kernel_module_request, ima_kernel_module_request), | |
1184 | #endif | |
4de2f084 | 1185 | LSM_HOOK_INIT(inode_free_security, ima_inode_free), |
cd3cec0a RS |
1186 | }; |
1187 | ||
1188 | static const struct lsm_id ima_lsmid = { | |
1189 | .name = "ima", | |
1190 | .id = LSM_ID_IMA, | |
1191 | }; | |
1192 | ||
1193 | static int __init init_ima_lsm(void) | |
1194 | { | |
4de2f084 | 1195 | ima_iintcache_init(); |
cd3cec0a | 1196 | security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid); |
84594c9e | 1197 | init_ima_appraise_lsm(&ima_lsmid); |
cd3cec0a RS |
1198 | return 0; |
1199 | } | |
1200 | ||
4de2f084 RS |
1201 | struct lsm_blob_sizes ima_blob_sizes __ro_after_init = { |
1202 | .lbs_inode = sizeof(struct ima_iint_cache *), | |
1203 | }; | |
1204 | ||
cd3cec0a RS |
1205 | DEFINE_LSM(ima) = { |
1206 | .name = "ima", | |
1207 | .init = init_ima_lsm, | |
1208 | .order = LSM_ORDER_LAST, | |
4de2f084 | 1209 | .blobs = &ima_blob_sizes, |
cd3cec0a RS |
1210 | }; |
1211 | ||
3323eec9 | 1212 | late_initcall(init_ima); /* Start IMA after the TPM is available */ |