~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/integrity/ima/ima_fs.c

Version: ~ [ linux-5.15-rc6 ] ~ [ linux-5.14.14 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.75 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.155 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.213 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.252 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.287 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.289 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp