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