linux/security/integrity/ima/ima_fs.c
<<
>>
Prefs
   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/module.h>
  20#include <linux/seq_file.h>
  21#include <linux/rculist.h>
  22#include <linux/rcupdate.h>
  23#include <linux/parser.h>
  24
  25#include "ima.h"
  26
  27static int valid_policy = 1;
  28#define TMPBUFLEN 12
  29static ssize_t ima_show_htable_value(char __user *buf, size_t count,
  30                                     loff_t *ppos, atomic_long_t *val)
  31{
  32        char tmpbuf[TMPBUFLEN];
  33        ssize_t len;
  34
  35        len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
  36        return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
  37}
  38
  39static ssize_t ima_show_htable_violations(struct file *filp,
  40                                          char __user *buf,
  41                                          size_t count, loff_t *ppos)
  42{
  43        return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
  44}
  45
  46static const struct file_operations ima_htable_violations_ops = {
  47        .read = ima_show_htable_violations
  48};
  49
  50static ssize_t ima_show_measurements_count(struct file *filp,
  51                                           char __user *buf,
  52                                           size_t count, loff_t *ppos)
  53{
  54        return ima_show_htable_value(buf, count, ppos, &ima_htable.len);
  55
  56}
  57
  58static const struct file_operations ima_measurements_count_ops = {
  59        .read = ima_show_measurements_count
  60};
  61
  62/* returns pointer to hlist_node */
  63static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
  64{
  65        loff_t l = *pos;
  66        struct ima_queue_entry *qe;
  67
  68        /* we need a lock since pos could point beyond last element */
  69        rcu_read_lock();
  70        list_for_each_entry_rcu(qe, &ima_measurements, later) {
  71                if (!l--) {
  72                        rcu_read_unlock();
  73                        return qe;
  74                }
  75        }
  76        rcu_read_unlock();
  77        return NULL;
  78}
  79
  80static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
  81{
  82        struct ima_queue_entry *qe = v;
  83
  84        /* lock protects when reading beyond last element
  85         * against concurrent list-extension
  86         */
  87        rcu_read_lock();
  88        qe = list_entry_rcu(qe->later.next,
  89                            struct ima_queue_entry, later);
  90        rcu_read_unlock();
  91        (*pos)++;
  92
  93        return (&qe->later == &ima_measurements) ? NULL : qe;
  94}
  95
  96static void ima_measurements_stop(struct seq_file *m, void *v)
  97{
  98}
  99
 100static void ima_putc(struct seq_file *m, void *data, int datalen)
 101{
 102        while (datalen--)
 103                seq_putc(m, *(char *)data++);
 104}
 105
 106/* print format:
 107 *       32bit-le=pcr#
 108 *       char[20]=template digest
 109 *       32bit-le=template name size
 110 *       char[n]=template name
 111 *       eventdata[n]=template specific data
 112 */
 113static int ima_measurements_show(struct seq_file *m, void *v)
 114{
 115        /* the list never shrinks, so we don't need a lock here */
 116        struct ima_queue_entry *qe = v;
 117        struct ima_template_entry *e;
 118        int namelen;
 119        u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
 120
 121        /* get entry */
 122        e = qe->entry;
 123        if (e == NULL)
 124                return -1;
 125
 126        /*
 127         * 1st: PCRIndex
 128         * PCR used is always the same (config option) in
 129         * little-endian format
 130         */
 131        ima_putc(m, &pcr, sizeof pcr);
 132
 133        /* 2nd: template digest */
 134        ima_putc(m, e->digest, IMA_DIGEST_SIZE);
 135
 136        /* 3rd: template name size */
 137        namelen = strlen(e->template_name);
 138        ima_putc(m, &namelen, sizeof namelen);
 139
 140        /* 4th:  template name */
 141        ima_putc(m, (void *)e->template_name, namelen);
 142
 143        /* 5th:  template specific data */
 144        ima_template_show(m, (struct ima_template_data *)&e->template,
 145                          IMA_SHOW_BINARY);
 146        return 0;
 147}
 148
 149static const struct seq_operations ima_measurments_seqops = {
 150        .start = ima_measurements_start,
 151        .next = ima_measurements_next,
 152        .stop = ima_measurements_stop,
 153        .show = ima_measurements_show
 154};
 155
 156static int ima_measurements_open(struct inode *inode, struct file *file)
 157{
 158        return seq_open(file, &ima_measurments_seqops);
 159}
 160
 161static const struct file_operations ima_measurements_ops = {
 162        .open = ima_measurements_open,
 163        .read = seq_read,
 164        .llseek = seq_lseek,
 165        .release = seq_release,
 166};
 167
 168static void ima_print_digest(struct seq_file *m, u8 *digest)
 169{
 170        int i;
 171
 172        for (i = 0; i < IMA_DIGEST_SIZE; i++)
 173                seq_printf(m, "%02x", *(digest + i));
 174}
 175
 176void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
 177{
 178        struct ima_template_data *entry = e;
 179        int namelen;
 180
 181        switch (show) {
 182        case IMA_SHOW_ASCII:
 183                ima_print_digest(m, entry->digest);
 184                seq_printf(m, " %s\n", entry->file_name);
 185                break;
 186        case IMA_SHOW_BINARY:
 187                ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
 188
 189                namelen = strlen(entry->file_name);
 190                ima_putc(m, &namelen, sizeof namelen);
 191                ima_putc(m, entry->file_name, namelen);
 192        default:
 193                break;
 194        }
 195}
 196
 197/* print in ascii */
 198static int ima_ascii_measurements_show(struct seq_file *m, void *v)
 199{
 200        /* the list never shrinks, so we don't need a lock here */
 201        struct ima_queue_entry *qe = v;
 202        struct ima_template_entry *e;
 203
 204        /* get entry */
 205        e = qe->entry;
 206        if (e == NULL)
 207                return -1;
 208
 209        /* 1st: PCR used (config option) */
 210        seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
 211
 212        /* 2nd: SHA1 template hash */
 213        ima_print_digest(m, e->digest);
 214
 215        /* 3th:  template name */
 216        seq_printf(m, " %s ", e->template_name);
 217
 218        /* 4th:  template specific data */
 219        ima_template_show(m, (struct ima_template_data *)&e->template,
 220                          IMA_SHOW_ASCII);
 221        return 0;
 222}
 223
 224static const struct seq_operations ima_ascii_measurements_seqops = {
 225        .start = ima_measurements_start,
 226        .next = ima_measurements_next,
 227        .stop = ima_measurements_stop,
 228        .show = ima_ascii_measurements_show
 229};
 230
 231static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
 232{
 233        return seq_open(file, &ima_ascii_measurements_seqops);
 234}
 235
 236static const struct file_operations ima_ascii_measurements_ops = {
 237        .open = ima_ascii_measurements_open,
 238        .read = seq_read,
 239        .llseek = seq_lseek,
 240        .release = seq_release,
 241};
 242
 243static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 244                                size_t datalen, loff_t *ppos)
 245{
 246        char *data;
 247        int rc;
 248
 249        if (datalen >= PAGE_SIZE)
 250                return -ENOMEM;
 251        if (*ppos != 0) {
 252                /* No partial writes. */
 253                return -EINVAL;
 254        }
 255        data = kmalloc(datalen + 1, GFP_KERNEL);
 256        if (!data)
 257                return -ENOMEM;
 258
 259        if (copy_from_user(data, buf, datalen)) {
 260                kfree(data);
 261                return -EFAULT;
 262        }
 263        *(data + datalen) = '\0';
 264        rc = ima_parse_add_rule(data);
 265        if (rc < 0) {
 266                datalen = -EINVAL;
 267                valid_policy = 0;
 268        }
 269
 270        kfree(data);
 271        return datalen;
 272}
 273
 274static struct dentry *ima_dir;
 275static struct dentry *binary_runtime_measurements;
 276static struct dentry *ascii_runtime_measurements;
 277static struct dentry *runtime_measurements_count;
 278static struct dentry *violations;
 279static struct dentry *ima_policy;
 280
 281static atomic_t policy_opencount = ATOMIC_INIT(1);
 282/*
 283 * ima_open_policy: sequentialize access to the policy file
 284 */
 285int ima_open_policy(struct inode * inode, struct file * filp)
 286{
 287        /* No point in being allowed to open it if you aren't going to write */
 288        if (!(filp->f_flags & O_WRONLY))
 289                return -EACCES;
 290        if (atomic_dec_and_test(&policy_opencount))
 291                return 0;
 292        return -EBUSY;
 293}
 294
 295/*
 296 * ima_release_policy - start using the new measure policy rules.
 297 *
 298 * Initially, ima_measure points to the default policy rules, now
 299 * point to the new policy rules, and remove the securityfs policy file,
 300 * assuming a valid policy.
 301 */
 302static int ima_release_policy(struct inode *inode, struct file *file)
 303{
 304        if (!valid_policy) {
 305                ima_delete_rules();
 306                valid_policy = 1;
 307                atomic_set(&policy_opencount, 1);
 308                return 0;
 309        }
 310        ima_update_policy();
 311        securityfs_remove(ima_policy);
 312        ima_policy = NULL;
 313        return 0;
 314}
 315
 316static const struct file_operations ima_measure_policy_ops = {
 317        .open = ima_open_policy,
 318        .write = ima_write_policy,
 319        .release = ima_release_policy
 320};
 321
 322int __init ima_fs_init(void)
 323{
 324        ima_dir = securityfs_create_dir("ima", NULL);
 325        if (IS_ERR(ima_dir))
 326                return -1;
 327
 328        binary_runtime_measurements =
 329            securityfs_create_file("binary_runtime_measurements",
 330                                   S_IRUSR | S_IRGRP, ima_dir, NULL,
 331                                   &ima_measurements_ops);
 332        if (IS_ERR(binary_runtime_measurements))
 333                goto out;
 334
 335        ascii_runtime_measurements =
 336            securityfs_create_file("ascii_runtime_measurements",
 337                                   S_IRUSR | S_IRGRP, ima_dir, NULL,
 338                                   &ima_ascii_measurements_ops);
 339        if (IS_ERR(ascii_runtime_measurements))
 340                goto out;
 341
 342        runtime_measurements_count =
 343            securityfs_create_file("runtime_measurements_count",
 344                                   S_IRUSR | S_IRGRP, ima_dir, NULL,
 345                                   &ima_measurements_count_ops);
 346        if (IS_ERR(runtime_measurements_count))
 347                goto out;
 348
 349        violations =
 350            securityfs_create_file("violations", S_IRUSR | S_IRGRP,
 351                                   ima_dir, NULL, &ima_htable_violations_ops);
 352        if (IS_ERR(violations))
 353                goto out;
 354
 355        ima_policy = securityfs_create_file("policy",
 356                                            S_IWUSR,
 357                                            ima_dir, NULL,
 358                                            &ima_measure_policy_ops);
 359        if (IS_ERR(ima_policy))
 360                goto out;
 361
 362        return 0;
 363out:
 364        securityfs_remove(runtime_measurements_count);
 365        securityfs_remove(ascii_runtime_measurements);
 366        securityfs_remove(binary_runtime_measurements);
 367        securityfs_remove(ima_dir);
 368        securityfs_remove(ima_policy);
 369        return -1;
 370}
 371
 372void __exit ima_fs_cleanup(void)
 373{
 374        securityfs_remove(violations);
 375        securityfs_remove(runtime_measurements_count);
 376        securityfs_remove(ascii_runtime_measurements);
 377        securityfs_remove(binary_runtime_measurements);
 378        securityfs_remove(ima_dir);
 379        securityfs_remove(ima_policy);
 380}
 381