xref: /linux/security/integrity/ima/ima_template_lib.c (revision 353ad6c0839431146fdee3ff16f9dd17a2809ee4)
1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23ce1217dSRoberto Sassu /*
33ce1217dSRoberto Sassu  * Copyright (C) 2013 Politecnico di Torino, Italy
4c9fecf50SAlexander A. Klimov  *                    TORSEC group -- https://security.polito.it
53ce1217dSRoberto Sassu  *
63ce1217dSRoberto Sassu  * Author: Roberto Sassu <roberto.sassu@polito.it>
73ce1217dSRoberto Sassu  *
83ce1217dSRoberto Sassu  * File: ima_template_lib.c
93ce1217dSRoberto Sassu  *      Library of supported template fields.
103ce1217dSRoberto Sassu  */
114d7aeee7SRoberto Sassu 
123ce1217dSRoberto Sassu #include "ima_template_lib.h"
13026d7fc9SRoberto Sassu #include <linux/xattr.h>
148314b673SRoberto Sassu #include <linux/evm.h>
153ce1217dSRoberto Sassu 
ima_template_hash_algo_allowed(u8 algo)164d7aeee7SRoberto Sassu static bool ima_template_hash_algo_allowed(u8 algo)
174d7aeee7SRoberto Sassu {
184d7aeee7SRoberto Sassu 	if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5)
194d7aeee7SRoberto Sassu 		return true;
204d7aeee7SRoberto Sassu 
214d7aeee7SRoberto Sassu 	return false;
224d7aeee7SRoberto Sassu }
234d7aeee7SRoberto Sassu 
244d7aeee7SRoberto Sassu enum data_formats {
254d7aeee7SRoberto Sassu 	DATA_FMT_DIGEST = 0,
264d7aeee7SRoberto Sassu 	DATA_FMT_DIGEST_WITH_ALGO,
27989dc725SMimi Zohar 	DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO,
28bcbc9b0cSMimi Zohar 	DATA_FMT_STRING,
29cde1391aSRoberto Sassu 	DATA_FMT_HEX,
30cde1391aSRoberto Sassu 	DATA_FMT_UINT
314d7aeee7SRoberto Sassu };
324d7aeee7SRoberto Sassu 
33989dc725SMimi Zohar enum digest_type {
34989dc725SMimi Zohar 	DIGEST_TYPE_IMA,
3554f03916SMimi Zohar 	DIGEST_TYPE_VERITY,
36989dc725SMimi Zohar 	DIGEST_TYPE__LAST
37989dc725SMimi Zohar };
38989dc725SMimi Zohar 
3954f03916SMimi Zohar #define DIGEST_TYPE_NAME_LEN_MAX 7	/* including NUL */
40989dc725SMimi Zohar static const char * const digest_type_name[DIGEST_TYPE__LAST] = {
4154f03916SMimi Zohar 	[DIGEST_TYPE_IMA] = "ima",
4254f03916SMimi Zohar 	[DIGEST_TYPE_VERITY] = "verity"
43989dc725SMimi Zohar };
44989dc725SMimi Zohar 
ima_write_template_field_data(const void * data,const u32 datalen,enum data_formats datafmt,struct ima_field_data * field_data)453ce1217dSRoberto Sassu static int ima_write_template_field_data(const void *data, const u32 datalen,
463ce1217dSRoberto Sassu 					 enum data_formats datafmt,
473ce1217dSRoberto Sassu 					 struct ima_field_data *field_data)
483ce1217dSRoberto Sassu {
493ce1217dSRoberto Sassu 	u8 *buf, *buf_ptr;
50e3b64c26SRoberto Sassu 	u32 buflen = datalen;
513ce1217dSRoberto Sassu 
52e3b64c26SRoberto Sassu 	if (datafmt == DATA_FMT_STRING)
533ce1217dSRoberto Sassu 		buflen = datalen + 1;
543ce1217dSRoberto Sassu 
553ce1217dSRoberto Sassu 	buf = kzalloc(buflen, GFP_KERNEL);
563ce1217dSRoberto Sassu 	if (!buf)
573ce1217dSRoberto Sassu 		return -ENOMEM;
583ce1217dSRoberto Sassu 
593ce1217dSRoberto Sassu 	memcpy(buf, data, datalen);
603ce1217dSRoberto Sassu 
613ce1217dSRoberto Sassu 	/*
623ce1217dSRoberto Sassu 	 * Replace all space characters with underscore for event names and
633ce1217dSRoberto Sassu 	 * strings. This avoid that, during the parsing of a measurements list,
643ce1217dSRoberto Sassu 	 * filenames with spaces or that end with the suffix ' (deleted)' are
653ce1217dSRoberto Sassu 	 * split into multiple template fields (the space is the delimitator
663ce1217dSRoberto Sassu 	 * character for measurements lists in ASCII format).
673ce1217dSRoberto Sassu 	 */
68e3b64c26SRoberto Sassu 	if (datafmt == DATA_FMT_STRING) {
693ce1217dSRoberto Sassu 		for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++)
703ce1217dSRoberto Sassu 			if (*buf_ptr == ' ')
713ce1217dSRoberto Sassu 				*buf_ptr = '_';
723ce1217dSRoberto Sassu 	}
733ce1217dSRoberto Sassu 
743ce1217dSRoberto Sassu 	field_data->data = buf;
753ce1217dSRoberto Sassu 	field_data->len = buflen;
763ce1217dSRoberto Sassu 	return 0;
773ce1217dSRoberto Sassu }
783ce1217dSRoberto Sassu 
ima_show_template_data_ascii(struct seq_file * m,enum ima_show_type show,enum data_formats datafmt,struct ima_field_data * field_data)793ce1217dSRoberto Sassu static void ima_show_template_data_ascii(struct seq_file *m,
803ce1217dSRoberto Sassu 					 enum ima_show_type show,
813ce1217dSRoberto Sassu 					 enum data_formats datafmt,
823ce1217dSRoberto Sassu 					 struct ima_field_data *field_data)
833ce1217dSRoberto Sassu {
8445b26133SMimi Zohar 	u8 *buf_ptr = field_data->data;
8545b26133SMimi Zohar 	u32 buflen = field_data->len;
864d7aeee7SRoberto Sassu 
873ce1217dSRoberto Sassu 	switch (datafmt) {
88989dc725SMimi Zohar 	case DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO:
894d7aeee7SRoberto Sassu 	case DATA_FMT_DIGEST_WITH_ALGO:
90989dc725SMimi Zohar 		buf_ptr = strrchr(field_data->data, ':');
914d7aeee7SRoberto Sassu 		if (buf_ptr != field_data->data)
924d7aeee7SRoberto Sassu 			seq_printf(m, "%s", field_data->data);
934d7aeee7SRoberto Sassu 
944d7aeee7SRoberto Sassu 		/* skip ':' and '\0' */
954d7aeee7SRoberto Sassu 		buf_ptr += 2;
964d7aeee7SRoberto Sassu 		buflen -= buf_ptr - field_data->data;
97df561f66SGustavo A. R. Silva 		fallthrough;
983ce1217dSRoberto Sassu 	case DATA_FMT_DIGEST:
99bcbc9b0cSMimi Zohar 	case DATA_FMT_HEX:
100bcbc9b0cSMimi Zohar 		if (!buflen)
101bcbc9b0cSMimi Zohar 			break;
1024d7aeee7SRoberto Sassu 		ima_print_digest(m, buf_ptr, buflen);
1033ce1217dSRoberto Sassu 		break;
1043ce1217dSRoberto Sassu 	case DATA_FMT_STRING:
1054d7aeee7SRoberto Sassu 		seq_printf(m, "%s", buf_ptr);
1063ce1217dSRoberto Sassu 		break;
107cde1391aSRoberto Sassu 	case DATA_FMT_UINT:
108cde1391aSRoberto Sassu 		switch (field_data->len) {
109cde1391aSRoberto Sassu 		case sizeof(u8):
110cde1391aSRoberto Sassu 			seq_printf(m, "%u", *(u8 *)buf_ptr);
111cde1391aSRoberto Sassu 			break;
112cde1391aSRoberto Sassu 		case sizeof(u16):
113cde1391aSRoberto Sassu 			if (ima_canonical_fmt)
114cde1391aSRoberto Sassu 				seq_printf(m, "%u",
11524c9ae23SRoberto Sassu 					   le16_to_cpu(*(__le16 *)buf_ptr));
116cde1391aSRoberto Sassu 			else
117cde1391aSRoberto Sassu 				seq_printf(m, "%u", *(u16 *)buf_ptr);
118cde1391aSRoberto Sassu 			break;
119cde1391aSRoberto Sassu 		case sizeof(u32):
120cde1391aSRoberto Sassu 			if (ima_canonical_fmt)
121cde1391aSRoberto Sassu 				seq_printf(m, "%u",
12224c9ae23SRoberto Sassu 					   le32_to_cpu(*(__le32 *)buf_ptr));
123cde1391aSRoberto Sassu 			else
124cde1391aSRoberto Sassu 				seq_printf(m, "%u", *(u32 *)buf_ptr);
125cde1391aSRoberto Sassu 			break;
126cde1391aSRoberto Sassu 		case sizeof(u64):
127cde1391aSRoberto Sassu 			if (ima_canonical_fmt)
128cde1391aSRoberto Sassu 				seq_printf(m, "%llu",
12924c9ae23SRoberto Sassu 					   le64_to_cpu(*(__le64 *)buf_ptr));
130cde1391aSRoberto Sassu 			else
131cde1391aSRoberto Sassu 				seq_printf(m, "%llu", *(u64 *)buf_ptr);
132cde1391aSRoberto Sassu 			break;
133cde1391aSRoberto Sassu 		default:
134cde1391aSRoberto Sassu 			break;
135cde1391aSRoberto Sassu 		}
1367d2201d4SGustavo A. R. Silva 		break;
1373ce1217dSRoberto Sassu 	default:
1383ce1217dSRoberto Sassu 		break;
1393ce1217dSRoberto Sassu 	}
1403ce1217dSRoberto Sassu }
1413ce1217dSRoberto Sassu 
ima_show_template_data_binary(struct seq_file * m,enum ima_show_type show,enum data_formats datafmt,struct ima_field_data * field_data)1423ce1217dSRoberto Sassu static void ima_show_template_data_binary(struct seq_file *m,
1433ce1217dSRoberto Sassu 					  enum ima_show_type show,
1443ce1217dSRoberto Sassu 					  enum data_formats datafmt,
1453ce1217dSRoberto Sassu 					  struct ima_field_data *field_data)
1463ce1217dSRoberto Sassu {
147c019e307SRoberto Sassu 	u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ?
148c019e307SRoberto Sassu 	    strlen(field_data->data) : field_data->len;
1493e8e5503SRoberto Sassu 
150d68a6fe9SMimi Zohar 	if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) {
1516b26285fSRoberto Sassu 		u32 field_len = !ima_canonical_fmt ?
1526b26285fSRoberto Sassu 				len : (__force u32)cpu_to_le32(len);
153d68a6fe9SMimi Zohar 
154d68a6fe9SMimi Zohar 		ima_putc(m, &field_len, sizeof(field_len));
155d68a6fe9SMimi Zohar 	}
156c019e307SRoberto Sassu 
157c019e307SRoberto Sassu 	if (!len)
1583ce1217dSRoberto Sassu 		return;
1593e8e5503SRoberto Sassu 
160c019e307SRoberto Sassu 	ima_putc(m, field_data->data, len);
1613ce1217dSRoberto Sassu }
1623ce1217dSRoberto Sassu 
ima_show_template_field_data(struct seq_file * m,enum ima_show_type show,enum data_formats datafmt,struct ima_field_data * field_data)1633ce1217dSRoberto Sassu static void ima_show_template_field_data(struct seq_file *m,
1643ce1217dSRoberto Sassu 					 enum ima_show_type show,
1653ce1217dSRoberto Sassu 					 enum data_formats datafmt,
1663ce1217dSRoberto Sassu 					 struct ima_field_data *field_data)
1673ce1217dSRoberto Sassu {
1683ce1217dSRoberto Sassu 	switch (show) {
1693ce1217dSRoberto Sassu 	case IMA_SHOW_ASCII:
1703ce1217dSRoberto Sassu 		ima_show_template_data_ascii(m, show, datafmt, field_data);
1713ce1217dSRoberto Sassu 		break;
1723ce1217dSRoberto Sassu 	case IMA_SHOW_BINARY:
1733e8e5503SRoberto Sassu 	case IMA_SHOW_BINARY_NO_FIELD_LEN:
174c019e307SRoberto Sassu 	case IMA_SHOW_BINARY_OLD_STRING_FMT:
1753ce1217dSRoberto Sassu 		ima_show_template_data_binary(m, show, datafmt, field_data);
1763ce1217dSRoberto Sassu 		break;
1773ce1217dSRoberto Sassu 	default:
1783ce1217dSRoberto Sassu 		break;
1793ce1217dSRoberto Sassu 	}
1803ce1217dSRoberto Sassu }
1813ce1217dSRoberto Sassu 
ima_show_template_digest(struct seq_file * m,enum ima_show_type show,struct ima_field_data * field_data)1823ce1217dSRoberto Sassu void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
1833ce1217dSRoberto Sassu 			      struct ima_field_data *field_data)
1843ce1217dSRoberto Sassu {
1853ce1217dSRoberto Sassu 	ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data);
1863ce1217dSRoberto Sassu }
1873ce1217dSRoberto Sassu 
ima_show_template_digest_ng(struct seq_file * m,enum ima_show_type show,struct ima_field_data * field_data)1884d7aeee7SRoberto Sassu void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
1894d7aeee7SRoberto Sassu 				 struct ima_field_data *field_data)
1904d7aeee7SRoberto Sassu {
1914d7aeee7SRoberto Sassu 	ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO,
1924d7aeee7SRoberto Sassu 				     field_data);
1934d7aeee7SRoberto Sassu }
1944d7aeee7SRoberto Sassu 
ima_show_template_digest_ngv2(struct seq_file * m,enum ima_show_type show,struct ima_field_data * field_data)195989dc725SMimi Zohar void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show,
196989dc725SMimi Zohar 				   struct ima_field_data *field_data)
197989dc725SMimi Zohar {
198989dc725SMimi Zohar 	ima_show_template_field_data(m, show,
199989dc725SMimi Zohar 				     DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO,
200989dc725SMimi Zohar 				     field_data);
201989dc725SMimi Zohar }
202989dc725SMimi Zohar 
ima_show_template_string(struct seq_file * m,enum ima_show_type show,struct ima_field_data * field_data)2033ce1217dSRoberto Sassu void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
2043ce1217dSRoberto Sassu 			      struct ima_field_data *field_data)
2053ce1217dSRoberto Sassu {
2063ce1217dSRoberto Sassu 	ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
2073ce1217dSRoberto Sassu }
2083ce1217dSRoberto Sassu 
ima_show_template_sig(struct seq_file * m,enum ima_show_type show,struct ima_field_data * field_data)209bcbc9b0cSMimi Zohar void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
210bcbc9b0cSMimi Zohar 			   struct ima_field_data *field_data)
211bcbc9b0cSMimi Zohar {
212bcbc9b0cSMimi Zohar 	ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
213bcbc9b0cSMimi Zohar }
214bcbc9b0cSMimi Zohar 
ima_show_template_buf(struct seq_file * m,enum ima_show_type show,struct ima_field_data * field_data)21586b4da8cSPrakhar Srivastava void ima_show_template_buf(struct seq_file *m, enum ima_show_type show,
21686b4da8cSPrakhar Srivastava 			   struct ima_field_data *field_data)
21786b4da8cSPrakhar Srivastava {
21886b4da8cSPrakhar Srivastava 	ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
21986b4da8cSPrakhar Srivastava }
22086b4da8cSPrakhar Srivastava 
ima_show_template_uint(struct seq_file * m,enum ima_show_type show,struct ima_field_data * field_data)221cde1391aSRoberto Sassu void ima_show_template_uint(struct seq_file *m, enum ima_show_type show,
222cde1391aSRoberto Sassu 			    struct ima_field_data *field_data)
223cde1391aSRoberto Sassu {
224cde1391aSRoberto Sassu 	ima_show_template_field_data(m, show, DATA_FMT_UINT, field_data);
225cde1391aSRoberto Sassu }
226cde1391aSRoberto Sassu 
227b17fd9ecSRoberto Sassu /**
228b17fd9ecSRoberto Sassu  * ima_parse_buf() - Parses lengths and data from an input buffer
229b17fd9ecSRoberto Sassu  * @bufstartp:       Buffer start address.
230b17fd9ecSRoberto Sassu  * @bufendp:         Buffer end address.
231b17fd9ecSRoberto Sassu  * @bufcurp:         Pointer to remaining (non-parsed) data.
232b17fd9ecSRoberto Sassu  * @maxfields:       Length of fields array.
233b17fd9ecSRoberto Sassu  * @fields:          Array containing lengths and pointers of parsed data.
234b17fd9ecSRoberto Sassu  * @curfields:       Number of array items containing parsed data.
235b17fd9ecSRoberto Sassu  * @len_mask:        Bitmap (if bit is set, data length should not be parsed).
236b17fd9ecSRoberto Sassu  * @enforce_mask:    Check if curfields == maxfields and/or bufcurp == bufendp.
237b17fd9ecSRoberto Sassu  * @bufname:         String identifier of the input buffer.
238b17fd9ecSRoberto Sassu  *
239b17fd9ecSRoberto Sassu  * Return: 0 on success, -EINVAL on error.
240b17fd9ecSRoberto Sassu  */
ima_parse_buf(void * bufstartp,void * bufendp,void ** bufcurp,int maxfields,struct ima_field_data * fields,int * curfields,unsigned long * len_mask,int enforce_mask,char * bufname)241b17fd9ecSRoberto Sassu int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
242b17fd9ecSRoberto Sassu 		  int maxfields, struct ima_field_data *fields, int *curfields,
243b17fd9ecSRoberto Sassu 		  unsigned long *len_mask, int enforce_mask, char *bufname)
244b17fd9ecSRoberto Sassu {
245b17fd9ecSRoberto Sassu 	void *bufp = bufstartp;
246b17fd9ecSRoberto Sassu 	int i;
247b17fd9ecSRoberto Sassu 
248b17fd9ecSRoberto Sassu 	for (i = 0; i < maxfields; i++) {
249b17fd9ecSRoberto Sassu 		if (len_mask == NULL || !test_bit(i, len_mask)) {
250b17fd9ecSRoberto Sassu 			if (bufp > (bufendp - sizeof(u32)))
251b17fd9ecSRoberto Sassu 				break;
252b17fd9ecSRoberto Sassu 
253b17fd9ecSRoberto Sassu 			if (ima_canonical_fmt)
25424c9ae23SRoberto Sassu 				fields[i].len = le32_to_cpu(*(__le32 *)bufp);
25524c9ae23SRoberto Sassu 			else
25624c9ae23SRoberto Sassu 				fields[i].len = *(u32 *)bufp;
257b17fd9ecSRoberto Sassu 
258b17fd9ecSRoberto Sassu 			bufp += sizeof(u32);
259b17fd9ecSRoberto Sassu 		}
260b17fd9ecSRoberto Sassu 
261b17fd9ecSRoberto Sassu 		if (bufp > (bufendp - fields[i].len))
262b17fd9ecSRoberto Sassu 			break;
263b17fd9ecSRoberto Sassu 
264b17fd9ecSRoberto Sassu 		fields[i].data = bufp;
265b17fd9ecSRoberto Sassu 		bufp += fields[i].len;
266b17fd9ecSRoberto Sassu 	}
267b17fd9ecSRoberto Sassu 
268b17fd9ecSRoberto Sassu 	if ((enforce_mask & ENFORCE_FIELDS) && i != maxfields) {
269b17fd9ecSRoberto Sassu 		pr_err("%s: nr of fields mismatch: expected: %d, current: %d\n",
270b17fd9ecSRoberto Sassu 		       bufname, maxfields, i);
271b17fd9ecSRoberto Sassu 		return -EINVAL;
272b17fd9ecSRoberto Sassu 	}
273b17fd9ecSRoberto Sassu 
274b17fd9ecSRoberto Sassu 	if ((enforce_mask & ENFORCE_BUFEND) && bufp != bufendp) {
275b17fd9ecSRoberto Sassu 		pr_err("%s: buf end mismatch: expected: %p, current: %p\n",
276b17fd9ecSRoberto Sassu 		       bufname, bufendp, bufp);
277b17fd9ecSRoberto Sassu 		return -EINVAL;
278b17fd9ecSRoberto Sassu 	}
279b17fd9ecSRoberto Sassu 
280b17fd9ecSRoberto Sassu 	if (curfields)
281b17fd9ecSRoberto Sassu 		*curfields = i;
282b17fd9ecSRoberto Sassu 
283b17fd9ecSRoberto Sassu 	if (bufcurp)
284b17fd9ecSRoberto Sassu 		*bufcurp = bufp;
285b17fd9ecSRoberto Sassu 
286b17fd9ecSRoberto Sassu 	return 0;
287b17fd9ecSRoberto Sassu }
288b17fd9ecSRoberto Sassu 
ima_eventdigest_init_common(const u8 * digest,u32 digestsize,u8 digest_type,u8 hash_algo,struct ima_field_data * field_data)2893878d505SThiago Jung Bauermann static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
290989dc725SMimi Zohar 				       u8 digest_type, u8 hash_algo,
291dcf4e392SRoberto Sassu 				       struct ima_field_data *field_data)
2924d7aeee7SRoberto Sassu {
2933ce1217dSRoberto Sassu 	/*
2944d7aeee7SRoberto Sassu 	 * digest formats:
2954d7aeee7SRoberto Sassu 	 *  - DATA_FMT_DIGEST: digest
29664466462SMimi Zohar 	 *  - DATA_FMT_DIGEST_WITH_ALGO: <hash algo> + ':' + '\0' + digest,
297989dc725SMimi Zohar 	 *  - DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO:
298989dc725SMimi Zohar 	 *	<digest type> + ':' + <hash algo> + ':' + '\0' + digest,
29964466462SMimi Zohar 	 *
30064466462SMimi Zohar 	 *    where 'DATA_FMT_DIGEST' is the original digest format ('d')
30164466462SMimi Zohar 	 *      with a hash size limitation of 20 bytes,
30254f03916SMimi Zohar 	 *    where <digest type> is either "ima" or "verity",
30364466462SMimi Zohar 	 *    where <hash algo> is the hash_algo_name[] string.
3044d7aeee7SRoberto Sassu 	 */
305989dc725SMimi Zohar 	u8 buffer[DIGEST_TYPE_NAME_LEN_MAX + CRYPTO_MAX_ALG_NAME + 2 +
306989dc725SMimi Zohar 		IMA_MAX_DIGEST_SIZE] = { 0 };
3074d7aeee7SRoberto Sassu 	enum data_formats fmt = DATA_FMT_DIGEST;
3084d7aeee7SRoberto Sassu 	u32 offset = 0;
3094d7aeee7SRoberto Sassu 
310989dc725SMimi Zohar 	if (digest_type < DIGEST_TYPE__LAST && hash_algo < HASH_ALGO__LAST) {
311989dc725SMimi Zohar 		fmt = DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO;
312989dc725SMimi Zohar 		offset += 1 + sprintf(buffer, "%s:%s:",
313989dc725SMimi Zohar 				      digest_type_name[digest_type],
314dcf4e392SRoberto Sassu 				      hash_algo_name[hash_algo]);
315989dc725SMimi Zohar 	} else if (hash_algo < HASH_ALGO__LAST) {
316989dc725SMimi Zohar 		fmt = DATA_FMT_DIGEST_WITH_ALGO;
317989dc725SMimi Zohar 		offset += 1 + sprintf(buffer, "%s:",
318989dc725SMimi Zohar 				      hash_algo_name[hash_algo]);
3194d7aeee7SRoberto Sassu 	}
3204d7aeee7SRoberto Sassu 
3214d7aeee7SRoberto Sassu 	if (digest)
3224d7aeee7SRoberto Sassu 		memcpy(buffer + offset, digest, digestsize);
3234d7aeee7SRoberto Sassu 	else
3244d7aeee7SRoberto Sassu 		/*
3254d7aeee7SRoberto Sassu 		 * If digest is NULL, the event being recorded is a violation.
3269fab303aSMimi Zohar 		 * Make room for the digest by increasing the offset by the
3279fab303aSMimi Zohar 		 * hash algorithm digest size.
3284d7aeee7SRoberto Sassu 		 */
3299fab303aSMimi Zohar 		offset += hash_digest_size[hash_algo];
3304d7aeee7SRoberto Sassu 
3314d7aeee7SRoberto Sassu 	return ima_write_template_field_data(buffer, offset + digestsize,
3324d7aeee7SRoberto Sassu 					     fmt, field_data);
3334d7aeee7SRoberto Sassu }
3344d7aeee7SRoberto Sassu 
3354d7aeee7SRoberto Sassu /*
3364d7aeee7SRoberto Sassu  * This function writes the digest of an event (with size limit).
3373ce1217dSRoberto Sassu  */
ima_eventdigest_init(struct ima_event_data * event_data,struct ima_field_data * field_data)33823b57419SRoberto Sassu int ima_eventdigest_init(struct ima_event_data *event_data,
3393ce1217dSRoberto Sassu 			 struct ima_field_data *field_data)
3403ce1217dSRoberto Sassu {
3418c54135eSMimi Zohar 	struct ima_max_digest_data hash;
342*38aa3f5aSGustavo A. R. Silva 	struct ima_digest_data *hash_hdr = container_of(&hash.hdr,
343*38aa3f5aSGustavo A. R. Silva 						struct ima_digest_data, hdr);
3444d7aeee7SRoberto Sassu 	u8 *cur_digest = NULL;
3454d7aeee7SRoberto Sassu 	u32 cur_digestsize = 0;
3463ce1217dSRoberto Sassu 	struct inode *inode;
3473ce1217dSRoberto Sassu 	int result;
3483ce1217dSRoberto Sassu 
3493ce1217dSRoberto Sassu 	memset(&hash, 0, sizeof(hash));
3503ce1217dSRoberto Sassu 
3518d94eb9bSRoberto Sassu 	if (event_data->violation)	/* recording a violation. */
3523ce1217dSRoberto Sassu 		goto out;
3533ce1217dSRoberto Sassu 
35423b57419SRoberto Sassu 	if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) {
35523b57419SRoberto Sassu 		cur_digest = event_data->iint->ima_hash->digest;
35623b57419SRoberto Sassu 		cur_digestsize = event_data->iint->ima_hash->length;
3573ce1217dSRoberto Sassu 		goto out;
3583ce1217dSRoberto Sassu 	}
3593ce1217dSRoberto Sassu 
3606cc7c266SRoberto Sassu 	if ((const char *)event_data->filename == boot_aggregate_name) {
3616cc7c266SRoberto Sassu 		if (ima_tpm_chip) {
3626cc7c266SRoberto Sassu 			hash.hdr.algo = HASH_ALGO_SHA1;
363*38aa3f5aSGustavo A. R. Silva 			result = ima_calc_boot_aggregate(hash_hdr);
3646cc7c266SRoberto Sassu 
3656cc7c266SRoberto Sassu 			/* algo can change depending on available PCR banks */
3666cc7c266SRoberto Sassu 			if (!result && hash.hdr.algo != HASH_ALGO_SHA1)
3676cc7c266SRoberto Sassu 				result = -EINVAL;
3686cc7c266SRoberto Sassu 
3696cc7c266SRoberto Sassu 			if (result < 0)
3706cc7c266SRoberto Sassu 				memset(&hash, 0, sizeof(hash));
3716cc7c266SRoberto Sassu 		}
3726cc7c266SRoberto Sassu 
373*38aa3f5aSGustavo A. R. Silva 		cur_digest = hash_hdr->digest;
3746cc7c266SRoberto Sassu 		cur_digestsize = hash_digest_size[HASH_ALGO_SHA1];
3756cc7c266SRoberto Sassu 		goto out;
3766cc7c266SRoberto Sassu 	}
3776cc7c266SRoberto Sassu 
37823b57419SRoberto Sassu 	if (!event_data->file)	/* missing info to re-calculate the digest */
3793ce1217dSRoberto Sassu 		return -EINVAL;
3803ce1217dSRoberto Sassu 
38123b57419SRoberto Sassu 	inode = file_inode(event_data->file);
3824d7aeee7SRoberto Sassu 	hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
3834d7aeee7SRoberto Sassu 	    ima_hash_algo : HASH_ALGO_SHA1;
384*38aa3f5aSGustavo A. R. Silva 	result = ima_calc_file_hash(event_data->file, hash_hdr);
3853ce1217dSRoberto Sassu 	if (result) {
3863ce1217dSRoberto Sassu 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
38723b57419SRoberto Sassu 				    event_data->filename, "collect_data",
3883ce1217dSRoberto Sassu 				    "failed", result, 0);
3893ce1217dSRoberto Sassu 		return result;
3903ce1217dSRoberto Sassu 	}
391*38aa3f5aSGustavo A. R. Silva 	cur_digest = hash_hdr->digest;
3924d7aeee7SRoberto Sassu 	cur_digestsize = hash.hdr.length;
3933ce1217dSRoberto Sassu out:
394712a49bdSRoberto Sassu 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
395989dc725SMimi Zohar 					   DIGEST_TYPE__LAST, HASH_ALGO__LAST,
396989dc725SMimi Zohar 					   field_data);
3973ce1217dSRoberto Sassu }
3983ce1217dSRoberto Sassu 
3993ce1217dSRoberto Sassu /*
4004d7aeee7SRoberto Sassu  * This function writes the digest of an event (without size limit).
4013ce1217dSRoberto Sassu  */
ima_eventdigest_ng_init(struct ima_event_data * event_data,struct ima_field_data * field_data)40223b57419SRoberto Sassu int ima_eventdigest_ng_init(struct ima_event_data *event_data,
40323b57419SRoberto Sassu 			    struct ima_field_data *field_data)
4043ce1217dSRoberto Sassu {
40509091c44SMimi Zohar 	u8 *cur_digest = NULL, hash_algo = ima_hash_algo;
4064d7aeee7SRoberto Sassu 	u32 cur_digestsize = 0;
4074d7aeee7SRoberto Sassu 
4088d94eb9bSRoberto Sassu 	if (event_data->violation)	/* recording a violation. */
4094d7aeee7SRoberto Sassu 		goto out;
4104d7aeee7SRoberto Sassu 
41123b57419SRoberto Sassu 	cur_digest = event_data->iint->ima_hash->digest;
41223b57419SRoberto Sassu 	cur_digestsize = event_data->iint->ima_hash->length;
4134d7aeee7SRoberto Sassu 
41423b57419SRoberto Sassu 	hash_algo = event_data->iint->ima_hash->algo;
4154d7aeee7SRoberto Sassu out:
4164d7aeee7SRoberto Sassu 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
417989dc725SMimi Zohar 					   DIGEST_TYPE__LAST, hash_algo,
418989dc725SMimi Zohar 					   field_data);
419989dc725SMimi Zohar }
420989dc725SMimi Zohar 
421989dc725SMimi Zohar /*
422989dc725SMimi Zohar  * This function writes the digest of an event (without size limit),
423989dc725SMimi Zohar  * prefixed with both the digest type and hash algorithm.
424989dc725SMimi Zohar  */
ima_eventdigest_ngv2_init(struct ima_event_data * event_data,struct ima_field_data * field_data)425989dc725SMimi Zohar int ima_eventdigest_ngv2_init(struct ima_event_data *event_data,
426989dc725SMimi Zohar 			      struct ima_field_data *field_data)
427989dc725SMimi Zohar {
428989dc725SMimi Zohar 	u8 *cur_digest = NULL, hash_algo = ima_hash_algo;
429989dc725SMimi Zohar 	u32 cur_digestsize = 0;
430989dc725SMimi Zohar 	u8 digest_type = DIGEST_TYPE_IMA;
431989dc725SMimi Zohar 
432989dc725SMimi Zohar 	if (event_data->violation)	/* recording a violation. */
433989dc725SMimi Zohar 		goto out;
434989dc725SMimi Zohar 
435989dc725SMimi Zohar 	cur_digest = event_data->iint->ima_hash->digest;
436989dc725SMimi Zohar 	cur_digestsize = event_data->iint->ima_hash->length;
437989dc725SMimi Zohar 
438989dc725SMimi Zohar 	hash_algo = event_data->iint->ima_hash->algo;
43954f03916SMimi Zohar 	if (event_data->iint->flags & IMA_VERITY_REQUIRED)
44054f03916SMimi Zohar 		digest_type = DIGEST_TYPE_VERITY;
441989dc725SMimi Zohar out:
442989dc725SMimi Zohar 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
443989dc725SMimi Zohar 					   digest_type, hash_algo,
444989dc725SMimi Zohar 					   field_data);
4454d7aeee7SRoberto Sassu }
4464d7aeee7SRoberto Sassu 
4473878d505SThiago Jung Bauermann /*
4483878d505SThiago Jung Bauermann  * This function writes the digest of the file which is expected to match the
4493878d505SThiago Jung Bauermann  * digest contained in the file's appended signature.
4503878d505SThiago Jung Bauermann  */
ima_eventdigest_modsig_init(struct ima_event_data * event_data,struct ima_field_data * field_data)4513878d505SThiago Jung Bauermann int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
4523878d505SThiago Jung Bauermann 				struct ima_field_data *field_data)
4533878d505SThiago Jung Bauermann {
4543878d505SThiago Jung Bauermann 	enum hash_algo hash_algo;
4553878d505SThiago Jung Bauermann 	const u8 *cur_digest;
4563878d505SThiago Jung Bauermann 	u32 cur_digestsize;
4573878d505SThiago Jung Bauermann 
4583878d505SThiago Jung Bauermann 	if (!event_data->modsig)
4593878d505SThiago Jung Bauermann 		return 0;
4603878d505SThiago Jung Bauermann 
4613878d505SThiago Jung Bauermann 	if (event_data->violation) {
4623878d505SThiago Jung Bauermann 		/* Recording a violation. */
4633878d505SThiago Jung Bauermann 		hash_algo = HASH_ALGO_SHA1;
4643878d505SThiago Jung Bauermann 		cur_digest = NULL;
4653878d505SThiago Jung Bauermann 		cur_digestsize = 0;
4663878d505SThiago Jung Bauermann 	} else {
4673878d505SThiago Jung Bauermann 		int rc;
4683878d505SThiago Jung Bauermann 
4693878d505SThiago Jung Bauermann 		rc = ima_get_modsig_digest(event_data->modsig, &hash_algo,
4703878d505SThiago Jung Bauermann 					   &cur_digest, &cur_digestsize);
4713878d505SThiago Jung Bauermann 		if (rc)
4723878d505SThiago Jung Bauermann 			return rc;
4733878d505SThiago Jung Bauermann 		else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0)
4743878d505SThiago Jung Bauermann 			/* There was some error collecting the digest. */
4753878d505SThiago Jung Bauermann 			return -EINVAL;
4763878d505SThiago Jung Bauermann 	}
4773878d505SThiago Jung Bauermann 
4783878d505SThiago Jung Bauermann 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
479989dc725SMimi Zohar 					   DIGEST_TYPE__LAST, hash_algo,
480989dc725SMimi Zohar 					   field_data);
4813878d505SThiago Jung Bauermann }
4823878d505SThiago Jung Bauermann 
ima_eventname_init_common(struct ima_event_data * event_data,struct ima_field_data * field_data,bool size_limit)48323b57419SRoberto Sassu static int ima_eventname_init_common(struct ima_event_data *event_data,
4844d7aeee7SRoberto Sassu 				     struct ima_field_data *field_data,
4854d7aeee7SRoberto Sassu 				     bool size_limit)
4864d7aeee7SRoberto Sassu {
4873ce1217dSRoberto Sassu 	const char *cur_filename = NULL;
488be84f32bSStefan Berger 	struct name_snapshot filename;
4893ce1217dSRoberto Sassu 	u32 cur_filename_len = 0;
490be84f32bSStefan Berger 	bool snapshot = false;
491be84f32bSStefan Berger 	int ret;
4923ce1217dSRoberto Sassu 
49323b57419SRoberto Sassu 	BUG_ON(event_data->filename == NULL && event_data->file == NULL);
4943ce1217dSRoberto Sassu 
49523b57419SRoberto Sassu 	if (event_data->filename) {
49623b57419SRoberto Sassu 		cur_filename = event_data->filename;
49723b57419SRoberto Sassu 		cur_filename_len = strlen(event_data->filename);
4983ce1217dSRoberto Sassu 
4994d7aeee7SRoberto Sassu 		if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
5003ce1217dSRoberto Sassu 			goto out;
5013ce1217dSRoberto Sassu 	}
5023ce1217dSRoberto Sassu 
50323b57419SRoberto Sassu 	if (event_data->file) {
504be84f32bSStefan Berger 		take_dentry_name_snapshot(&filename,
505be84f32bSStefan Berger 					  event_data->file->f_path.dentry);
506be84f32bSStefan Berger 		snapshot = true;
507be84f32bSStefan Berger 		cur_filename = filename.name.name;
5083ce1217dSRoberto Sassu 		cur_filename_len = strlen(cur_filename);
5093ce1217dSRoberto Sassu 	} else
5103ce1217dSRoberto Sassu 		/*
5113ce1217dSRoberto Sassu 		 * Truncate filename if the latter is too long and
5123ce1217dSRoberto Sassu 		 * the file descriptor is not available.
5133ce1217dSRoberto Sassu 		 */
5143ce1217dSRoberto Sassu 		cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
5153ce1217dSRoberto Sassu out:
516be84f32bSStefan Berger 	ret = ima_write_template_field_data(cur_filename, cur_filename_len,
517e3b64c26SRoberto Sassu 					    DATA_FMT_STRING, field_data);
518be84f32bSStefan Berger 
519be84f32bSStefan Berger 	if (snapshot)
520be84f32bSStefan Berger 		release_dentry_name_snapshot(&filename);
521be84f32bSStefan Berger 
522be84f32bSStefan Berger 	return ret;
5234d7aeee7SRoberto Sassu }
5244d7aeee7SRoberto Sassu 
5254d7aeee7SRoberto Sassu /*
5264d7aeee7SRoberto Sassu  * This function writes the name of an event (with size limit).
5274d7aeee7SRoberto Sassu  */
ima_eventname_init(struct ima_event_data * event_data,struct ima_field_data * field_data)52823b57419SRoberto Sassu int ima_eventname_init(struct ima_event_data *event_data,
5294d7aeee7SRoberto Sassu 		       struct ima_field_data *field_data)
5304d7aeee7SRoberto Sassu {
53123b57419SRoberto Sassu 	return ima_eventname_init_common(event_data, field_data, true);
5324d7aeee7SRoberto Sassu }
5334d7aeee7SRoberto Sassu 
5344d7aeee7SRoberto Sassu /*
5354d7aeee7SRoberto Sassu  * This function writes the name of an event (without size limit).
5364d7aeee7SRoberto Sassu  */
ima_eventname_ng_init(struct ima_event_data * event_data,struct ima_field_data * field_data)53723b57419SRoberto Sassu int ima_eventname_ng_init(struct ima_event_data *event_data,
5384d7aeee7SRoberto Sassu 			  struct ima_field_data *field_data)
5394d7aeee7SRoberto Sassu {
54023b57419SRoberto Sassu 	return ima_eventname_init_common(event_data, field_data, false);
5413ce1217dSRoberto Sassu }
542bcbc9b0cSMimi Zohar 
543bcbc9b0cSMimi Zohar /*
544bcbc9b0cSMimi Zohar  *  ima_eventsig_init - include the file signature as part of the template data
545bcbc9b0cSMimi Zohar  */
ima_eventsig_init(struct ima_event_data * event_data,struct ima_field_data * field_data)54623b57419SRoberto Sassu int ima_eventsig_init(struct ima_event_data *event_data,
547bcbc9b0cSMimi Zohar 		      struct ima_field_data *field_data)
548bcbc9b0cSMimi Zohar {
54923b57419SRoberto Sassu 	struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
550bcbc9b0cSMimi Zohar 
551398c42e2SMimi Zohar 	if (!xattr_value ||
552398c42e2SMimi Zohar 	    (xattr_value->type != EVM_IMA_XATTR_DIGSIG &&
553398c42e2SMimi Zohar 	     xattr_value->type != IMA_VERITY_DIGSIG))
554026d7fc9SRoberto Sassu 		return ima_eventevmsig_init(event_data, field_data);
555bcbc9b0cSMimi Zohar 
5561775cb87SThiago Jung Bauermann 	return ima_write_template_field_data(xattr_value, event_data->xattr_len,
5571775cb87SThiago Jung Bauermann 					     DATA_FMT_HEX, field_data);
558bcbc9b0cSMimi Zohar }
55986b4da8cSPrakhar Srivastava 
56086b4da8cSPrakhar Srivastava /*
56186b4da8cSPrakhar Srivastava  *  ima_eventbuf_init - include the buffer(kexec-cmldine) as part of the
56286b4da8cSPrakhar Srivastava  *  template data.
56386b4da8cSPrakhar Srivastava  */
ima_eventbuf_init(struct ima_event_data * event_data,struct ima_field_data * field_data)56486b4da8cSPrakhar Srivastava int ima_eventbuf_init(struct ima_event_data *event_data,
56586b4da8cSPrakhar Srivastava 		      struct ima_field_data *field_data)
56686b4da8cSPrakhar Srivastava {
56786b4da8cSPrakhar Srivastava 	if ((!event_data->buf) || (event_data->buf_len == 0))
56886b4da8cSPrakhar Srivastava 		return 0;
56986b4da8cSPrakhar Srivastava 
57086b4da8cSPrakhar Srivastava 	return ima_write_template_field_data(event_data->buf,
57186b4da8cSPrakhar Srivastava 					     event_data->buf_len, DATA_FMT_HEX,
57286b4da8cSPrakhar Srivastava 					     field_data);
57386b4da8cSPrakhar Srivastava }
5743878d505SThiago Jung Bauermann 
5753878d505SThiago Jung Bauermann /*
5763878d505SThiago Jung Bauermann  *  ima_eventmodsig_init - include the appended file signature as part of the
5773878d505SThiago Jung Bauermann  *  template data
5783878d505SThiago Jung Bauermann  */
ima_eventmodsig_init(struct ima_event_data * event_data,struct ima_field_data * field_data)5793878d505SThiago Jung Bauermann int ima_eventmodsig_init(struct ima_event_data *event_data,
5803878d505SThiago Jung Bauermann 			 struct ima_field_data *field_data)
5813878d505SThiago Jung Bauermann {
5823878d505SThiago Jung Bauermann 	const void *data;
5833878d505SThiago Jung Bauermann 	u32 data_len;
5843878d505SThiago Jung Bauermann 	int rc;
5853878d505SThiago Jung Bauermann 
5863878d505SThiago Jung Bauermann 	if (!event_data->modsig)
5873878d505SThiago Jung Bauermann 		return 0;
5883878d505SThiago Jung Bauermann 
5893878d505SThiago Jung Bauermann 	/*
5903878d505SThiago Jung Bauermann 	 * modsig is a runtime structure containing pointers. Get its raw data
5913878d505SThiago Jung Bauermann 	 * instead.
5923878d505SThiago Jung Bauermann 	 */
5933878d505SThiago Jung Bauermann 	rc = ima_get_raw_modsig(event_data->modsig, &data, &data_len);
5943878d505SThiago Jung Bauermann 	if (rc)
5953878d505SThiago Jung Bauermann 		return rc;
5963878d505SThiago Jung Bauermann 
5973878d505SThiago Jung Bauermann 	return ima_write_template_field_data(data, data_len, DATA_FMT_HEX,
5983878d505SThiago Jung Bauermann 					     field_data);
5993878d505SThiago Jung Bauermann }
600026d7fc9SRoberto Sassu 
601026d7fc9SRoberto Sassu /*
602026d7fc9SRoberto Sassu  *  ima_eventevmsig_init - include the EVM portable signature as part of the
603026d7fc9SRoberto Sassu  *  template data
604026d7fc9SRoberto Sassu  */
ima_eventevmsig_init(struct ima_event_data * event_data,struct ima_field_data * field_data)605026d7fc9SRoberto Sassu int ima_eventevmsig_init(struct ima_event_data *event_data,
606026d7fc9SRoberto Sassu 			 struct ima_field_data *field_data)
607026d7fc9SRoberto Sassu {
608026d7fc9SRoberto Sassu 	struct evm_ima_xattr_data *xattr_data = NULL;
609026d7fc9SRoberto Sassu 	int rc = 0;
610026d7fc9SRoberto Sassu 
611026d7fc9SRoberto Sassu 	if (!event_data->file)
612026d7fc9SRoberto Sassu 		return 0;
613026d7fc9SRoberto Sassu 
6144609e1f1SChristian Brauner 	rc = vfs_getxattr_alloc(&nop_mnt_idmap, file_dentry(event_data->file),
615026d7fc9SRoberto Sassu 				XATTR_NAME_EVM, (char **)&xattr_data, 0,
616026d7fc9SRoberto Sassu 				GFP_NOFS);
617f6fbd8cbSPaul Moore 	if (rc <= 0 || xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG) {
618f6fbd8cbSPaul Moore 		rc = 0;
619f6fbd8cbSPaul Moore 		goto out;
620026d7fc9SRoberto Sassu 	}
621026d7fc9SRoberto Sassu 
622026d7fc9SRoberto Sassu 	rc = ima_write_template_field_data((char *)xattr_data, rc, DATA_FMT_HEX,
623026d7fc9SRoberto Sassu 					   field_data);
624f6fbd8cbSPaul Moore 
625f6fbd8cbSPaul Moore out:
626026d7fc9SRoberto Sassu 	kfree(xattr_data);
627026d7fc9SRoberto Sassu 	return rc;
628026d7fc9SRoberto Sassu }
6297dcfeaccSRoberto Sassu 
ima_eventinodedac_init_common(struct ima_event_data * event_data,struct ima_field_data * field_data,bool get_uid)6307dcfeaccSRoberto Sassu static int ima_eventinodedac_init_common(struct ima_event_data *event_data,
6317dcfeaccSRoberto Sassu 					 struct ima_field_data *field_data,
6327dcfeaccSRoberto Sassu 					 bool get_uid)
6337dcfeaccSRoberto Sassu {
6347dcfeaccSRoberto Sassu 	unsigned int id;
6357dcfeaccSRoberto Sassu 
6367dcfeaccSRoberto Sassu 	if (!event_data->file)
6377dcfeaccSRoberto Sassu 		return 0;
6387dcfeaccSRoberto Sassu 
6397dcfeaccSRoberto Sassu 	if (get_uid)
6407dcfeaccSRoberto Sassu 		id = i_uid_read(file_inode(event_data->file));
6417dcfeaccSRoberto Sassu 	else
6427dcfeaccSRoberto Sassu 		id = i_gid_read(file_inode(event_data->file));
6437dcfeaccSRoberto Sassu 
6447dcfeaccSRoberto Sassu 	if (ima_canonical_fmt) {
6457dcfeaccSRoberto Sassu 		if (sizeof(id) == sizeof(u16))
6466b26285fSRoberto Sassu 			id = (__force u16)cpu_to_le16(id);
6477dcfeaccSRoberto Sassu 		else
6486b26285fSRoberto Sassu 			id = (__force u32)cpu_to_le32(id);
6497dcfeaccSRoberto Sassu 	}
6507dcfeaccSRoberto Sassu 
6517dcfeaccSRoberto Sassu 	return ima_write_template_field_data((void *)&id, sizeof(id),
6527dcfeaccSRoberto Sassu 					     DATA_FMT_UINT, field_data);
6537dcfeaccSRoberto Sassu }
6547dcfeaccSRoberto Sassu 
6557dcfeaccSRoberto Sassu /*
6567dcfeaccSRoberto Sassu  *  ima_eventinodeuid_init - include the inode UID as part of the template
6577dcfeaccSRoberto Sassu  *  data
6587dcfeaccSRoberto Sassu  */
ima_eventinodeuid_init(struct ima_event_data * event_data,struct ima_field_data * field_data)6597dcfeaccSRoberto Sassu int ima_eventinodeuid_init(struct ima_event_data *event_data,
6607dcfeaccSRoberto Sassu 			   struct ima_field_data *field_data)
6617dcfeaccSRoberto Sassu {
6627dcfeaccSRoberto Sassu 	return ima_eventinodedac_init_common(event_data, field_data, true);
6637dcfeaccSRoberto Sassu }
6647dcfeaccSRoberto Sassu 
6657dcfeaccSRoberto Sassu /*
6667dcfeaccSRoberto Sassu  *  ima_eventinodegid_init - include the inode GID as part of the template
6677dcfeaccSRoberto Sassu  *  data
6687dcfeaccSRoberto Sassu  */
ima_eventinodegid_init(struct ima_event_data * event_data,struct ima_field_data * field_data)6697dcfeaccSRoberto Sassu int ima_eventinodegid_init(struct ima_event_data *event_data,
6707dcfeaccSRoberto Sassu 			   struct ima_field_data *field_data)
6717dcfeaccSRoberto Sassu {
6727dcfeaccSRoberto Sassu 	return ima_eventinodedac_init_common(event_data, field_data, false);
6737dcfeaccSRoberto Sassu }
674f8216f6bSRoberto Sassu 
675f8216f6bSRoberto Sassu /*
676f8216f6bSRoberto Sassu  *  ima_eventinodemode_init - include the inode mode as part of the template
677f8216f6bSRoberto Sassu  *  data
678f8216f6bSRoberto Sassu  */
ima_eventinodemode_init(struct ima_event_data * event_data,struct ima_field_data * field_data)679f8216f6bSRoberto Sassu int ima_eventinodemode_init(struct ima_event_data *event_data,
680f8216f6bSRoberto Sassu 			    struct ima_field_data *field_data)
681f8216f6bSRoberto Sassu {
682f8216f6bSRoberto Sassu 	struct inode *inode;
6836b26285fSRoberto Sassu 	u16 mode;
684f8216f6bSRoberto Sassu 
685f8216f6bSRoberto Sassu 	if (!event_data->file)
686f8216f6bSRoberto Sassu 		return 0;
687f8216f6bSRoberto Sassu 
688f8216f6bSRoberto Sassu 	inode = file_inode(event_data->file);
689f8216f6bSRoberto Sassu 	mode = inode->i_mode;
690f8216f6bSRoberto Sassu 	if (ima_canonical_fmt)
6916b26285fSRoberto Sassu 		mode = (__force u16)cpu_to_le16(mode);
692f8216f6bSRoberto Sassu 
693f8216f6bSRoberto Sassu 	return ima_write_template_field_data((char *)&mode, sizeof(mode),
694f8216f6bSRoberto Sassu 					     DATA_FMT_UINT, field_data);
695f8216f6bSRoberto Sassu }
6968314b673SRoberto Sassu 
ima_eventinodexattrs_init_common(struct ima_event_data * event_data,struct ima_field_data * field_data,char type)6978314b673SRoberto Sassu static int ima_eventinodexattrs_init_common(struct ima_event_data *event_data,
6988314b673SRoberto Sassu 					    struct ima_field_data *field_data,
6998314b673SRoberto Sassu 					    char type)
7008314b673SRoberto Sassu {
7018314b673SRoberto Sassu 	u8 *buffer = NULL;
7028314b673SRoberto Sassu 	int rc;
7038314b673SRoberto Sassu 
7048314b673SRoberto Sassu 	if (!event_data->file)
7058314b673SRoberto Sassu 		return 0;
7068314b673SRoberto Sassu 
7078314b673SRoberto Sassu 	rc = evm_read_protected_xattrs(file_dentry(event_data->file), NULL, 0,
7088314b673SRoberto Sassu 				       type, ima_canonical_fmt);
7098314b673SRoberto Sassu 	if (rc < 0)
7108314b673SRoberto Sassu 		return 0;
7118314b673SRoberto Sassu 
7128314b673SRoberto Sassu 	buffer = kmalloc(rc, GFP_KERNEL);
7138314b673SRoberto Sassu 	if (!buffer)
7148314b673SRoberto Sassu 		return 0;
7158314b673SRoberto Sassu 
7168314b673SRoberto Sassu 	rc = evm_read_protected_xattrs(file_dentry(event_data->file), buffer,
7178314b673SRoberto Sassu 				       rc, type, ima_canonical_fmt);
7188314b673SRoberto Sassu 	if (rc < 0) {
7198314b673SRoberto Sassu 		rc = 0;
7208314b673SRoberto Sassu 		goto out;
7218314b673SRoberto Sassu 	}
7228314b673SRoberto Sassu 
7238314b673SRoberto Sassu 	rc = ima_write_template_field_data((char *)buffer, rc, DATA_FMT_HEX,
7248314b673SRoberto Sassu 					   field_data);
7258314b673SRoberto Sassu out:
7268314b673SRoberto Sassu 	kfree(buffer);
7278314b673SRoberto Sassu 	return rc;
7288314b673SRoberto Sassu }
7298314b673SRoberto Sassu 
7308314b673SRoberto Sassu /*
7318314b673SRoberto Sassu  *  ima_eventinodexattrnames_init - include a list of xattr names as part of the
7328314b673SRoberto Sassu  *  template data
7338314b673SRoberto Sassu  */
ima_eventinodexattrnames_init(struct ima_event_data * event_data,struct ima_field_data * field_data)7348314b673SRoberto Sassu int ima_eventinodexattrnames_init(struct ima_event_data *event_data,
7358314b673SRoberto Sassu 				  struct ima_field_data *field_data)
7368314b673SRoberto Sassu {
7378314b673SRoberto Sassu 	return ima_eventinodexattrs_init_common(event_data, field_data, 'n');
7388314b673SRoberto Sassu }
7398314b673SRoberto Sassu 
7408314b673SRoberto Sassu /*
7418314b673SRoberto Sassu  *  ima_eventinodexattrlengths_init - include a list of xattr lengths as part of
7428314b673SRoberto Sassu  *  the template data
7438314b673SRoberto Sassu  */
ima_eventinodexattrlengths_init(struct ima_event_data * event_data,struct ima_field_data * field_data)7448314b673SRoberto Sassu int ima_eventinodexattrlengths_init(struct ima_event_data *event_data,
7458314b673SRoberto Sassu 				    struct ima_field_data *field_data)
7468314b673SRoberto Sassu {
7478314b673SRoberto Sassu 	return ima_eventinodexattrs_init_common(event_data, field_data, 'l');
7488314b673SRoberto Sassu }
7498314b673SRoberto Sassu 
7508314b673SRoberto Sassu /*
7518314b673SRoberto Sassu  *  ima_eventinodexattrvalues_init - include a list of xattr values as part of
7528314b673SRoberto Sassu  *  the template data
7538314b673SRoberto Sassu  */
ima_eventinodexattrvalues_init(struct ima_event_data * event_data,struct ima_field_data * field_data)7548314b673SRoberto Sassu int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
7558314b673SRoberto Sassu 				   struct ima_field_data *field_data)
7568314b673SRoberto Sassu {
7578314b673SRoberto Sassu 	return ima_eventinodexattrs_init_common(event_data, field_data, 'v');
7588314b673SRoberto Sassu }
759