1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22fe5d6deSMimi Zohar /*
32fe5d6deSMimi Zohar * Copyright (C) 2011 IBM Corporation
42fe5d6deSMimi Zohar *
52fe5d6deSMimi Zohar * Author:
62fe5d6deSMimi Zohar * Mimi Zohar <zohar@us.ibm.com>
72fe5d6deSMimi Zohar */
8b000d5cbSArd Biesheuvel #include <linux/module.h>
9876979c9SPaul Gortmaker #include <linux/init.h>
102fe5d6deSMimi Zohar #include <linux/file.h>
112fe5d6deSMimi Zohar #include <linux/fs.h>
122fe5d6deSMimi Zohar #include <linux/xattr.h>
132fe5d6deSMimi Zohar #include <linux/magic.h>
142fe5d6deSMimi Zohar #include <linux/ima.h>
152fe5d6deSMimi Zohar #include <linux/evm.h>
16398c42e2SMimi Zohar #include <linux/fsverity.h>
17273df864SNayna Jain #include <keys/system_keyring.h>
18398c42e2SMimi Zohar #include <uapi/linux/fsverity.h>
192fe5d6deSMimi Zohar
202fe5d6deSMimi Zohar #include "ima.h"
212fe5d6deSMimi Zohar
22e1f5e01fSMimi Zohar #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
23b000d5cbSArd Biesheuvel static char *ima_appraise_cmdline_default __initdata;
24b000d5cbSArd Biesheuvel core_param(ima_appraise, ima_appraise_cmdline_default, charp, 0);
25b000d5cbSArd Biesheuvel
ima_appraise_parse_cmdline(void)26b000d5cbSArd Biesheuvel void __init ima_appraise_parse_cmdline(void)
27b000d5cbSArd Biesheuvel {
28b000d5cbSArd Biesheuvel const char *str = ima_appraise_cmdline_default;
29e4d7e2dfSBruno Meneguele bool sb_state = arch_ima_get_secureboot();
30e4d7e2dfSBruno Meneguele int appraisal_state = ima_appraise;
31311aa6aaSBruno Meneguele
32b000d5cbSArd Biesheuvel if (!str)
33b000d5cbSArd Biesheuvel return;
34b000d5cbSArd Biesheuvel
352fe5d6deSMimi Zohar if (strncmp(str, "off", 3) == 0)
36e4d7e2dfSBruno Meneguele appraisal_state = 0;
372faa6ef3SDmitry Kasatkin else if (strncmp(str, "log", 3) == 0)
38e4d7e2dfSBruno Meneguele appraisal_state = IMA_APPRAISE_LOG;
392fe5d6deSMimi Zohar else if (strncmp(str, "fix", 3) == 0)
40e4d7e2dfSBruno Meneguele appraisal_state = IMA_APPRAISE_FIX;
414afb28abSBruno Meneguele else if (strncmp(str, "enforce", 7) == 0)
42e4d7e2dfSBruno Meneguele appraisal_state = IMA_APPRAISE_ENFORCE;
437fe2bb7eSBruno Meneguele else
447fe2bb7eSBruno Meneguele pr_err("invalid \"%s\" appraise option", str);
45e4d7e2dfSBruno Meneguele
46e4d7e2dfSBruno Meneguele /* If appraisal state was changed, but secure boot is enabled,
47e4d7e2dfSBruno Meneguele * keep its default */
48e4d7e2dfSBruno Meneguele if (sb_state) {
49e4d7e2dfSBruno Meneguele if (!(appraisal_state & IMA_APPRAISE_ENFORCE))
50e4d7e2dfSBruno Meneguele pr_info("Secure boot enabled: ignoring ima_appraise=%s option",
51e4d7e2dfSBruno Meneguele str);
52e4d7e2dfSBruno Meneguele } else {
53e4d7e2dfSBruno Meneguele ima_appraise = appraisal_state;
54e4d7e2dfSBruno Meneguele }
552fe5d6deSMimi Zohar }
56b000d5cbSArd Biesheuvel #endif
572fe5d6deSMimi Zohar
582fe5d6deSMimi Zohar /*
596f6723e2SMimi Zohar * is_ima_appraise_enabled - return appraise status
606f6723e2SMimi Zohar *
616f6723e2SMimi Zohar * Only return enabled, if not in ima_appraise="fix" or "log" modes.
626f6723e2SMimi Zohar */
is_ima_appraise_enabled(void)636f6723e2SMimi Zohar bool is_ima_appraise_enabled(void)
646f6723e2SMimi Zohar {
65e5729f86SThiago Jung Bauermann return ima_appraise & IMA_APPRAISE_ENFORCE;
666f6723e2SMimi Zohar }
676f6723e2SMimi Zohar
686f6723e2SMimi Zohar /*
692fe5d6deSMimi Zohar * ima_must_appraise - set appraise flag
702fe5d6deSMimi Zohar *
71da1b0029SMimi Zohar * Return 1 to appraise or hash
722fe5d6deSMimi Zohar */
ima_must_appraise(struct mnt_idmap * idmap,struct inode * inode,int mask,enum ima_hooks func)7339f60c1cSChristian Brauner int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
74a2d2329eSChristian Brauner int mask, enum ima_hooks func)
752fe5d6deSMimi Zohar {
76d906c10dSMatthew Garrett u32 secid;
77d906c10dSMatthew Garrett
7807f6a794SMimi Zohar if (!ima_appraise)
792fe5d6deSMimi Zohar return 0;
8007f6a794SMimi Zohar
816326948fSPaul Moore security_current_getsecid_subj(&secid);
8239f60c1cSChristian Brauner return ima_match_policy(idmap, inode, current_cred(), secid,
831624dc00STHOBY Simon func, mask, IMA_APPRAISE | IMA_HASH, NULL,
841624dc00STHOBY Simon NULL, NULL, NULL);
852fe5d6deSMimi Zohar }
862fe5d6deSMimi Zohar
ima_fix_xattr(struct dentry * dentry,struct integrity_iint_cache * iint)87def3e8b9SDmitry Kasatkin static int ima_fix_xattr(struct dentry *dentry,
882fe5d6deSMimi Zohar struct integrity_iint_cache *iint)
892fe5d6deSMimi Zohar {
903ea7a560SDmitry Kasatkin int rc, offset;
913ea7a560SDmitry Kasatkin u8 algo = iint->ima_hash->algo;
923ea7a560SDmitry Kasatkin
933ea7a560SDmitry Kasatkin if (algo <= HASH_ALGO_SHA1) {
943ea7a560SDmitry Kasatkin offset = 1;
953ea7a560SDmitry Kasatkin iint->ima_hash->xattr.sha1.type = IMA_XATTR_DIGEST;
963ea7a560SDmitry Kasatkin } else {
973ea7a560SDmitry Kasatkin offset = 0;
983ea7a560SDmitry Kasatkin iint->ima_hash->xattr.ng.type = IMA_XATTR_DIGEST_NG;
993ea7a560SDmitry Kasatkin iint->ima_hash->xattr.ng.algo = algo;
1003ea7a560SDmitry Kasatkin }
10139f60c1cSChristian Brauner rc = __vfs_setxattr_noperm(&nop_mnt_idmap, dentry, XATTR_NAME_IMA,
1023ea7a560SDmitry Kasatkin &iint->ima_hash->xattr.data[offset],
1033ea7a560SDmitry Kasatkin (sizeof(iint->ima_hash->xattr) - offset) +
1043ea7a560SDmitry Kasatkin iint->ima_hash->length, 0);
1053ea7a560SDmitry Kasatkin return rc;
1062fe5d6deSMimi Zohar }
1072fe5d6deSMimi Zohar
108d79d72e0SMimi Zohar /* Return specific func appraised cached result */
ima_get_cache_status(struct integrity_iint_cache * iint,enum ima_hooks func)109d79d72e0SMimi Zohar enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
1104ad87a3dSMimi Zohar enum ima_hooks func)
111d79d72e0SMimi Zohar {
112d79d72e0SMimi Zohar switch (func) {
113d79d72e0SMimi Zohar case MMAP_CHECK:
1144958db32SRoberto Sassu case MMAP_CHECK_REQPROT:
115d79d72e0SMimi Zohar return iint->ima_mmap_status;
116d79d72e0SMimi Zohar case BPRM_CHECK:
117d79d72e0SMimi Zohar return iint->ima_bprm_status;
118d906c10dSMatthew Garrett case CREDS_CHECK:
119d906c10dSMatthew Garrett return iint->ima_creds_status;
120d79d72e0SMimi Zohar case FILE_CHECK:
121c6af8efeSMimi Zohar case POST_SETATTR:
122d79d72e0SMimi Zohar return iint->ima_file_status;
123c6af8efeSMimi Zohar case MODULE_CHECK ... MAX_CHECK - 1:
124c6af8efeSMimi Zohar default:
125c6af8efeSMimi Zohar return iint->ima_read_status;
126d79d72e0SMimi Zohar }
127d79d72e0SMimi Zohar }
128d79d72e0SMimi Zohar
ima_set_cache_status(struct integrity_iint_cache * iint,enum ima_hooks func,enum integrity_status status)129d79d72e0SMimi Zohar static void ima_set_cache_status(struct integrity_iint_cache *iint,
1304ad87a3dSMimi Zohar enum ima_hooks func,
1314ad87a3dSMimi Zohar enum integrity_status status)
132d79d72e0SMimi Zohar {
133d79d72e0SMimi Zohar switch (func) {
134d79d72e0SMimi Zohar case MMAP_CHECK:
1354958db32SRoberto Sassu case MMAP_CHECK_REQPROT:
136d79d72e0SMimi Zohar iint->ima_mmap_status = status;
137d79d72e0SMimi Zohar break;
138d79d72e0SMimi Zohar case BPRM_CHECK:
139d79d72e0SMimi Zohar iint->ima_bprm_status = status;
140d79d72e0SMimi Zohar break;
141d906c10dSMatthew Garrett case CREDS_CHECK:
142d906c10dSMatthew Garrett iint->ima_creds_status = status;
14309186e50SGustavo A. R. Silva break;
144d79d72e0SMimi Zohar case FILE_CHECK:
145c6af8efeSMimi Zohar case POST_SETATTR:
146d79d72e0SMimi Zohar iint->ima_file_status = status;
147c6af8efeSMimi Zohar break;
148c6af8efeSMimi Zohar case MODULE_CHECK ... MAX_CHECK - 1:
149c6af8efeSMimi Zohar default:
150c6af8efeSMimi Zohar iint->ima_read_status = status;
151c6af8efeSMimi Zohar break;
152d79d72e0SMimi Zohar }
153d79d72e0SMimi Zohar }
154d79d72e0SMimi Zohar
ima_cache_flags(struct integrity_iint_cache * iint,enum ima_hooks func)1554ad87a3dSMimi Zohar static void ima_cache_flags(struct integrity_iint_cache *iint,
1564ad87a3dSMimi Zohar enum ima_hooks func)
157d79d72e0SMimi Zohar {
158d79d72e0SMimi Zohar switch (func) {
159d79d72e0SMimi Zohar case MMAP_CHECK:
1604958db32SRoberto Sassu case MMAP_CHECK_REQPROT:
161d79d72e0SMimi Zohar iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED);
162d79d72e0SMimi Zohar break;
163d79d72e0SMimi Zohar case BPRM_CHECK:
164d79d72e0SMimi Zohar iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED);
165d79d72e0SMimi Zohar break;
166d906c10dSMatthew Garrett case CREDS_CHECK:
167d906c10dSMatthew Garrett iint->flags |= (IMA_CREDS_APPRAISED | IMA_APPRAISED);
168d906c10dSMatthew Garrett break;
169d79d72e0SMimi Zohar case FILE_CHECK:
170c6af8efeSMimi Zohar case POST_SETATTR:
171d79d72e0SMimi Zohar iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED);
172c6af8efeSMimi Zohar break;
173c6af8efeSMimi Zohar case MODULE_CHECK ... MAX_CHECK - 1:
174c6af8efeSMimi Zohar default:
175c6af8efeSMimi Zohar iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED);
176c6af8efeSMimi Zohar break;
177d79d72e0SMimi Zohar }
178d79d72e0SMimi Zohar }
179d79d72e0SMimi Zohar
ima_get_hash_algo(const struct evm_ima_xattr_data * xattr_value,int xattr_len)18050f742ddSTHOBY Simon enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
1811525b06dSDmitry Kasatkin int xattr_len)
182d3634d0fSDmitry Kasatkin {
183d3634d0fSDmitry Kasatkin struct signature_v2_hdr *sig;
184b4bfec7fSSeth Forshee enum hash_algo ret;
185d3634d0fSDmitry Kasatkin
1863ea7a560SDmitry Kasatkin if (!xattr_value || xattr_len < 2)
1871525b06dSDmitry Kasatkin /* return default hash algo */
1881525b06dSDmitry Kasatkin return ima_hash_algo;
189d3634d0fSDmitry Kasatkin
1903ea7a560SDmitry Kasatkin switch (xattr_value->type) {
191398c42e2SMimi Zohar case IMA_VERITY_DIGSIG:
192398c42e2SMimi Zohar sig = (typeof(sig))xattr_value;
193398c42e2SMimi Zohar if (sig->version != 3 || xattr_len <= sizeof(*sig) ||
194398c42e2SMimi Zohar sig->hash_algo >= HASH_ALGO__LAST)
195398c42e2SMimi Zohar return ima_hash_algo;
196398c42e2SMimi Zohar return sig->hash_algo;
1973ea7a560SDmitry Kasatkin case EVM_IMA_XATTR_DIGSIG:
1983ea7a560SDmitry Kasatkin sig = (typeof(sig))xattr_value;
199cb181da1STHOBY Simon if (sig->version != 2 || xattr_len <= sizeof(*sig)
200cb181da1STHOBY Simon || sig->hash_algo >= HASH_ALGO__LAST)
2011525b06dSDmitry Kasatkin return ima_hash_algo;
2021525b06dSDmitry Kasatkin return sig->hash_algo;
2033ea7a560SDmitry Kasatkin case IMA_XATTR_DIGEST_NG:
204650b29dbSThiago Jung Bauermann /* first byte contains algorithm id */
205650b29dbSThiago Jung Bauermann ret = xattr_value->data[0];
206b4bfec7fSSeth Forshee if (ret < HASH_ALGO__LAST)
207b4bfec7fSSeth Forshee return ret;
2083ea7a560SDmitry Kasatkin break;
2093ea7a560SDmitry Kasatkin case IMA_XATTR_DIGEST:
2103ea7a560SDmitry Kasatkin /* this is for backward compatibility */
2113ea7a560SDmitry Kasatkin if (xattr_len == 21) {
2123ea7a560SDmitry Kasatkin unsigned int zero = 0;
213650b29dbSThiago Jung Bauermann if (!memcmp(&xattr_value->data[16], &zero, 4))
2141525b06dSDmitry Kasatkin return HASH_ALGO_MD5;
2153ea7a560SDmitry Kasatkin else
2161525b06dSDmitry Kasatkin return HASH_ALGO_SHA1;
2173ea7a560SDmitry Kasatkin } else if (xattr_len == 17)
2181525b06dSDmitry Kasatkin return HASH_ALGO_MD5;
2193ea7a560SDmitry Kasatkin break;
2203ea7a560SDmitry Kasatkin }
2211525b06dSDmitry Kasatkin
2221525b06dSDmitry Kasatkin /* return default hash algo */
2231525b06dSDmitry Kasatkin return ima_hash_algo;
224d3634d0fSDmitry Kasatkin }
225d3634d0fSDmitry Kasatkin
ima_read_xattr(struct dentry * dentry,struct evm_ima_xattr_data ** xattr_value,int xattr_len)226d3634d0fSDmitry Kasatkin int ima_read_xattr(struct dentry *dentry,
227f6fbd8cbSPaul Moore struct evm_ima_xattr_data **xattr_value, int xattr_len)
228d3634d0fSDmitry Kasatkin {
229f6fbd8cbSPaul Moore int ret;
230d3634d0fSDmitry Kasatkin
2314609e1f1SChristian Brauner ret = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, XATTR_NAME_IMA,
232f6fbd8cbSPaul Moore (char **)xattr_value, xattr_len, GFP_NOFS);
2335d6c3191SAndreas Gruenbacher if (ret == -EOPNOTSUPP)
2345d6c3191SAndreas Gruenbacher ret = 0;
2355d6c3191SAndreas Gruenbacher return ret;
236d3634d0fSDmitry Kasatkin }
237d3634d0fSDmitry Kasatkin
2382fe5d6deSMimi Zohar /*
239398c42e2SMimi Zohar * calc_file_id_hash - calculate the hash of the ima_file_id struct data
240398c42e2SMimi Zohar * @type: xattr type [enum evm_ima_xattr_type]
241398c42e2SMimi Zohar * @algo: hash algorithm [enum hash_algo]
242398c42e2SMimi Zohar * @digest: pointer to the digest to be hashed
243398c42e2SMimi Zohar * @hash: (out) pointer to the hash
244398c42e2SMimi Zohar *
245398c42e2SMimi Zohar * IMA signature version 3 disambiguates the data that is signed by
246398c42e2SMimi Zohar * indirectly signing the hash of the ima_file_id structure data.
247398c42e2SMimi Zohar *
248398c42e2SMimi Zohar * Signing the ima_file_id struct is currently only supported for
249398c42e2SMimi Zohar * IMA_VERITY_DIGSIG type xattrs.
250398c42e2SMimi Zohar *
251398c42e2SMimi Zohar * Return 0 on success, error code otherwise.
252398c42e2SMimi Zohar */
calc_file_id_hash(enum evm_ima_xattr_type type,enum hash_algo algo,const u8 * digest,struct ima_digest_data * hash)253398c42e2SMimi Zohar static int calc_file_id_hash(enum evm_ima_xattr_type type,
254398c42e2SMimi Zohar enum hash_algo algo, const u8 *digest,
255398c42e2SMimi Zohar struct ima_digest_data *hash)
256398c42e2SMimi Zohar {
257398c42e2SMimi Zohar struct ima_file_id file_id = {
258398c42e2SMimi Zohar .hash_type = IMA_VERITY_DIGSIG, .hash_algorithm = algo};
259398c42e2SMimi Zohar unsigned int unused = HASH_MAX_DIGESTSIZE - hash_digest_size[algo];
260398c42e2SMimi Zohar
261398c42e2SMimi Zohar if (type != IMA_VERITY_DIGSIG)
262398c42e2SMimi Zohar return -EINVAL;
263398c42e2SMimi Zohar
264398c42e2SMimi Zohar memcpy(file_id.hash, digest, hash_digest_size[algo]);
265398c42e2SMimi Zohar
266398c42e2SMimi Zohar hash->algo = algo;
267398c42e2SMimi Zohar hash->length = hash_digest_size[algo];
268398c42e2SMimi Zohar
269398c42e2SMimi Zohar return ima_calc_buffer_hash(&file_id, sizeof(file_id) - unused, hash);
270398c42e2SMimi Zohar }
271398c42e2SMimi Zohar
272398c42e2SMimi Zohar /*
273a5fbeb61SThiago Jung Bauermann * xattr_verify - verify xattr digest or signature
274a5fbeb61SThiago Jung Bauermann *
275a5fbeb61SThiago Jung Bauermann * Verify whether the hash or signature matches the file contents.
276a5fbeb61SThiago Jung Bauermann *
277a5fbeb61SThiago Jung Bauermann * Return 0 on success, error code otherwise.
278a5fbeb61SThiago Jung Bauermann */
xattr_verify(enum ima_hooks func,struct integrity_iint_cache * iint,struct evm_ima_xattr_data * xattr_value,int xattr_len,enum integrity_status * status,const char ** cause)279a5fbeb61SThiago Jung Bauermann static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
280a5fbeb61SThiago Jung Bauermann struct evm_ima_xattr_data *xattr_value, int xattr_len,
281a5fbeb61SThiago Jung Bauermann enum integrity_status *status, const char **cause)
282a5fbeb61SThiago Jung Bauermann {
283398c42e2SMimi Zohar struct ima_max_digest_data hash;
284398c42e2SMimi Zohar struct signature_v2_hdr *sig;
285a5fbeb61SThiago Jung Bauermann int rc = -EINVAL, hash_start = 0;
286398c42e2SMimi Zohar int mask;
287a5fbeb61SThiago Jung Bauermann
288a5fbeb61SThiago Jung Bauermann switch (xattr_value->type) {
289a5fbeb61SThiago Jung Bauermann case IMA_XATTR_DIGEST_NG:
290a5fbeb61SThiago Jung Bauermann /* first byte contains algorithm id */
291a5fbeb61SThiago Jung Bauermann hash_start = 1;
292df561f66SGustavo A. R. Silva fallthrough;
293a5fbeb61SThiago Jung Bauermann case IMA_XATTR_DIGEST:
2947aa5783dSRoberto Sassu if (*status != INTEGRITY_PASS_IMMUTABLE) {
295a5fbeb61SThiago Jung Bauermann if (iint->flags & IMA_DIGSIG_REQUIRED) {
296398c42e2SMimi Zohar if (iint->flags & IMA_VERITY_REQUIRED)
297398c42e2SMimi Zohar *cause = "verity-signature-required";
298398c42e2SMimi Zohar else
299a5fbeb61SThiago Jung Bauermann *cause = "IMA-signature-required";
300a5fbeb61SThiago Jung Bauermann *status = INTEGRITY_FAIL;
301a5fbeb61SThiago Jung Bauermann break;
302a5fbeb61SThiago Jung Bauermann }
303a5fbeb61SThiago Jung Bauermann clear_bit(IMA_DIGSIG, &iint->atomic_flags);
3047aa5783dSRoberto Sassu } else {
3057aa5783dSRoberto Sassu set_bit(IMA_DIGSIG, &iint->atomic_flags);
3067aa5783dSRoberto Sassu }
307a5fbeb61SThiago Jung Bauermann if (xattr_len - sizeof(xattr_value->type) - hash_start >=
308a5fbeb61SThiago Jung Bauermann iint->ima_hash->length)
309a5fbeb61SThiago Jung Bauermann /*
310a5fbeb61SThiago Jung Bauermann * xattr length may be longer. md5 hash in previous
311a5fbeb61SThiago Jung Bauermann * version occupied 20 bytes in xattr, instead of 16
312a5fbeb61SThiago Jung Bauermann */
313a5fbeb61SThiago Jung Bauermann rc = memcmp(&xattr_value->data[hash_start],
314a5fbeb61SThiago Jung Bauermann iint->ima_hash->digest,
315a5fbeb61SThiago Jung Bauermann iint->ima_hash->length);
316a5fbeb61SThiago Jung Bauermann else
317a5fbeb61SThiago Jung Bauermann rc = -EINVAL;
318a5fbeb61SThiago Jung Bauermann if (rc) {
319a5fbeb61SThiago Jung Bauermann *cause = "invalid-hash";
320a5fbeb61SThiago Jung Bauermann *status = INTEGRITY_FAIL;
321a5fbeb61SThiago Jung Bauermann break;
322a5fbeb61SThiago Jung Bauermann }
323a5fbeb61SThiago Jung Bauermann *status = INTEGRITY_PASS;
324a5fbeb61SThiago Jung Bauermann break;
325a5fbeb61SThiago Jung Bauermann case EVM_IMA_XATTR_DIGSIG:
326a5fbeb61SThiago Jung Bauermann set_bit(IMA_DIGSIG, &iint->atomic_flags);
327398c42e2SMimi Zohar
328398c42e2SMimi Zohar mask = IMA_DIGSIG_REQUIRED | IMA_VERITY_REQUIRED;
329398c42e2SMimi Zohar if ((iint->flags & mask) == mask) {
330398c42e2SMimi Zohar *cause = "verity-signature-required";
331398c42e2SMimi Zohar *status = INTEGRITY_FAIL;
332398c42e2SMimi Zohar break;
333398c42e2SMimi Zohar }
334398c42e2SMimi Zohar
335398c42e2SMimi Zohar sig = (typeof(sig))xattr_value;
336398c42e2SMimi Zohar if (sig->version >= 3) {
337398c42e2SMimi Zohar *cause = "invalid-signature-version";
338398c42e2SMimi Zohar *status = INTEGRITY_FAIL;
339398c42e2SMimi Zohar break;
340398c42e2SMimi Zohar }
341a5fbeb61SThiago Jung Bauermann rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
342a5fbeb61SThiago Jung Bauermann (const char *)xattr_value,
343a5fbeb61SThiago Jung Bauermann xattr_len,
344a5fbeb61SThiago Jung Bauermann iint->ima_hash->digest,
345a5fbeb61SThiago Jung Bauermann iint->ima_hash->length);
346a5fbeb61SThiago Jung Bauermann if (rc == -EOPNOTSUPP) {
347a5fbeb61SThiago Jung Bauermann *status = INTEGRITY_UNKNOWN;
348a5fbeb61SThiago Jung Bauermann break;
349a5fbeb61SThiago Jung Bauermann }
350a5fbeb61SThiago Jung Bauermann if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
351a5fbeb61SThiago Jung Bauermann func == KEXEC_KERNEL_CHECK)
352a5fbeb61SThiago Jung Bauermann rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
353a5fbeb61SThiago Jung Bauermann (const char *)xattr_value,
354a5fbeb61SThiago Jung Bauermann xattr_len,
355a5fbeb61SThiago Jung Bauermann iint->ima_hash->digest,
356a5fbeb61SThiago Jung Bauermann iint->ima_hash->length);
357a5fbeb61SThiago Jung Bauermann if (rc) {
358a5fbeb61SThiago Jung Bauermann *cause = "invalid-signature";
359a5fbeb61SThiago Jung Bauermann *status = INTEGRITY_FAIL;
360a5fbeb61SThiago Jung Bauermann } else {
361a5fbeb61SThiago Jung Bauermann *status = INTEGRITY_PASS;
362a5fbeb61SThiago Jung Bauermann }
363a5fbeb61SThiago Jung Bauermann break;
364398c42e2SMimi Zohar case IMA_VERITY_DIGSIG:
365398c42e2SMimi Zohar set_bit(IMA_DIGSIG, &iint->atomic_flags);
366398c42e2SMimi Zohar
367398c42e2SMimi Zohar if (iint->flags & IMA_DIGSIG_REQUIRED) {
368398c42e2SMimi Zohar if (!(iint->flags & IMA_VERITY_REQUIRED)) {
369398c42e2SMimi Zohar *cause = "IMA-signature-required";
370398c42e2SMimi Zohar *status = INTEGRITY_FAIL;
371398c42e2SMimi Zohar break;
372398c42e2SMimi Zohar }
373398c42e2SMimi Zohar }
374398c42e2SMimi Zohar
375398c42e2SMimi Zohar sig = (typeof(sig))xattr_value;
376398c42e2SMimi Zohar if (sig->version != 3) {
377398c42e2SMimi Zohar *cause = "invalid-signature-version";
378398c42e2SMimi Zohar *status = INTEGRITY_FAIL;
379398c42e2SMimi Zohar break;
380398c42e2SMimi Zohar }
381398c42e2SMimi Zohar
382398c42e2SMimi Zohar rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo,
383398c42e2SMimi Zohar iint->ima_hash->digest, &hash.hdr);
384398c42e2SMimi Zohar if (rc) {
385398c42e2SMimi Zohar *cause = "sigv3-hashing-error";
386398c42e2SMimi Zohar *status = INTEGRITY_FAIL;
387398c42e2SMimi Zohar break;
388398c42e2SMimi Zohar }
389398c42e2SMimi Zohar
390398c42e2SMimi Zohar rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
391398c42e2SMimi Zohar (const char *)xattr_value,
392398c42e2SMimi Zohar xattr_len, hash.digest,
393398c42e2SMimi Zohar hash.hdr.length);
394398c42e2SMimi Zohar if (rc) {
395398c42e2SMimi Zohar *cause = "invalid-verity-signature";
396398c42e2SMimi Zohar *status = INTEGRITY_FAIL;
397398c42e2SMimi Zohar } else {
398398c42e2SMimi Zohar *status = INTEGRITY_PASS;
399398c42e2SMimi Zohar }
400398c42e2SMimi Zohar
401398c42e2SMimi Zohar break;
402a5fbeb61SThiago Jung Bauermann default:
403a5fbeb61SThiago Jung Bauermann *status = INTEGRITY_UNKNOWN;
404a5fbeb61SThiago Jung Bauermann *cause = "unknown-ima-data";
405a5fbeb61SThiago Jung Bauermann break;
406a5fbeb61SThiago Jung Bauermann }
407a5fbeb61SThiago Jung Bauermann
408a5fbeb61SThiago Jung Bauermann return rc;
409a5fbeb61SThiago Jung Bauermann }
410a5fbeb61SThiago Jung Bauermann
411a5fbeb61SThiago Jung Bauermann /*
41239b07096SThiago Jung Bauermann * modsig_verify - verify modsig signature
41339b07096SThiago Jung Bauermann *
41439b07096SThiago Jung Bauermann * Verify whether the signature matches the file contents.
41539b07096SThiago Jung Bauermann *
41639b07096SThiago Jung Bauermann * Return 0 on success, error code otherwise.
41739b07096SThiago Jung Bauermann */
modsig_verify(enum ima_hooks func,const struct modsig * modsig,enum integrity_status * status,const char ** cause)41839b07096SThiago Jung Bauermann static int modsig_verify(enum ima_hooks func, const struct modsig *modsig,
41939b07096SThiago Jung Bauermann enum integrity_status *status, const char **cause)
42039b07096SThiago Jung Bauermann {
42139b07096SThiago Jung Bauermann int rc;
42239b07096SThiago Jung Bauermann
42339b07096SThiago Jung Bauermann rc = integrity_modsig_verify(INTEGRITY_KEYRING_IMA, modsig);
42439b07096SThiago Jung Bauermann if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
42539b07096SThiago Jung Bauermann func == KEXEC_KERNEL_CHECK)
42639b07096SThiago Jung Bauermann rc = integrity_modsig_verify(INTEGRITY_KEYRING_PLATFORM,
42739b07096SThiago Jung Bauermann modsig);
42839b07096SThiago Jung Bauermann if (rc) {
42939b07096SThiago Jung Bauermann *cause = "invalid-signature";
43039b07096SThiago Jung Bauermann *status = INTEGRITY_FAIL;
43139b07096SThiago Jung Bauermann } else {
43239b07096SThiago Jung Bauermann *status = INTEGRITY_PASS;
43339b07096SThiago Jung Bauermann }
43439b07096SThiago Jung Bauermann
43539b07096SThiago Jung Bauermann return rc;
43639b07096SThiago Jung Bauermann }
43739b07096SThiago Jung Bauermann
43839b07096SThiago Jung Bauermann /*
439273df864SNayna Jain * ima_check_blacklist - determine if the binary is blacklisted.
440273df864SNayna Jain *
441273df864SNayna Jain * Add the hash of the blacklisted binary to the measurement list, based
442273df864SNayna Jain * on policy.
443273df864SNayna Jain *
444273df864SNayna Jain * Returns -EPERM if the hash is blacklisted.
445273df864SNayna Jain */
ima_check_blacklist(struct integrity_iint_cache * iint,const struct modsig * modsig,int pcr)446273df864SNayna Jain int ima_check_blacklist(struct integrity_iint_cache *iint,
447273df864SNayna Jain const struct modsig *modsig, int pcr)
448273df864SNayna Jain {
449273df864SNayna Jain enum hash_algo hash_algo;
450273df864SNayna Jain const u8 *digest = NULL;
451273df864SNayna Jain u32 digestsize = 0;
452273df864SNayna Jain int rc = 0;
453273df864SNayna Jain
454273df864SNayna Jain if (!(iint->flags & IMA_CHECK_BLACKLIST))
455273df864SNayna Jain return 0;
456273df864SNayna Jain
457273df864SNayna Jain if (iint->flags & IMA_MODSIG_ALLOWED && modsig) {
458273df864SNayna Jain ima_get_modsig_digest(modsig, &hash_algo, &digest, &digestsize);
459273df864SNayna Jain
460273df864SNayna Jain rc = is_binary_blacklisted(digest, digestsize);
461*f20765fdSEric Snowberg } else if (iint->flags & IMA_DIGSIG_REQUIRED && iint->ima_hash)
462*f20765fdSEric Snowberg rc = is_binary_blacklisted(iint->ima_hash->digest, iint->ima_hash->length);
463*f20765fdSEric Snowberg
464273df864SNayna Jain if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
46539f60c1cSChristian Brauner process_buffer_measurement(&nop_mnt_idmap, NULL, digest, digestsize,
466273df864SNayna Jain "blacklisted-hash", NONE,
467ca3c9bdbSRoberto Sassu pcr, NULL, false, NULL, 0);
468273df864SNayna Jain
469273df864SNayna Jain return rc;
470273df864SNayna Jain }
471273df864SNayna Jain
472273df864SNayna Jain /*
4732fe5d6deSMimi Zohar * ima_appraise_measurement - appraise file measurement
4742fe5d6deSMimi Zohar *
4752fe5d6deSMimi Zohar * Call evm_verifyxattr() to verify the integrity of 'security.ima'.
4762fe5d6deSMimi Zohar * Assuming success, compare the xattr hash with the collected measurement.
4772fe5d6deSMimi Zohar *
4782fe5d6deSMimi Zohar * Return 0 on success, error code otherwise
4792fe5d6deSMimi Zohar */
ima_appraise_measurement(enum ima_hooks func,struct integrity_iint_cache * iint,struct file * file,const unsigned char * filename,struct evm_ima_xattr_data * xattr_value,int xattr_len,const struct modsig * modsig)4804ad87a3dSMimi Zohar int ima_appraise_measurement(enum ima_hooks func,
4814ad87a3dSMimi Zohar struct integrity_iint_cache *iint,
482d3634d0fSDmitry Kasatkin struct file *file, const unsigned char *filename,
483d3634d0fSDmitry Kasatkin struct evm_ima_xattr_data *xattr_value,
48439b07096SThiago Jung Bauermann int xattr_len, const struct modsig *modsig)
4852fe5d6deSMimi Zohar {
48652a13284SMimi Zohar static const char op[] = "appraise_data";
487f5e51fa3SThiago Jung Bauermann const char *cause = "unknown";
488e71b9dffSMiklos Szeredi struct dentry *dentry = file_dentry(file);
489c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry);
4902fe5d6deSMimi Zohar enum integrity_status status = INTEGRITY_UNKNOWN;
491a5fbeb61SThiago Jung Bauermann int rc = xattr_len;
49239b07096SThiago Jung Bauermann bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig;
4932fe5d6deSMimi Zohar
49439b07096SThiago Jung Bauermann /* If not appraising a modsig, we need an xattr. */
49539b07096SThiago Jung Bauermann if (!(inode->i_opflags & IOP_XATTR) && !try_modsig)
4962fe5d6deSMimi Zohar return INTEGRITY_UNKNOWN;
4972fe5d6deSMimi Zohar
49839b07096SThiago Jung Bauermann /* If reading the xattr failed and there's no modsig, error out. */
49939b07096SThiago Jung Bauermann if (rc <= 0 && !try_modsig) {
5002fe5d6deSMimi Zohar if (rc && rc != -ENODATA)
5012fe5d6deSMimi Zohar goto out;
5022fe5d6deSMimi Zohar
503398c42e2SMimi Zohar if (iint->flags & IMA_DIGSIG_REQUIRED) {
504398c42e2SMimi Zohar if (iint->flags & IMA_VERITY_REQUIRED)
505398c42e2SMimi Zohar cause = "verity-signature-required";
506398c42e2SMimi Zohar else
507398c42e2SMimi Zohar cause = "IMA-signature-required";
508398c42e2SMimi Zohar } else {
509398c42e2SMimi Zohar cause = "missing-hash";
510398c42e2SMimi Zohar }
511398c42e2SMimi Zohar
512b151d6b0SDmitry Kasatkin status = INTEGRITY_NOLABEL;
5136035a27bSAl Viro if (file->f_mode & FMODE_CREATED)
514b151d6b0SDmitry Kasatkin iint->flags |= IMA_NEW_FILE;
5151ac202e9SDaniel Glöckner if ((iint->flags & IMA_NEW_FILE) &&
516b7e27bc1SMimi Zohar (!(iint->flags & IMA_DIGSIG_REQUIRED) ||
517b7e27bc1SMimi Zohar (inode->i_size == 0)))
518b151d6b0SDmitry Kasatkin status = INTEGRITY_PASS;
5192fe5d6deSMimi Zohar goto out;
5202fe5d6deSMimi Zohar }
5212fe5d6deSMimi Zohar
522d2ee2cfcSHuaxin Lu status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value,
523d2ee2cfcSHuaxin Lu rc < 0 ? 0 : rc, iint);
524f5e51fa3SThiago Jung Bauermann switch (status) {
525f5e51fa3SThiago Jung Bauermann case INTEGRITY_PASS:
526f5e51fa3SThiago Jung Bauermann case INTEGRITY_PASS_IMMUTABLE:
527f5e51fa3SThiago Jung Bauermann case INTEGRITY_UNKNOWN:
528f5e51fa3SThiago Jung Bauermann break;
529f5e51fa3SThiago Jung Bauermann case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */
53039b07096SThiago Jung Bauermann /* It's fine not to have xattrs when using a modsig. */
53139b07096SThiago Jung Bauermann if (try_modsig)
53239b07096SThiago Jung Bauermann break;
533df561f66SGustavo A. R. Silva fallthrough;
534f5e51fa3SThiago Jung Bauermann case INTEGRITY_NOLABEL: /* No security.evm xattr. */
5352fe5d6deSMimi Zohar cause = "missing-HMAC";
536f5e51fa3SThiago Jung Bauermann goto out;
537cdef685bSRoberto Sassu case INTEGRITY_FAIL_IMMUTABLE:
5387aa5783dSRoberto Sassu set_bit(IMA_DIGSIG, &iint->atomic_flags);
53955748ac6SMimi Zohar cause = "invalid-fail-immutable";
54055748ac6SMimi Zohar goto out;
541f5e51fa3SThiago Jung Bauermann case INTEGRITY_FAIL: /* Invalid HMAC/signature. */
5422fe5d6deSMimi Zohar cause = "invalid-HMAC";
5432fe5d6deSMimi Zohar goto out;
544f5e51fa3SThiago Jung Bauermann default:
545f5e51fa3SThiago Jung Bauermann WARN_ONCE(true, "Unexpected integrity status %d\n", status);
5462fe5d6deSMimi Zohar }
547f5e51fa3SThiago Jung Bauermann
548a5fbeb61SThiago Jung Bauermann if (xattr_value)
549a5fbeb61SThiago Jung Bauermann rc = xattr_verify(func, iint, xattr_value, xattr_len, &status,
550a5fbeb61SThiago Jung Bauermann &cause);
5518606404fSDmitry Kasatkin
55239b07096SThiago Jung Bauermann /*
55339b07096SThiago Jung Bauermann * If we have a modsig and either no imasig or the imasig's key isn't
55439b07096SThiago Jung Bauermann * known, then try verifying the modsig.
55539b07096SThiago Jung Bauermann */
55639b07096SThiago Jung Bauermann if (try_modsig &&
55739b07096SThiago Jung Bauermann (!xattr_value || xattr_value->type == IMA_XATTR_DIGEST_NG ||
55839b07096SThiago Jung Bauermann rc == -ENOKEY))
55939b07096SThiago Jung Bauermann rc = modsig_verify(func, modsig, &status, &cause);
56039b07096SThiago Jung Bauermann
5612fe5d6deSMimi Zohar out:
56257b56ac6SMimi Zohar /*
56357b56ac6SMimi Zohar * File signatures on some filesystems can not be properly verified.
5649e67028eSMimi Zohar * When such filesystems are mounted by an untrusted mounter or on a
5659e67028eSMimi Zohar * system not willing to accept such a risk, fail the file signature
5669e67028eSMimi Zohar * verification.
56757b56ac6SMimi Zohar */
5689e67028eSMimi Zohar if ((inode->i_sb->s_iflags & SB_I_IMA_UNVERIFIABLE_SIGNATURE) &&
5699e67028eSMimi Zohar ((inode->i_sb->s_iflags & SB_I_UNTRUSTED_MOUNTER) ||
5709e67028eSMimi Zohar (iint->flags & IMA_FAIL_UNVERIFIABLE_SIGS))) {
57157b56ac6SMimi Zohar status = INTEGRITY_FAIL;
57257b56ac6SMimi Zohar cause = "unverifiable-signature";
57357b56ac6SMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
57457b56ac6SMimi Zohar op, cause, rc, 0);
57557b56ac6SMimi Zohar } else if (status != INTEGRITY_PASS) {
576f5e51fa3SThiago Jung Bauermann /* Fix mode, but don't replace file signatures. */
57739b07096SThiago Jung Bauermann if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig &&
5788606404fSDmitry Kasatkin (!xattr_value ||
5798606404fSDmitry Kasatkin xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
580def3e8b9SDmitry Kasatkin if (!ima_fix_xattr(dentry, iint))
5812fe5d6deSMimi Zohar status = INTEGRITY_PASS;
582f5e51fa3SThiago Jung Bauermann }
583f5e51fa3SThiago Jung Bauermann
5847aa5783dSRoberto Sassu /*
5857aa5783dSRoberto Sassu * Permit new files with file/EVM portable signatures, but
5867aa5783dSRoberto Sassu * without data.
5877aa5783dSRoberto Sassu */
588f5e51fa3SThiago Jung Bauermann if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&
5897aa5783dSRoberto Sassu test_bit(IMA_DIGSIG, &iint->atomic_flags)) {
59005d1a717SMimi Zohar status = INTEGRITY_PASS;
5912fe5d6deSMimi Zohar }
592f5e51fa3SThiago Jung Bauermann
5932fe5d6deSMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
5942fe5d6deSMimi Zohar op, cause, rc, 0);
5958606404fSDmitry Kasatkin } else {
596d79d72e0SMimi Zohar ima_cache_flags(iint, func);
5972fe5d6deSMimi Zohar }
59857b56ac6SMimi Zohar
599d79d72e0SMimi Zohar ima_set_cache_status(iint, func, status);
6002fe5d6deSMimi Zohar return status;
6012fe5d6deSMimi Zohar }
6022fe5d6deSMimi Zohar
6032fe5d6deSMimi Zohar /*
6042fe5d6deSMimi Zohar * ima_update_xattr - update 'security.ima' hash value
6052fe5d6deSMimi Zohar */
ima_update_xattr(struct integrity_iint_cache * iint,struct file * file)6062fe5d6deSMimi Zohar void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
6072fe5d6deSMimi Zohar {
608e71b9dffSMiklos Szeredi struct dentry *dentry = file_dentry(file);
6092fe5d6deSMimi Zohar int rc = 0;
6102fe5d6deSMimi Zohar
6118606404fSDmitry Kasatkin /* do not collect and update hash for digital signatures */
6120d73a552SDmitry Kasatkin if (test_bit(IMA_DIGSIG, &iint->atomic_flags))
6138606404fSDmitry Kasatkin return;
6148606404fSDmitry Kasatkin
615da1b0029SMimi Zohar if ((iint->ima_file_status != INTEGRITY_PASS) &&
616da1b0029SMimi Zohar !(iint->flags & IMA_HASH))
617020aae3eSRoberto Sassu return;
618020aae3eSRoberto Sassu
61915588227SThiago Jung Bauermann rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo, NULL);
6202fe5d6deSMimi Zohar if (rc < 0)
6212fe5d6deSMimi Zohar return;
6228606404fSDmitry Kasatkin
6230d73a552SDmitry Kasatkin inode_lock(file_inode(file));
6242fe5d6deSMimi Zohar ima_fix_xattr(dentry, iint);
6250d73a552SDmitry Kasatkin inode_unlock(file_inode(file));
6262fe5d6deSMimi Zohar }
6272fe5d6deSMimi Zohar
6282fe5d6deSMimi Zohar /**
6292fe5d6deSMimi Zohar * ima_inode_post_setattr - reflect file metadata changes
63039f60c1cSChristian Brauner * @idmap: idmap of the mount the inode was found from
6312fe5d6deSMimi Zohar * @dentry: pointer to the affected dentry
6322fe5d6deSMimi Zohar *
6332fe5d6deSMimi Zohar * Changes to a dentry's metadata might result in needing to appraise.
6342fe5d6deSMimi Zohar *
6352fe5d6deSMimi Zohar * This function is called from notify_change(), which expects the caller
6362fe5d6deSMimi Zohar * to lock the inode's i_mutex.
6372fe5d6deSMimi Zohar */
ima_inode_post_setattr(struct mnt_idmap * idmap,struct dentry * dentry)63839f60c1cSChristian Brauner void ima_inode_post_setattr(struct mnt_idmap *idmap,
639a2d2329eSChristian Brauner struct dentry *dentry)
6402fe5d6deSMimi Zohar {
641c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry);
6422fe5d6deSMimi Zohar struct integrity_iint_cache *iint;
643da1b0029SMimi Zohar int action;
6442fe5d6deSMimi Zohar
645a756024eSRoberto Sassu if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
6465d6c3191SAndreas Gruenbacher || !(inode->i_opflags & IOP_XATTR))
6472fe5d6deSMimi Zohar return;
6482fe5d6deSMimi Zohar
64939f60c1cSChristian Brauner action = ima_must_appraise(idmap, inode, MAY_ACCESS, POST_SETATTR);
6500d73a552SDmitry Kasatkin iint = integrity_iint_find(inode);
6510d73a552SDmitry Kasatkin if (iint) {
6520d73a552SDmitry Kasatkin set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags);
653da1b0029SMimi Zohar if (!action)
6540d73a552SDmitry Kasatkin clear_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
6550d73a552SDmitry Kasatkin }
6562fe5d6deSMimi Zohar }
65742c63330SMimi Zohar
65842c63330SMimi Zohar /*
65942c63330SMimi Zohar * ima_protect_xattr - protect 'security.ima'
66042c63330SMimi Zohar *
66142c63330SMimi Zohar * Ensure that not just anyone can modify or remove 'security.ima'.
66242c63330SMimi Zohar */
ima_protect_xattr(struct dentry * dentry,const char * xattr_name,const void * xattr_value,size_t xattr_value_len)66342c63330SMimi Zohar static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
66442c63330SMimi Zohar const void *xattr_value, size_t xattr_value_len)
66542c63330SMimi Zohar {
66642c63330SMimi Zohar if (strcmp(xattr_name, XATTR_NAME_IMA) == 0) {
66742c63330SMimi Zohar if (!capable(CAP_SYS_ADMIN))
66842c63330SMimi Zohar return -EPERM;
66942c63330SMimi Zohar return 1;
67042c63330SMimi Zohar }
67142c63330SMimi Zohar return 0;
67242c63330SMimi Zohar }
67342c63330SMimi Zohar
ima_reset_appraise_flags(struct inode * inode,int digsig)674060bdebfSMimi Zohar static void ima_reset_appraise_flags(struct inode *inode, int digsig)
67542c63330SMimi Zohar {
67642c63330SMimi Zohar struct integrity_iint_cache *iint;
67742c63330SMimi Zohar
678a756024eSRoberto Sassu if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
67942c63330SMimi Zohar return;
68042c63330SMimi Zohar
68142c63330SMimi Zohar iint = integrity_iint_find(inode);
68242c63330SMimi Zohar if (!iint)
68342c63330SMimi Zohar return;
684a422638dSEric Richter iint->measured_pcrs = 0;
6850d73a552SDmitry Kasatkin set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags);
686060bdebfSMimi Zohar if (digsig)
6870d73a552SDmitry Kasatkin set_bit(IMA_DIGSIG, &iint->atomic_flags);
6880d73a552SDmitry Kasatkin else
6890d73a552SDmitry Kasatkin clear_bit(IMA_DIGSIG, &iint->atomic_flags);
69042c63330SMimi Zohar }
69142c63330SMimi Zohar
69250f742ddSTHOBY Simon /**
69350f742ddSTHOBY Simon * validate_hash_algo() - Block setxattr with unsupported hash algorithms
69450f742ddSTHOBY Simon * @dentry: object of the setxattr()
69550f742ddSTHOBY Simon * @xattr_value: userland supplied xattr value
69650f742ddSTHOBY Simon * @xattr_value_len: length of xattr_value
69750f742ddSTHOBY Simon *
69850f742ddSTHOBY Simon * The xattr value is mapped to its hash algorithm, and this algorithm
69950f742ddSTHOBY Simon * must be built in the kernel for the setxattr to be allowed.
70050f742ddSTHOBY Simon *
70150f742ddSTHOBY Simon * Emit an audit message when the algorithm is invalid.
70250f742ddSTHOBY Simon *
70350f742ddSTHOBY Simon * Return: 0 on success, else an error.
70450f742ddSTHOBY Simon */
validate_hash_algo(struct dentry * dentry,const struct evm_ima_xattr_data * xattr_value,size_t xattr_value_len)70550f742ddSTHOBY Simon static int validate_hash_algo(struct dentry *dentry,
70650f742ddSTHOBY Simon const struct evm_ima_xattr_data *xattr_value,
70750f742ddSTHOBY Simon size_t xattr_value_len)
70850f742ddSTHOBY Simon {
70950f742ddSTHOBY Simon char *path = NULL, *pathbuf = NULL;
71050f742ddSTHOBY Simon enum hash_algo xattr_hash_algo;
7114f2946aaSTHOBY Simon const char *errmsg = "unavailable-hash-algorithm";
7124f2946aaSTHOBY Simon unsigned int allowed_hashes;
71350f742ddSTHOBY Simon
71450f742ddSTHOBY Simon xattr_hash_algo = ima_get_hash_algo(xattr_value, xattr_value_len);
71550f742ddSTHOBY Simon
7164f2946aaSTHOBY Simon allowed_hashes = atomic_read(&ima_setxattr_allowed_hash_algorithms);
7174f2946aaSTHOBY Simon
7184f2946aaSTHOBY Simon if (allowed_hashes) {
7194f2946aaSTHOBY Simon /* success if the algorithm is allowed in the ima policy */
7204f2946aaSTHOBY Simon if (allowed_hashes & (1U << xattr_hash_algo))
72150f742ddSTHOBY Simon return 0;
72250f742ddSTHOBY Simon
7234f2946aaSTHOBY Simon /*
7244f2946aaSTHOBY Simon * We use a different audit message when the hash algorithm
7254f2946aaSTHOBY Simon * is denied by a policy rule, instead of not being built
7264f2946aaSTHOBY Simon * in the kernel image
7274f2946aaSTHOBY Simon */
7284f2946aaSTHOBY Simon errmsg = "denied-hash-algorithm";
7294f2946aaSTHOBY Simon } else {
7304f2946aaSTHOBY Simon if (likely(xattr_hash_algo == ima_hash_algo))
7314f2946aaSTHOBY Simon return 0;
7324f2946aaSTHOBY Simon
7334f2946aaSTHOBY Simon /* allow any xattr using an algorithm built in the kernel */
7344f2946aaSTHOBY Simon if (crypto_has_alg(hash_algo_name[xattr_hash_algo], 0, 0))
7354f2946aaSTHOBY Simon return 0;
7364f2946aaSTHOBY Simon }
7374f2946aaSTHOBY Simon
73850f742ddSTHOBY Simon pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
73950f742ddSTHOBY Simon if (!pathbuf)
74050f742ddSTHOBY Simon return -EACCES;
74150f742ddSTHOBY Simon
74250f742ddSTHOBY Simon path = dentry_path(dentry, pathbuf, PATH_MAX);
74350f742ddSTHOBY Simon
74450f742ddSTHOBY Simon integrity_audit_msg(AUDIT_INTEGRITY_DATA, d_inode(dentry), path,
7454f2946aaSTHOBY Simon "set_data", errmsg, -EACCES, 0);
74650f742ddSTHOBY Simon
74750f742ddSTHOBY Simon kfree(pathbuf);
74850f742ddSTHOBY Simon
74950f742ddSTHOBY Simon return -EACCES;
75050f742ddSTHOBY Simon }
75150f742ddSTHOBY Simon
ima_inode_setxattr(struct dentry * dentry,const char * xattr_name,const void * xattr_value,size_t xattr_value_len)75242c63330SMimi Zohar int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
75342c63330SMimi Zohar const void *xattr_value, size_t xattr_value_len)
75442c63330SMimi Zohar {
755060bdebfSMimi Zohar const struct evm_ima_xattr_data *xvalue = xattr_value;
756e3ccfe1aSRoberto Sassu int digsig = 0;
75742c63330SMimi Zohar int result;
7585926586fSMimi Zohar int err;
75942c63330SMimi Zohar
76042c63330SMimi Zohar result = ima_protect_xattr(dentry, xattr_name, xattr_value,
76142c63330SMimi Zohar xattr_value_len);
76242c63330SMimi Zohar if (result == 1) {
763a48fda9dSDmitry Kasatkin if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
764a48fda9dSDmitry Kasatkin return -EINVAL;
7655926586fSMimi Zohar
7665926586fSMimi Zohar err = validate_hash_algo(dentry, xvalue, xattr_value_len);
7675926586fSMimi Zohar if (err)
7685926586fSMimi Zohar return err;
7695926586fSMimi Zohar
770e3ccfe1aSRoberto Sassu digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
7717aa5783dSRoberto Sassu } else if (!strcmp(xattr_name, XATTR_NAME_EVM) && xattr_value_len > 0) {
7727aa5783dSRoberto Sassu digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
773e3ccfe1aSRoberto Sassu }
774e3ccfe1aSRoberto Sassu if (result == 1 || evm_revalidate_status(xattr_name)) {
775e3ccfe1aSRoberto Sassu ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
7765926586fSMimi Zohar if (result == 1)
7775926586fSMimi Zohar result = 0;
77842c63330SMimi Zohar }
77942c63330SMimi Zohar return result;
78042c63330SMimi Zohar }
78142c63330SMimi Zohar
ima_inode_set_acl(struct mnt_idmap * idmap,struct dentry * dentry,const char * acl_name,struct posix_acl * kacl)782700b7940SChristian Brauner int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
783e61b135fSChristian Brauner const char *acl_name, struct posix_acl *kacl)
784e61b135fSChristian Brauner {
785e61b135fSChristian Brauner if (evm_revalidate_status(acl_name))
786e61b135fSChristian Brauner ima_reset_appraise_flags(d_backing_inode(dentry), 0);
787e61b135fSChristian Brauner
788e61b135fSChristian Brauner return 0;
789e61b135fSChristian Brauner }
790e61b135fSChristian Brauner
ima_inode_removexattr(struct dentry * dentry,const char * xattr_name)79142c63330SMimi Zohar int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
79242c63330SMimi Zohar {
79342c63330SMimi Zohar int result;
79442c63330SMimi Zohar
79542c63330SMimi Zohar result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
796e3ccfe1aSRoberto Sassu if (result == 1 || evm_revalidate_status(xattr_name)) {
797c6f493d6SDavid Howells ima_reset_appraise_flags(d_backing_inode(dentry), 0);
798e3ccfe1aSRoberto Sassu if (result == 1)
79942c63330SMimi Zohar result = 0;
80042c63330SMimi Zohar }
80142c63330SMimi Zohar return result;
80242c63330SMimi Zohar }
803