xref: /OK3568_Linux_fs/kernel/security/integrity/ima/ima_fs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2005,2006,2007,2008 IBM Corporation
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Authors:
6*4882a593Smuzhiyun  * Kylene Hall <kjhall@us.ibm.com>
7*4882a593Smuzhiyun  * Reiner Sailer <sailer@us.ibm.com>
8*4882a593Smuzhiyun  * Mimi Zohar <zohar@us.ibm.com>
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * File: ima_fs.c
11*4882a593Smuzhiyun  *	implemenents security file system for reporting
12*4882a593Smuzhiyun  *	current measurement list and IMA statistics
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/fcntl.h>
16*4882a593Smuzhiyun #include <linux/kernel_read_file.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun #include <linux/init.h>
19*4882a593Smuzhiyun #include <linux/seq_file.h>
20*4882a593Smuzhiyun #include <linux/rculist.h>
21*4882a593Smuzhiyun #include <linux/rcupdate.h>
22*4882a593Smuzhiyun #include <linux/parser.h>
23*4882a593Smuzhiyun #include <linux/vmalloc.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include "ima.h"
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun static DEFINE_MUTEX(ima_write_mutex);
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun bool ima_canonical_fmt;
default_canonical_fmt_setup(char * str)30*4882a593Smuzhiyun static int __init default_canonical_fmt_setup(char *str)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
33*4882a593Smuzhiyun 	ima_canonical_fmt = true;
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun 	return 1;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun __setup("ima_canonical_fmt", default_canonical_fmt_setup);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun static int valid_policy = 1;
40*4882a593Smuzhiyun 
ima_show_htable_value(char __user * buf,size_t count,loff_t * ppos,atomic_long_t * val)41*4882a593Smuzhiyun static ssize_t ima_show_htable_value(char __user *buf, size_t count,
42*4882a593Smuzhiyun 				     loff_t *ppos, atomic_long_t *val)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	char tmpbuf[32];	/* greater than largest 'long' string value */
45*4882a593Smuzhiyun 	ssize_t len;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", atomic_long_read(val));
48*4882a593Smuzhiyun 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
ima_show_htable_violations(struct file * filp,char __user * buf,size_t count,loff_t * ppos)51*4882a593Smuzhiyun static ssize_t ima_show_htable_violations(struct file *filp,
52*4882a593Smuzhiyun 					  char __user *buf,
53*4882a593Smuzhiyun 					  size_t count, loff_t *ppos)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static const struct file_operations ima_htable_violations_ops = {
59*4882a593Smuzhiyun 	.read = ima_show_htable_violations,
60*4882a593Smuzhiyun 	.llseek = generic_file_llseek,
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
ima_show_measurements_count(struct file * filp,char __user * buf,size_t count,loff_t * ppos)63*4882a593Smuzhiyun static ssize_t ima_show_measurements_count(struct file *filp,
64*4882a593Smuzhiyun 					   char __user *buf,
65*4882a593Smuzhiyun 					   size_t count, loff_t *ppos)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	return ima_show_htable_value(buf, count, ppos, &ima_htable.len);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static const struct file_operations ima_measurements_count_ops = {
72*4882a593Smuzhiyun 	.read = ima_show_measurements_count,
73*4882a593Smuzhiyun 	.llseek = generic_file_llseek,
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /* returns pointer to hlist_node */
ima_measurements_start(struct seq_file * m,loff_t * pos)77*4882a593Smuzhiyun static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	loff_t l = *pos;
80*4882a593Smuzhiyun 	struct ima_queue_entry *qe;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	/* we need a lock since pos could point beyond last element */
83*4882a593Smuzhiyun 	rcu_read_lock();
84*4882a593Smuzhiyun 	list_for_each_entry_rcu(qe, &ima_measurements, later) {
85*4882a593Smuzhiyun 		if (!l--) {
86*4882a593Smuzhiyun 			rcu_read_unlock();
87*4882a593Smuzhiyun 			return qe;
88*4882a593Smuzhiyun 		}
89*4882a593Smuzhiyun 	}
90*4882a593Smuzhiyun 	rcu_read_unlock();
91*4882a593Smuzhiyun 	return NULL;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
ima_measurements_next(struct seq_file * m,void * v,loff_t * pos)94*4882a593Smuzhiyun static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct ima_queue_entry *qe = v;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	/* lock protects when reading beyond last element
99*4882a593Smuzhiyun 	 * against concurrent list-extension
100*4882a593Smuzhiyun 	 */
101*4882a593Smuzhiyun 	rcu_read_lock();
102*4882a593Smuzhiyun 	qe = list_entry_rcu(qe->later.next, struct ima_queue_entry, later);
103*4882a593Smuzhiyun 	rcu_read_unlock();
104*4882a593Smuzhiyun 	(*pos)++;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	return (&qe->later == &ima_measurements) ? NULL : qe;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
ima_measurements_stop(struct seq_file * m,void * v)109*4882a593Smuzhiyun static void ima_measurements_stop(struct seq_file *m, void *v)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
ima_putc(struct seq_file * m,void * data,int datalen)113*4882a593Smuzhiyun void ima_putc(struct seq_file *m, void *data, int datalen)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	while (datalen--)
116*4882a593Smuzhiyun 		seq_putc(m, *(char *)data++);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /* print format:
120*4882a593Smuzhiyun  *       32bit-le=pcr#
121*4882a593Smuzhiyun  *       char[20]=template digest
122*4882a593Smuzhiyun  *       32bit-le=template name size
123*4882a593Smuzhiyun  *       char[n]=template name
124*4882a593Smuzhiyun  *       [eventdata length]
125*4882a593Smuzhiyun  *       eventdata[n]=template specific data
126*4882a593Smuzhiyun  */
ima_measurements_show(struct seq_file * m,void * v)127*4882a593Smuzhiyun int ima_measurements_show(struct seq_file *m, void *v)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	/* the list never shrinks, so we don't need a lock here */
130*4882a593Smuzhiyun 	struct ima_queue_entry *qe = v;
131*4882a593Smuzhiyun 	struct ima_template_entry *e;
132*4882a593Smuzhiyun 	char *template_name;
133*4882a593Smuzhiyun 	u32 pcr, namelen, template_data_len; /* temporary fields */
134*4882a593Smuzhiyun 	bool is_ima_template = false;
135*4882a593Smuzhiyun 	int i;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/* get entry */
138*4882a593Smuzhiyun 	e = qe->entry;
139*4882a593Smuzhiyun 	if (e == NULL)
140*4882a593Smuzhiyun 		return -1;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	template_name = (e->template_desc->name[0] != '\0') ?
143*4882a593Smuzhiyun 	    e->template_desc->name : e->template_desc->fmt;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	/*
146*4882a593Smuzhiyun 	 * 1st: PCRIndex
147*4882a593Smuzhiyun 	 * PCR used defaults to the same (config option) in
148*4882a593Smuzhiyun 	 * little-endian format, unless set in policy
149*4882a593Smuzhiyun 	 */
150*4882a593Smuzhiyun 	pcr = !ima_canonical_fmt ? e->pcr : cpu_to_le32(e->pcr);
151*4882a593Smuzhiyun 	ima_putc(m, &pcr, sizeof(e->pcr));
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	/* 2nd: template digest */
154*4882a593Smuzhiyun 	ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	/* 3rd: template name size */
157*4882a593Smuzhiyun 	namelen = !ima_canonical_fmt ? strlen(template_name) :
158*4882a593Smuzhiyun 		cpu_to_le32(strlen(template_name));
159*4882a593Smuzhiyun 	ima_putc(m, &namelen, sizeof(namelen));
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	/* 4th:  template name */
162*4882a593Smuzhiyun 	ima_putc(m, template_name, strlen(template_name));
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	/* 5th:  template length (except for 'ima' template) */
165*4882a593Smuzhiyun 	if (strcmp(template_name, IMA_TEMPLATE_IMA_NAME) == 0)
166*4882a593Smuzhiyun 		is_ima_template = true;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	if (!is_ima_template) {
169*4882a593Smuzhiyun 		template_data_len = !ima_canonical_fmt ? e->template_data_len :
170*4882a593Smuzhiyun 			cpu_to_le32(e->template_data_len);
171*4882a593Smuzhiyun 		ima_putc(m, &template_data_len, sizeof(e->template_data_len));
172*4882a593Smuzhiyun 	}
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	/* 6th:  template specific data */
175*4882a593Smuzhiyun 	for (i = 0; i < e->template_desc->num_fields; i++) {
176*4882a593Smuzhiyun 		enum ima_show_type show = IMA_SHOW_BINARY;
177*4882a593Smuzhiyun 		const struct ima_template_field *field =
178*4882a593Smuzhiyun 			e->template_desc->fields[i];
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 		if (is_ima_template && strcmp(field->field_id, "d") == 0)
181*4882a593Smuzhiyun 			show = IMA_SHOW_BINARY_NO_FIELD_LEN;
182*4882a593Smuzhiyun 		if (is_ima_template && strcmp(field->field_id, "n") == 0)
183*4882a593Smuzhiyun 			show = IMA_SHOW_BINARY_OLD_STRING_FMT;
184*4882a593Smuzhiyun 		field->field_show(m, show, &e->template_data[i]);
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun 	return 0;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun static const struct seq_operations ima_measurments_seqops = {
190*4882a593Smuzhiyun 	.start = ima_measurements_start,
191*4882a593Smuzhiyun 	.next = ima_measurements_next,
192*4882a593Smuzhiyun 	.stop = ima_measurements_stop,
193*4882a593Smuzhiyun 	.show = ima_measurements_show
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun 
ima_measurements_open(struct inode * inode,struct file * file)196*4882a593Smuzhiyun static int ima_measurements_open(struct inode *inode, struct file *file)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	return seq_open(file, &ima_measurments_seqops);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun static const struct file_operations ima_measurements_ops = {
202*4882a593Smuzhiyun 	.open = ima_measurements_open,
203*4882a593Smuzhiyun 	.read = seq_read,
204*4882a593Smuzhiyun 	.llseek = seq_lseek,
205*4882a593Smuzhiyun 	.release = seq_release,
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun 
ima_print_digest(struct seq_file * m,u8 * digest,u32 size)208*4882a593Smuzhiyun void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	u32 i;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	for (i = 0; i < size; i++)
213*4882a593Smuzhiyun 		seq_printf(m, "%02x", *(digest + i));
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun /* print in ascii */
ima_ascii_measurements_show(struct seq_file * m,void * v)217*4882a593Smuzhiyun static int ima_ascii_measurements_show(struct seq_file *m, void *v)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	/* the list never shrinks, so we don't need a lock here */
220*4882a593Smuzhiyun 	struct ima_queue_entry *qe = v;
221*4882a593Smuzhiyun 	struct ima_template_entry *e;
222*4882a593Smuzhiyun 	char *template_name;
223*4882a593Smuzhiyun 	int i;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	/* get entry */
226*4882a593Smuzhiyun 	e = qe->entry;
227*4882a593Smuzhiyun 	if (e == NULL)
228*4882a593Smuzhiyun 		return -1;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	template_name = (e->template_desc->name[0] != '\0') ?
231*4882a593Smuzhiyun 	    e->template_desc->name : e->template_desc->fmt;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	/* 1st: PCR used (config option) */
234*4882a593Smuzhiyun 	seq_printf(m, "%2d ", e->pcr);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	/* 2nd: SHA1 template hash */
237*4882a593Smuzhiyun 	ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/* 3th:  template name */
240*4882a593Smuzhiyun 	seq_printf(m, " %s", template_name);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	/* 4th:  template specific data */
243*4882a593Smuzhiyun 	for (i = 0; i < e->template_desc->num_fields; i++) {
244*4882a593Smuzhiyun 		seq_puts(m, " ");
245*4882a593Smuzhiyun 		if (e->template_data[i].len == 0)
246*4882a593Smuzhiyun 			continue;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 		e->template_desc->fields[i]->field_show(m, IMA_SHOW_ASCII,
249*4882a593Smuzhiyun 							&e->template_data[i]);
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun 	seq_puts(m, "\n");
252*4882a593Smuzhiyun 	return 0;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static const struct seq_operations ima_ascii_measurements_seqops = {
256*4882a593Smuzhiyun 	.start = ima_measurements_start,
257*4882a593Smuzhiyun 	.next = ima_measurements_next,
258*4882a593Smuzhiyun 	.stop = ima_measurements_stop,
259*4882a593Smuzhiyun 	.show = ima_ascii_measurements_show
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun 
ima_ascii_measurements_open(struct inode * inode,struct file * file)262*4882a593Smuzhiyun static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	return seq_open(file, &ima_ascii_measurements_seqops);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun static const struct file_operations ima_ascii_measurements_ops = {
268*4882a593Smuzhiyun 	.open = ima_ascii_measurements_open,
269*4882a593Smuzhiyun 	.read = seq_read,
270*4882a593Smuzhiyun 	.llseek = seq_lseek,
271*4882a593Smuzhiyun 	.release = seq_release,
272*4882a593Smuzhiyun };
273*4882a593Smuzhiyun 
ima_read_policy(char * path)274*4882a593Smuzhiyun static ssize_t ima_read_policy(char *path)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	void *data = NULL;
277*4882a593Smuzhiyun 	char *datap;
278*4882a593Smuzhiyun 	size_t size;
279*4882a593Smuzhiyun 	int rc, pathlen = strlen(path);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	char *p;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	/* remove \n */
284*4882a593Smuzhiyun 	datap = path;
285*4882a593Smuzhiyun 	strsep(&datap, "\n");
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	rc = kernel_read_file_from_path(path, 0, &data, INT_MAX, NULL,
288*4882a593Smuzhiyun 					READING_POLICY);
289*4882a593Smuzhiyun 	if (rc < 0) {
290*4882a593Smuzhiyun 		pr_err("Unable to open file: %s (%d)", path, rc);
291*4882a593Smuzhiyun 		return rc;
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 	size = rc;
294*4882a593Smuzhiyun 	rc = 0;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	datap = data;
297*4882a593Smuzhiyun 	while (size > 0 && (p = strsep(&datap, "\n"))) {
298*4882a593Smuzhiyun 		pr_debug("rule: %s\n", p);
299*4882a593Smuzhiyun 		rc = ima_parse_add_rule(p);
300*4882a593Smuzhiyun 		if (rc < 0)
301*4882a593Smuzhiyun 			break;
302*4882a593Smuzhiyun 		size -= rc;
303*4882a593Smuzhiyun 	}
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	vfree(data);
306*4882a593Smuzhiyun 	if (rc < 0)
307*4882a593Smuzhiyun 		return rc;
308*4882a593Smuzhiyun 	else if (size)
309*4882a593Smuzhiyun 		return -EINVAL;
310*4882a593Smuzhiyun 	else
311*4882a593Smuzhiyun 		return pathlen;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
ima_write_policy(struct file * file,const char __user * buf,size_t datalen,loff_t * ppos)314*4882a593Smuzhiyun static ssize_t ima_write_policy(struct file *file, const char __user *buf,
315*4882a593Smuzhiyun 				size_t datalen, loff_t *ppos)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun 	char *data;
318*4882a593Smuzhiyun 	ssize_t result;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	if (datalen >= PAGE_SIZE)
321*4882a593Smuzhiyun 		datalen = PAGE_SIZE - 1;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	/* No partial writes. */
324*4882a593Smuzhiyun 	result = -EINVAL;
325*4882a593Smuzhiyun 	if (*ppos != 0)
326*4882a593Smuzhiyun 		goto out;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	data = memdup_user_nul(buf, datalen);
329*4882a593Smuzhiyun 	if (IS_ERR(data)) {
330*4882a593Smuzhiyun 		result = PTR_ERR(data);
331*4882a593Smuzhiyun 		goto out;
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	result = mutex_lock_interruptible(&ima_write_mutex);
335*4882a593Smuzhiyun 	if (result < 0)
336*4882a593Smuzhiyun 		goto out_free;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (data[0] == '/') {
339*4882a593Smuzhiyun 		result = ima_read_policy(data);
340*4882a593Smuzhiyun 	} else if (ima_appraise & IMA_APPRAISE_POLICY) {
341*4882a593Smuzhiyun 		pr_err("signed policy file (specified as an absolute pathname) required\n");
342*4882a593Smuzhiyun 		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
343*4882a593Smuzhiyun 				    "policy_update", "signed policy required",
344*4882a593Smuzhiyun 				    1, 0);
345*4882a593Smuzhiyun 		result = -EACCES;
346*4882a593Smuzhiyun 	} else {
347*4882a593Smuzhiyun 		result = ima_parse_add_rule(data);
348*4882a593Smuzhiyun 	}
349*4882a593Smuzhiyun 	mutex_unlock(&ima_write_mutex);
350*4882a593Smuzhiyun out_free:
351*4882a593Smuzhiyun 	kfree(data);
352*4882a593Smuzhiyun out:
353*4882a593Smuzhiyun 	if (result < 0)
354*4882a593Smuzhiyun 		valid_policy = 0;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	return result;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun static struct dentry *ima_dir;
360*4882a593Smuzhiyun static struct dentry *ima_symlink;
361*4882a593Smuzhiyun static struct dentry *binary_runtime_measurements;
362*4882a593Smuzhiyun static struct dentry *ascii_runtime_measurements;
363*4882a593Smuzhiyun static struct dentry *runtime_measurements_count;
364*4882a593Smuzhiyun static struct dentry *violations;
365*4882a593Smuzhiyun static struct dentry *ima_policy;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun enum ima_fs_flags {
368*4882a593Smuzhiyun 	IMA_FS_BUSY,
369*4882a593Smuzhiyun };
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun static unsigned long ima_fs_flags;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun #ifdef	CONFIG_IMA_READ_POLICY
374*4882a593Smuzhiyun static const struct seq_operations ima_policy_seqops = {
375*4882a593Smuzhiyun 		.start = ima_policy_start,
376*4882a593Smuzhiyun 		.next = ima_policy_next,
377*4882a593Smuzhiyun 		.stop = ima_policy_stop,
378*4882a593Smuzhiyun 		.show = ima_policy_show,
379*4882a593Smuzhiyun };
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun /*
383*4882a593Smuzhiyun  * ima_open_policy: sequentialize access to the policy file
384*4882a593Smuzhiyun  */
ima_open_policy(struct inode * inode,struct file * filp)385*4882a593Smuzhiyun static int ima_open_policy(struct inode *inode, struct file *filp)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	if (!(filp->f_flags & O_WRONLY)) {
388*4882a593Smuzhiyun #ifndef	CONFIG_IMA_READ_POLICY
389*4882a593Smuzhiyun 		return -EACCES;
390*4882a593Smuzhiyun #else
391*4882a593Smuzhiyun 		if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
392*4882a593Smuzhiyun 			return -EACCES;
393*4882a593Smuzhiyun 		if (!capable(CAP_SYS_ADMIN))
394*4882a593Smuzhiyun 			return -EPERM;
395*4882a593Smuzhiyun 		return seq_open(filp, &ima_policy_seqops);
396*4882a593Smuzhiyun #endif
397*4882a593Smuzhiyun 	}
398*4882a593Smuzhiyun 	if (test_and_set_bit(IMA_FS_BUSY, &ima_fs_flags))
399*4882a593Smuzhiyun 		return -EBUSY;
400*4882a593Smuzhiyun 	return 0;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun /*
404*4882a593Smuzhiyun  * ima_release_policy - start using the new measure policy rules.
405*4882a593Smuzhiyun  *
406*4882a593Smuzhiyun  * Initially, ima_measure points to the default policy rules, now
407*4882a593Smuzhiyun  * point to the new policy rules, and remove the securityfs policy file,
408*4882a593Smuzhiyun  * assuming a valid policy.
409*4882a593Smuzhiyun  */
ima_release_policy(struct inode * inode,struct file * file)410*4882a593Smuzhiyun static int ima_release_policy(struct inode *inode, struct file *file)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	const char *cause = valid_policy ? "completed" : "failed";
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
415*4882a593Smuzhiyun 		return seq_release(inode, file);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	if (valid_policy && ima_check_policy() < 0) {
418*4882a593Smuzhiyun 		cause = "failed";
419*4882a593Smuzhiyun 		valid_policy = 0;
420*4882a593Smuzhiyun 	}
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	pr_info("policy update %s\n", cause);
423*4882a593Smuzhiyun 	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
424*4882a593Smuzhiyun 			    "policy_update", cause, !valid_policy, 0);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	if (!valid_policy) {
427*4882a593Smuzhiyun 		ima_delete_rules();
428*4882a593Smuzhiyun 		valid_policy = 1;
429*4882a593Smuzhiyun 		clear_bit(IMA_FS_BUSY, &ima_fs_flags);
430*4882a593Smuzhiyun 		return 0;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	ima_update_policy();
434*4882a593Smuzhiyun #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY)
435*4882a593Smuzhiyun 	securityfs_remove(ima_policy);
436*4882a593Smuzhiyun 	ima_policy = NULL;
437*4882a593Smuzhiyun #elif defined(CONFIG_IMA_WRITE_POLICY)
438*4882a593Smuzhiyun 	clear_bit(IMA_FS_BUSY, &ima_fs_flags);
439*4882a593Smuzhiyun #elif defined(CONFIG_IMA_READ_POLICY)
440*4882a593Smuzhiyun 	inode->i_mode &= ~S_IWUSR;
441*4882a593Smuzhiyun #endif
442*4882a593Smuzhiyun 	return 0;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun static const struct file_operations ima_measure_policy_ops = {
446*4882a593Smuzhiyun 	.open = ima_open_policy,
447*4882a593Smuzhiyun 	.write = ima_write_policy,
448*4882a593Smuzhiyun 	.read = seq_read,
449*4882a593Smuzhiyun 	.release = ima_release_policy,
450*4882a593Smuzhiyun 	.llseek = generic_file_llseek,
451*4882a593Smuzhiyun };
452*4882a593Smuzhiyun 
ima_fs_init(void)453*4882a593Smuzhiyun int __init ima_fs_init(void)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	ima_dir = securityfs_create_dir("ima", integrity_dir);
456*4882a593Smuzhiyun 	if (IS_ERR(ima_dir))
457*4882a593Smuzhiyun 		return -1;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	ima_symlink = securityfs_create_symlink("ima", NULL, "integrity/ima",
460*4882a593Smuzhiyun 						NULL);
461*4882a593Smuzhiyun 	if (IS_ERR(ima_symlink))
462*4882a593Smuzhiyun 		goto out;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	binary_runtime_measurements =
465*4882a593Smuzhiyun 	    securityfs_create_file("binary_runtime_measurements",
466*4882a593Smuzhiyun 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
467*4882a593Smuzhiyun 				   &ima_measurements_ops);
468*4882a593Smuzhiyun 	if (IS_ERR(binary_runtime_measurements))
469*4882a593Smuzhiyun 		goto out;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	ascii_runtime_measurements =
472*4882a593Smuzhiyun 	    securityfs_create_file("ascii_runtime_measurements",
473*4882a593Smuzhiyun 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
474*4882a593Smuzhiyun 				   &ima_ascii_measurements_ops);
475*4882a593Smuzhiyun 	if (IS_ERR(ascii_runtime_measurements))
476*4882a593Smuzhiyun 		goto out;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	runtime_measurements_count =
479*4882a593Smuzhiyun 	    securityfs_create_file("runtime_measurements_count",
480*4882a593Smuzhiyun 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
481*4882a593Smuzhiyun 				   &ima_measurements_count_ops);
482*4882a593Smuzhiyun 	if (IS_ERR(runtime_measurements_count))
483*4882a593Smuzhiyun 		goto out;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	violations =
486*4882a593Smuzhiyun 	    securityfs_create_file("violations", S_IRUSR | S_IRGRP,
487*4882a593Smuzhiyun 				   ima_dir, NULL, &ima_htable_violations_ops);
488*4882a593Smuzhiyun 	if (IS_ERR(violations))
489*4882a593Smuzhiyun 		goto out;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	ima_policy = securityfs_create_file("policy", POLICY_FILE_FLAGS,
492*4882a593Smuzhiyun 					    ima_dir, NULL,
493*4882a593Smuzhiyun 					    &ima_measure_policy_ops);
494*4882a593Smuzhiyun 	if (IS_ERR(ima_policy))
495*4882a593Smuzhiyun 		goto out;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	return 0;
498*4882a593Smuzhiyun out:
499*4882a593Smuzhiyun 	securityfs_remove(ima_policy);
500*4882a593Smuzhiyun 	securityfs_remove(violations);
501*4882a593Smuzhiyun 	securityfs_remove(runtime_measurements_count);
502*4882a593Smuzhiyun 	securityfs_remove(ascii_runtime_measurements);
503*4882a593Smuzhiyun 	securityfs_remove(binary_runtime_measurements);
504*4882a593Smuzhiyun 	securityfs_remove(ima_symlink);
505*4882a593Smuzhiyun 	securityfs_remove(ima_dir);
506*4882a593Smuzhiyun 	return -1;
507*4882a593Smuzhiyun }
508