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