aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_iint.c
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2009-02-04 09:06:58 -0500
committerJames Morris <jmorris@namei.org>2009-02-05 17:05:30 -0500
commit3323eec921efd815178a23107ab63588c605c0b2 (patch)
treebc9e9714ac4881ebc515c1bd155674c52c356d6a /security/integrity/ima/ima_iint.c
parent6146f0d5e47ca4047ffded0fb79b6c25359b386c (diff)
integrity: IMA as an integrity service provider
IMA provides hardware (TPM) based measurement and attestation for file measurements. As the Trusted Computing (TPM) model requires, IMA measures all files before they are accessed in any way (on the integrity_bprm_check, integrity_path_check and integrity_file_mmap hooks), and commits the measurements to the TPM. Once added to the TPM, measurements can not be removed. In addition, IMA maintains a list of these file measurements, which can be used to validate the aggregate value stored in the TPM. The TPM can sign these measurements, and thus the system can prove, to itself and to a third party, the system's integrity in a way that cannot be circumvented by malicious or compromised software. - alloc ima_template_entry before calling ima_store_template() - log ima_add_boot_aggregate() failure - removed unused IMA_TEMPLATE_NAME_LEN - replaced hard coded string length with #define name Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/integrity/ima/ima_iint.c')
-rw-r--r--security/integrity/ima/ima_iint.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
new file mode 100644
index 000000000000..750db3c993a7
--- /dev/null
+++ b/security/integrity/ima/ima_iint.c
@@ -0,0 +1,185 @@
1/*
2 * Copyright (C) 2008 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2 of the
10 * License.
11 *
12 * File: ima_iint.c
13 * - implements the IMA hooks: ima_inode_alloc, ima_inode_free
14 * - cache integrity information associated with an inode
15 * using a radix tree.
16 */
17#include <linux/module.h>
18#include <linux/spinlock.h>
19#include <linux/radix-tree.h>
20#include "ima.h"
21
22#define ima_iint_delete ima_inode_free
23
24RADIX_TREE(ima_iint_store, GFP_ATOMIC);
25DEFINE_SPINLOCK(ima_iint_lock);
26
27static struct kmem_cache *iint_cache __read_mostly;
28
29/* ima_iint_find_get - return the iint associated with an inode
30 *
31 * ima_iint_find_get gets a reference to the iint. Caller must
32 * remember to put the iint reference.
33 */
34struct ima_iint_cache *ima_iint_find_get(struct inode *inode)
35{
36 struct ima_iint_cache *iint;
37
38 rcu_read_lock();
39 iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode);
40 if (!iint)
41 goto out;
42 kref_get(&iint->refcount);
43out:
44 rcu_read_unlock();
45 return iint;
46}
47
48/* Allocate memory for the iint associated with the inode
49 * from the iint_cache slab, initialize the iint, and
50 * insert it into the radix tree.
51 *
52 * On success return a pointer to the iint; on failure return NULL.
53 */
54struct ima_iint_cache *ima_iint_insert(struct inode *inode)
55{
56 struct ima_iint_cache *iint = NULL;
57 int rc = 0;
58
59 if (!ima_initialized)
60 return iint;
61 iint = kmem_cache_alloc(iint_cache, GFP_KERNEL);
62 if (!iint)
63 return iint;
64
65 rc = radix_tree_preload(GFP_KERNEL);
66 if (rc < 0)
67 goto out;
68
69 spin_lock(&ima_iint_lock);
70 rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
71 spin_unlock(&ima_iint_lock);
72out:
73 if (rc < 0) {
74 kmem_cache_free(iint_cache, iint);
75 if (rc == -EEXIST) {
76 iint = radix_tree_lookup(&ima_iint_store,
77 (unsigned long)inode);
78 } else
79 iint = NULL;
80 }
81 radix_tree_preload_end();
82 return iint;
83}
84
85/**
86 * ima_inode_alloc - allocate an iint associated with an inode
87 * @inode: pointer to the inode
88 *
89 * Return 0 on success, 1 on failure.
90 */
91int ima_inode_alloc(struct inode *inode)
92{
93 struct ima_iint_cache *iint;
94
95 if (!ima_initialized)
96 return 0;
97
98 iint = ima_iint_insert(inode);
99 if (!iint)
100 return 1;
101 return 0;
102}
103
104/* ima_iint_find_insert_get - get the iint associated with an inode
105 *
106 * Most insertions are done at inode_alloc, except those allocated
107 * before late_initcall. When the iint does not exist, allocate it,
108 * initialize and insert it, and increment the iint refcount.
109 *
110 * (Can't initialize at security_initcall before any inodes are
111 * allocated, got to wait at least until proc_init.)
112 *
113 * Return the iint.
114 */
115struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
116{
117 struct ima_iint_cache *iint = NULL;
118
119 iint = ima_iint_find_get(inode);
120 if (iint)
121 return iint;
122
123 iint = ima_iint_insert(inode);
124 if (iint)
125 kref_get(&iint->refcount);
126
127 return iint;
128}
129
130/* iint_free - called when the iint refcount goes to zero */
131void iint_free(struct kref *kref)
132{
133 struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
134 refcount);
135 iint->version = 0;
136 iint->flags = 0UL;
137 kref_set(&iint->refcount, 1);
138 kmem_cache_free(iint_cache, iint);
139}
140
141void iint_rcu_free(struct rcu_head *rcu_head)
142{
143 struct ima_iint_cache *iint = container_of(rcu_head,
144 struct ima_iint_cache, rcu);
145 kref_put(&iint->refcount, iint_free);
146}
147
148/**
149 * ima_iint_delete - called on integrity_inode_free
150 * @inode: pointer to the inode
151 *
152 * Free the integrity information(iint) associated with an inode.
153 */
154void ima_iint_delete(struct inode *inode)
155{
156 struct ima_iint_cache *iint;
157
158 if (!ima_initialized)
159 return;
160 spin_lock(&ima_iint_lock);
161 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
162 spin_unlock(&ima_iint_lock);
163 if (iint)
164 call_rcu(&iint->rcu, iint_rcu_free);
165}
166
167static void init_once(void *foo)
168{
169 struct ima_iint_cache *iint = foo;
170
171 memset(iint, 0, sizeof *iint);
172 iint->version = 0;
173 iint->flags = 0UL;
174 mutex_init(&iint->mutex);
175 iint->readcount = 0;
176 iint->writecount = 0;
177 kref_set(&iint->refcount, 1);
178}
179
180void ima_iintcache_init(void)
181{
182 iint_cache =
183 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
184 SLAB_PANIC, init_once);
185}