xref: /OK3568_Linux_fs/kernel/security/integrity/ima/ima_api.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2008 IBM Corporation
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Mimi Zohar <zohar@us.ibm.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * File: ima_api.c
8*4882a593Smuzhiyun  *	Implements must_appraise_or_measure, collect_measurement,
9*4882a593Smuzhiyun  *	appraise_measurement, store_measurement and store_template.
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/file.h>
13*4882a593Smuzhiyun #include <linux/fs.h>
14*4882a593Smuzhiyun #include <linux/xattr.h>
15*4882a593Smuzhiyun #include <linux/evm.h>
16*4882a593Smuzhiyun #include <linux/iversion.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include "ima.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun  * ima_free_template_entry - free an existing template entry
22*4882a593Smuzhiyun  */
ima_free_template_entry(struct ima_template_entry * entry)23*4882a593Smuzhiyun void ima_free_template_entry(struct ima_template_entry *entry)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	int i;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 	for (i = 0; i < entry->template_desc->num_fields; i++)
28*4882a593Smuzhiyun 		kfree(entry->template_data[i].data);
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	kfree(entry->digests);
31*4882a593Smuzhiyun 	kfree(entry);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /*
35*4882a593Smuzhiyun  * ima_alloc_init_template - create and initialize a new template entry
36*4882a593Smuzhiyun  */
ima_alloc_init_template(struct ima_event_data * event_data,struct ima_template_entry ** entry,struct ima_template_desc * desc)37*4882a593Smuzhiyun int ima_alloc_init_template(struct ima_event_data *event_data,
38*4882a593Smuzhiyun 			    struct ima_template_entry **entry,
39*4882a593Smuzhiyun 			    struct ima_template_desc *desc)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	struct ima_template_desc *template_desc;
42*4882a593Smuzhiyun 	struct tpm_digest *digests;
43*4882a593Smuzhiyun 	int i, result = 0;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	if (desc)
46*4882a593Smuzhiyun 		template_desc = desc;
47*4882a593Smuzhiyun 	else
48*4882a593Smuzhiyun 		template_desc = ima_template_desc_current();
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	*entry = kzalloc(struct_size(*entry, template_data,
51*4882a593Smuzhiyun 				     template_desc->num_fields), GFP_NOFS);
52*4882a593Smuzhiyun 	if (!*entry)
53*4882a593Smuzhiyun 		return -ENOMEM;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
56*4882a593Smuzhiyun 			  sizeof(*digests), GFP_NOFS);
57*4882a593Smuzhiyun 	if (!digests) {
58*4882a593Smuzhiyun 		kfree(*entry);
59*4882a593Smuzhiyun 		*entry = NULL;
60*4882a593Smuzhiyun 		return -ENOMEM;
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	(*entry)->digests = digests;
64*4882a593Smuzhiyun 	(*entry)->template_desc = template_desc;
65*4882a593Smuzhiyun 	for (i = 0; i < template_desc->num_fields; i++) {
66*4882a593Smuzhiyun 		const struct ima_template_field *field =
67*4882a593Smuzhiyun 			template_desc->fields[i];
68*4882a593Smuzhiyun 		u32 len;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 		result = field->field_init(event_data,
71*4882a593Smuzhiyun 					   &((*entry)->template_data[i]));
72*4882a593Smuzhiyun 		if (result != 0)
73*4882a593Smuzhiyun 			goto out;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 		len = (*entry)->template_data[i].len;
76*4882a593Smuzhiyun 		(*entry)->template_data_len += sizeof(len);
77*4882a593Smuzhiyun 		(*entry)->template_data_len += len;
78*4882a593Smuzhiyun 	}
79*4882a593Smuzhiyun 	return 0;
80*4882a593Smuzhiyun out:
81*4882a593Smuzhiyun 	ima_free_template_entry(*entry);
82*4882a593Smuzhiyun 	*entry = NULL;
83*4882a593Smuzhiyun 	return result;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun /*
87*4882a593Smuzhiyun  * ima_store_template - store ima template measurements
88*4882a593Smuzhiyun  *
89*4882a593Smuzhiyun  * Calculate the hash of a template entry, add the template entry
90*4882a593Smuzhiyun  * to an ordered list of measurement entries maintained inside the kernel,
91*4882a593Smuzhiyun  * and also update the aggregate integrity value (maintained inside the
92*4882a593Smuzhiyun  * configured TPM PCR) over the hashes of the current list of measurement
93*4882a593Smuzhiyun  * entries.
94*4882a593Smuzhiyun  *
95*4882a593Smuzhiyun  * Applications retrieve the current kernel-held measurement list through
96*4882a593Smuzhiyun  * the securityfs entries in /sys/kernel/security/ima. The signed aggregate
97*4882a593Smuzhiyun  * TPM PCR (called quote) can be retrieved using a TPM user space library
98*4882a593Smuzhiyun  * and is used to validate the measurement list.
99*4882a593Smuzhiyun  *
100*4882a593Smuzhiyun  * Returns 0 on success, error code otherwise
101*4882a593Smuzhiyun  */
ima_store_template(struct ima_template_entry * entry,int violation,struct inode * inode,const unsigned char * filename,int pcr)102*4882a593Smuzhiyun int ima_store_template(struct ima_template_entry *entry,
103*4882a593Smuzhiyun 		       int violation, struct inode *inode,
104*4882a593Smuzhiyun 		       const unsigned char *filename, int pcr)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	static const char op[] = "add_template_measure";
107*4882a593Smuzhiyun 	static const char audit_cause[] = "hashing_error";
108*4882a593Smuzhiyun 	char *template_name = entry->template_desc->name;
109*4882a593Smuzhiyun 	int result;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if (!violation) {
112*4882a593Smuzhiyun 		result = ima_calc_field_array_hash(&entry->template_data[0],
113*4882a593Smuzhiyun 						   entry);
114*4882a593Smuzhiyun 		if (result < 0) {
115*4882a593Smuzhiyun 			integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
116*4882a593Smuzhiyun 					    template_name, op,
117*4882a593Smuzhiyun 					    audit_cause, result, 0);
118*4882a593Smuzhiyun 			return result;
119*4882a593Smuzhiyun 		}
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 	entry->pcr = pcr;
122*4882a593Smuzhiyun 	result = ima_add_template_entry(entry, violation, op, inode, filename);
123*4882a593Smuzhiyun 	return result;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /*
127*4882a593Smuzhiyun  * ima_add_violation - add violation to measurement list.
128*4882a593Smuzhiyun  *
129*4882a593Smuzhiyun  * Violations are flagged in the measurement list with zero hash values.
130*4882a593Smuzhiyun  * By extending the PCR with 0xFF's instead of with zeroes, the PCR
131*4882a593Smuzhiyun  * value is invalidated.
132*4882a593Smuzhiyun  */
ima_add_violation(struct file * file,const unsigned char * filename,struct integrity_iint_cache * iint,const char * op,const char * cause)133*4882a593Smuzhiyun void ima_add_violation(struct file *file, const unsigned char *filename,
134*4882a593Smuzhiyun 		       struct integrity_iint_cache *iint,
135*4882a593Smuzhiyun 		       const char *op, const char *cause)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	struct ima_template_entry *entry;
138*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
139*4882a593Smuzhiyun 	struct ima_event_data event_data = { .iint = iint,
140*4882a593Smuzhiyun 					     .file = file,
141*4882a593Smuzhiyun 					     .filename = filename,
142*4882a593Smuzhiyun 					     .violation = cause };
143*4882a593Smuzhiyun 	int violation = 1;
144*4882a593Smuzhiyun 	int result;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	/* can overflow, only indicator */
147*4882a593Smuzhiyun 	atomic_long_inc(&ima_htable.violations);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	result = ima_alloc_init_template(&event_data, &entry, NULL);
150*4882a593Smuzhiyun 	if (result < 0) {
151*4882a593Smuzhiyun 		result = -ENOMEM;
152*4882a593Smuzhiyun 		goto err_out;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 	result = ima_store_template(entry, violation, inode,
155*4882a593Smuzhiyun 				    filename, CONFIG_IMA_MEASURE_PCR_IDX);
156*4882a593Smuzhiyun 	if (result < 0)
157*4882a593Smuzhiyun 		ima_free_template_entry(entry);
158*4882a593Smuzhiyun err_out:
159*4882a593Smuzhiyun 	integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
160*4882a593Smuzhiyun 			    op, cause, result, 0);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun /**
164*4882a593Smuzhiyun  * ima_get_action - appraise & measure decision based on policy.
165*4882a593Smuzhiyun  * @inode: pointer to the inode associated with the object being validated
166*4882a593Smuzhiyun  * @cred: pointer to credentials structure to validate
167*4882a593Smuzhiyun  * @secid: secid of the task being validated
168*4882a593Smuzhiyun  * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXEC,
169*4882a593Smuzhiyun  *        MAY_APPEND)
170*4882a593Smuzhiyun  * @func: caller identifier
171*4882a593Smuzhiyun  * @pcr: pointer filled in if matched measure policy sets pcr=
172*4882a593Smuzhiyun  * @template_desc: pointer filled in if matched measure policy sets template=
173*4882a593Smuzhiyun  * @keyring: keyring name used to determine the action
174*4882a593Smuzhiyun  *
175*4882a593Smuzhiyun  * The policy is defined in terms of keypairs:
176*4882a593Smuzhiyun  *		subj=, obj=, type=, func=, mask=, fsmagic=
177*4882a593Smuzhiyun  *	subj,obj, and type: are LSM specific.
178*4882a593Smuzhiyun  *	func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
179*4882a593Smuzhiyun  *	| KEXEC_CMDLINE | KEY_CHECK
180*4882a593Smuzhiyun  *	mask: contains the permission mask
181*4882a593Smuzhiyun  *	fsmagic: hex value
182*4882a593Smuzhiyun  *
183*4882a593Smuzhiyun  * Returns IMA_MEASURE, IMA_APPRAISE mask.
184*4882a593Smuzhiyun  *
185*4882a593Smuzhiyun  */
ima_get_action(struct inode * inode,const struct cred * cred,u32 secid,int mask,enum ima_hooks func,int * pcr,struct ima_template_desc ** template_desc,const char * keyring)186*4882a593Smuzhiyun int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
187*4882a593Smuzhiyun 		   int mask, enum ima_hooks func, int *pcr,
188*4882a593Smuzhiyun 		   struct ima_template_desc **template_desc,
189*4882a593Smuzhiyun 		   const char *keyring)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	flags &= ima_policy_flag;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
196*4882a593Smuzhiyun 				template_desc, keyring);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun /*
200*4882a593Smuzhiyun  * ima_collect_measurement - collect file measurement
201*4882a593Smuzhiyun  *
202*4882a593Smuzhiyun  * Calculate the file hash, if it doesn't already exist,
203*4882a593Smuzhiyun  * storing the measurement and i_version in the iint.
204*4882a593Smuzhiyun  *
205*4882a593Smuzhiyun  * Must be called with iint->mutex held.
206*4882a593Smuzhiyun  *
207*4882a593Smuzhiyun  * Return 0 on success, error code otherwise
208*4882a593Smuzhiyun  */
ima_collect_measurement(struct integrity_iint_cache * iint,struct file * file,void * buf,loff_t size,enum hash_algo algo,struct modsig * modsig)209*4882a593Smuzhiyun int ima_collect_measurement(struct integrity_iint_cache *iint,
210*4882a593Smuzhiyun 			    struct file *file, void *buf, loff_t size,
211*4882a593Smuzhiyun 			    enum hash_algo algo, struct modsig *modsig)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	const char *audit_cause = "failed";
214*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
215*4882a593Smuzhiyun 	const char *filename = file->f_path.dentry->d_name.name;
216*4882a593Smuzhiyun 	int result = 0;
217*4882a593Smuzhiyun 	int length;
218*4882a593Smuzhiyun 	void *tmpbuf;
219*4882a593Smuzhiyun 	u64 i_version;
220*4882a593Smuzhiyun 	struct {
221*4882a593Smuzhiyun 		struct ima_digest_data hdr;
222*4882a593Smuzhiyun 		char digest[IMA_MAX_DIGEST_SIZE];
223*4882a593Smuzhiyun 	} hash;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	/*
226*4882a593Smuzhiyun 	 * Always collect the modsig, because IMA might have already collected
227*4882a593Smuzhiyun 	 * the file digest without collecting the modsig in a previous
228*4882a593Smuzhiyun 	 * measurement rule.
229*4882a593Smuzhiyun 	 */
230*4882a593Smuzhiyun 	if (modsig)
231*4882a593Smuzhiyun 		ima_collect_modsig(modsig, buf, size);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	if (iint->flags & IMA_COLLECTED)
234*4882a593Smuzhiyun 		goto out;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	/*
237*4882a593Smuzhiyun 	 * Dectecting file change is based on i_version. On filesystems
238*4882a593Smuzhiyun 	 * which do not support i_version, support is limited to an initial
239*4882a593Smuzhiyun 	 * measurement/appraisal/audit.
240*4882a593Smuzhiyun 	 */
241*4882a593Smuzhiyun 	i_version = inode_query_iversion(inode);
242*4882a593Smuzhiyun 	hash.hdr.algo = algo;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	/* Initialize hash digest to 0's in case of failure */
245*4882a593Smuzhiyun 	memset(&hash.digest, 0, sizeof(hash.digest));
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	if (buf)
248*4882a593Smuzhiyun 		result = ima_calc_buffer_hash(buf, size, &hash.hdr);
249*4882a593Smuzhiyun 	else
250*4882a593Smuzhiyun 		result = ima_calc_file_hash(file, &hash.hdr);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	if (result && result != -EBADF && result != -EINVAL)
253*4882a593Smuzhiyun 		goto out;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	length = sizeof(hash.hdr) + hash.hdr.length;
256*4882a593Smuzhiyun 	tmpbuf = krealloc(iint->ima_hash, length, GFP_NOFS);
257*4882a593Smuzhiyun 	if (!tmpbuf) {
258*4882a593Smuzhiyun 		result = -ENOMEM;
259*4882a593Smuzhiyun 		goto out;
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	iint->ima_hash = tmpbuf;
263*4882a593Smuzhiyun 	memcpy(iint->ima_hash, &hash, length);
264*4882a593Smuzhiyun 	iint->version = i_version;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	/* Possibly temporary failure due to type of read (eg. O_DIRECT) */
267*4882a593Smuzhiyun 	if (!result)
268*4882a593Smuzhiyun 		iint->flags |= IMA_COLLECTED;
269*4882a593Smuzhiyun out:
270*4882a593Smuzhiyun 	if (result) {
271*4882a593Smuzhiyun 		if (file->f_flags & O_DIRECT)
272*4882a593Smuzhiyun 			audit_cause = "failed(directio)";
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
275*4882a593Smuzhiyun 				    filename, "collect_data", audit_cause,
276*4882a593Smuzhiyun 				    result, 0);
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 	return result;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun /*
282*4882a593Smuzhiyun  * ima_store_measurement - store file measurement
283*4882a593Smuzhiyun  *
284*4882a593Smuzhiyun  * Create an "ima" template and then store the template by calling
285*4882a593Smuzhiyun  * ima_store_template.
286*4882a593Smuzhiyun  *
287*4882a593Smuzhiyun  * We only get here if the inode has not already been measured,
288*4882a593Smuzhiyun  * but the measurement could already exist:
289*4882a593Smuzhiyun  *	- multiple copies of the same file on either the same or
290*4882a593Smuzhiyun  *	  different filesystems.
291*4882a593Smuzhiyun  *	- the inode was previously flushed as well as the iint info,
292*4882a593Smuzhiyun  *	  containing the hashing info.
293*4882a593Smuzhiyun  *
294*4882a593Smuzhiyun  * Must be called with iint->mutex held.
295*4882a593Smuzhiyun  */
ima_store_measurement(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,int pcr,struct ima_template_desc * template_desc)296*4882a593Smuzhiyun void ima_store_measurement(struct integrity_iint_cache *iint,
297*4882a593Smuzhiyun 			   struct file *file, const unsigned char *filename,
298*4882a593Smuzhiyun 			   struct evm_ima_xattr_data *xattr_value,
299*4882a593Smuzhiyun 			   int xattr_len, const struct modsig *modsig, int pcr,
300*4882a593Smuzhiyun 			   struct ima_template_desc *template_desc)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	static const char op[] = "add_template_measure";
303*4882a593Smuzhiyun 	static const char audit_cause[] = "ENOMEM";
304*4882a593Smuzhiyun 	int result = -ENOMEM;
305*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
306*4882a593Smuzhiyun 	struct ima_template_entry *entry;
307*4882a593Smuzhiyun 	struct ima_event_data event_data = { .iint = iint,
308*4882a593Smuzhiyun 					     .file = file,
309*4882a593Smuzhiyun 					     .filename = filename,
310*4882a593Smuzhiyun 					     .xattr_value = xattr_value,
311*4882a593Smuzhiyun 					     .xattr_len = xattr_len,
312*4882a593Smuzhiyun 					     .modsig = modsig };
313*4882a593Smuzhiyun 	int violation = 0;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	/*
316*4882a593Smuzhiyun 	 * We still need to store the measurement in the case of MODSIG because
317*4882a593Smuzhiyun 	 * we only have its contents to put in the list at the time of
318*4882a593Smuzhiyun 	 * appraisal, but a file measurement from earlier might already exist in
319*4882a593Smuzhiyun 	 * the measurement list.
320*4882a593Smuzhiyun 	 */
321*4882a593Smuzhiyun 	if (iint->measured_pcrs & (0x1 << pcr) && !modsig)
322*4882a593Smuzhiyun 		return;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	result = ima_alloc_init_template(&event_data, &entry, template_desc);
325*4882a593Smuzhiyun 	if (result < 0) {
326*4882a593Smuzhiyun 		integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
327*4882a593Smuzhiyun 				    op, audit_cause, result, 0);
328*4882a593Smuzhiyun 		return;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	result = ima_store_template(entry, violation, inode, filename, pcr);
332*4882a593Smuzhiyun 	if ((!result || result == -EEXIST) && !(file->f_flags & O_DIRECT)) {
333*4882a593Smuzhiyun 		iint->flags |= IMA_MEASURED;
334*4882a593Smuzhiyun 		iint->measured_pcrs |= (0x1 << pcr);
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun 	if (result < 0)
337*4882a593Smuzhiyun 		ima_free_template_entry(entry);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
ima_audit_measurement(struct integrity_iint_cache * iint,const unsigned char * filename)340*4882a593Smuzhiyun void ima_audit_measurement(struct integrity_iint_cache *iint,
341*4882a593Smuzhiyun 			   const unsigned char *filename)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	struct audit_buffer *ab;
344*4882a593Smuzhiyun 	char *hash;
345*4882a593Smuzhiyun 	const char *algo_name = hash_algo_name[iint->ima_hash->algo];
346*4882a593Smuzhiyun 	int i;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	if (iint->flags & IMA_AUDITED)
349*4882a593Smuzhiyun 		return;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	hash = kzalloc((iint->ima_hash->length * 2) + 1, GFP_KERNEL);
352*4882a593Smuzhiyun 	if (!hash)
353*4882a593Smuzhiyun 		return;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	for (i = 0; i < iint->ima_hash->length; i++)
356*4882a593Smuzhiyun 		hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]);
357*4882a593Smuzhiyun 	hash[i * 2] = '\0';
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	ab = audit_log_start(audit_context(), GFP_KERNEL,
360*4882a593Smuzhiyun 			     AUDIT_INTEGRITY_RULE);
361*4882a593Smuzhiyun 	if (!ab)
362*4882a593Smuzhiyun 		goto out;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	audit_log_format(ab, "file=");
365*4882a593Smuzhiyun 	audit_log_untrustedstring(ab, filename);
366*4882a593Smuzhiyun 	audit_log_format(ab, " hash=\"%s:%s\"", algo_name, hash);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	audit_log_task_info(ab);
369*4882a593Smuzhiyun 	audit_log_end(ab);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	iint->flags |= IMA_AUDITED;
372*4882a593Smuzhiyun out:
373*4882a593Smuzhiyun 	kfree(hash);
374*4882a593Smuzhiyun 	return;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun /*
378*4882a593Smuzhiyun  * ima_d_path - return a pointer to the full pathname
379*4882a593Smuzhiyun  *
380*4882a593Smuzhiyun  * Attempt to return a pointer to the full pathname for use in the
381*4882a593Smuzhiyun  * IMA measurement list, IMA audit records, and auditing logs.
382*4882a593Smuzhiyun  *
383*4882a593Smuzhiyun  * On failure, return a pointer to a copy of the filename, not dname.
384*4882a593Smuzhiyun  * Returning a pointer to dname, could result in using the pointer
385*4882a593Smuzhiyun  * after the memory has been freed.
386*4882a593Smuzhiyun  */
ima_d_path(const struct path * path,char ** pathbuf,char * namebuf)387*4882a593Smuzhiyun const char *ima_d_path(const struct path *path, char **pathbuf, char *namebuf)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	char *pathname = NULL;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	*pathbuf = __getname();
392*4882a593Smuzhiyun 	if (*pathbuf) {
393*4882a593Smuzhiyun 		pathname = d_absolute_path(path, *pathbuf, PATH_MAX);
394*4882a593Smuzhiyun 		if (IS_ERR(pathname)) {
395*4882a593Smuzhiyun 			__putname(*pathbuf);
396*4882a593Smuzhiyun 			*pathbuf = NULL;
397*4882a593Smuzhiyun 			pathname = NULL;
398*4882a593Smuzhiyun 		}
399*4882a593Smuzhiyun 	}
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	if (!pathname) {
402*4882a593Smuzhiyun 		strlcpy(namebuf, path->dentry->d_name.name, NAME_MAX);
403*4882a593Smuzhiyun 		pathname = namebuf;
404*4882a593Smuzhiyun 	}
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	return pathname;
407*4882a593Smuzhiyun }
408