diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2011-03-09 14:13:22 -0500 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2011-07-18 12:29:38 -0400 |
commit | f381c272224f5f158f5cff64f8f3481fa0eee8b3 (patch) | |
tree | a003dc4c6635c9d2fa90f31577ba5e7ea7bc71b1 /security/integrity/iint.c | |
parent | 9d8f13ba3f4833219e50767b022b82cd0da930eb (diff) |
integrity: move ima inode integrity data management
Move the inode integrity data(iint) management up to the integrity directory
in order to share the iint among the different integrity models.
Changelog:
- don't define MAX_DIGEST_SIZE
- rename several globally visible 'ima_' prefixed functions, structs,
locks, etc to 'integrity_'
- replace '20' with SHA1_DIGEST_SIZE
- reflect location change in appropriate Kconfig and Makefiles
- remove unnecessary initialization of iint_initialized to 0
- rebased on current ima_iint.c
- define integrity_iint_store/lock as static
There should be no other functional changes.
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Diffstat (limited to 'security/integrity/iint.c')
-rw-r--r-- | security/integrity/iint.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/security/integrity/iint.c b/security/integrity/iint.c new file mode 100644 index 000000000000..d17de48bd6cc --- /dev/null +++ b/security/integrity/iint.c | |||
@@ -0,0 +1,170 @@ | |||
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: integrity_iint.c | ||
13 | * - implements the integrity hooks: integrity_inode_alloc, | ||
14 | * integrity_inode_free | ||
15 | * - cache integrity information associated with an inode | ||
16 | * using a rbtree tree. | ||
17 | */ | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/rbtree.h> | ||
22 | #include "integrity.h" | ||
23 | |||
24 | static struct rb_root integrity_iint_tree = RB_ROOT; | ||
25 | static DEFINE_SPINLOCK(integrity_iint_lock); | ||
26 | static struct kmem_cache *iint_cache __read_mostly; | ||
27 | |||
28 | int iint_initialized; | ||
29 | |||
30 | /* | ||
31 | * __integrity_iint_find - return the iint associated with an inode | ||
32 | */ | ||
33 | static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) | ||
34 | { | ||
35 | struct integrity_iint_cache *iint; | ||
36 | struct rb_node *n = integrity_iint_tree.rb_node; | ||
37 | |||
38 | assert_spin_locked(&integrity_iint_lock); | ||
39 | |||
40 | while (n) { | ||
41 | iint = rb_entry(n, struct integrity_iint_cache, rb_node); | ||
42 | |||
43 | if (inode < iint->inode) | ||
44 | n = n->rb_left; | ||
45 | else if (inode > iint->inode) | ||
46 | n = n->rb_right; | ||
47 | else | ||
48 | break; | ||
49 | } | ||
50 | if (!n) | ||
51 | return NULL; | ||
52 | |||
53 | return iint; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * integrity_iint_find - return the iint associated with an inode | ||
58 | */ | ||
59 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode) | ||
60 | { | ||
61 | struct integrity_iint_cache *iint; | ||
62 | |||
63 | if (!IS_IMA(inode)) | ||
64 | return NULL; | ||
65 | |||
66 | spin_lock(&integrity_iint_lock); | ||
67 | iint = __integrity_iint_find(inode); | ||
68 | spin_unlock(&integrity_iint_lock); | ||
69 | |||
70 | return iint; | ||
71 | } | ||
72 | |||
73 | static void iint_free(struct integrity_iint_cache *iint) | ||
74 | { | ||
75 | iint->version = 0; | ||
76 | iint->flags = 0UL; | ||
77 | kmem_cache_free(iint_cache, iint); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * integrity_inode_alloc - allocate an iint associated with an inode | ||
82 | * @inode: pointer to the inode | ||
83 | */ | ||
84 | int integrity_inode_alloc(struct inode *inode) | ||
85 | { | ||
86 | struct rb_node **p; | ||
87 | struct rb_node *new_node, *parent = NULL; | ||
88 | struct integrity_iint_cache *new_iint, *test_iint; | ||
89 | int rc; | ||
90 | |||
91 | new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS); | ||
92 | if (!new_iint) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | new_iint->inode = inode; | ||
96 | new_node = &new_iint->rb_node; | ||
97 | |||
98 | mutex_lock(&inode->i_mutex); /* i_flags */ | ||
99 | spin_lock(&integrity_iint_lock); | ||
100 | |||
101 | p = &integrity_iint_tree.rb_node; | ||
102 | while (*p) { | ||
103 | parent = *p; | ||
104 | test_iint = rb_entry(parent, struct integrity_iint_cache, | ||
105 | rb_node); | ||
106 | rc = -EEXIST; | ||
107 | if (inode < test_iint->inode) | ||
108 | p = &(*p)->rb_left; | ||
109 | else if (inode > test_iint->inode) | ||
110 | p = &(*p)->rb_right; | ||
111 | else | ||
112 | goto out_err; | ||
113 | } | ||
114 | |||
115 | inode->i_flags |= S_IMA; | ||
116 | rb_link_node(new_node, parent, p); | ||
117 | rb_insert_color(new_node, &integrity_iint_tree); | ||
118 | |||
119 | spin_unlock(&integrity_iint_lock); | ||
120 | mutex_unlock(&inode->i_mutex); /* i_flags */ | ||
121 | |||
122 | return 0; | ||
123 | out_err: | ||
124 | spin_unlock(&integrity_iint_lock); | ||
125 | mutex_unlock(&inode->i_mutex); /* i_flags */ | ||
126 | iint_free(new_iint); | ||
127 | |||
128 | return rc; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * integrity_inode_free - called on security_inode_free | ||
133 | * @inode: pointer to the inode | ||
134 | * | ||
135 | * Free the integrity information(iint) associated with an inode. | ||
136 | */ | ||
137 | void integrity_inode_free(struct inode *inode) | ||
138 | { | ||
139 | struct integrity_iint_cache *iint; | ||
140 | |||
141 | if (!IS_IMA(inode)) | ||
142 | return; | ||
143 | |||
144 | spin_lock(&integrity_iint_lock); | ||
145 | iint = __integrity_iint_find(inode); | ||
146 | rb_erase(&iint->rb_node, &integrity_iint_tree); | ||
147 | spin_unlock(&integrity_iint_lock); | ||
148 | |||
149 | iint_free(iint); | ||
150 | } | ||
151 | |||
152 | static void init_once(void *foo) | ||
153 | { | ||
154 | struct integrity_iint_cache *iint = foo; | ||
155 | |||
156 | memset(iint, 0, sizeof *iint); | ||
157 | iint->version = 0; | ||
158 | iint->flags = 0UL; | ||
159 | mutex_init(&iint->mutex); | ||
160 | } | ||
161 | |||
162 | static int __init integrity_iintcache_init(void) | ||
163 | { | ||
164 | iint_cache = | ||
165 | kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), | ||
166 | 0, SLAB_PANIC, init_once); | ||
167 | iint_initialized = 1; | ||
168 | return 0; | ||
169 | } | ||
170 | security_initcall(integrity_iintcache_init); | ||