12
12
* File: ima_iint.c
13
13
* - implements the IMA hooks: ima_inode_alloc, ima_inode_free
14
14
* - cache integrity information associated with an inode
15
- * using a radix tree.
15
+ * using a rbtree tree.
16
16
*/
17
17
#include <linux/slab.h>
18
18
#include <linux/module.h>
19
19
#include <linux/spinlock.h>
20
- #include <linux/radix-tree .h>
20
+ #include <linux/rbtree .h>
21
21
#include "ima.h"
22
22
23
- RADIX_TREE ( ima_iint_store , GFP_ATOMIC ) ;
24
- DEFINE_SPINLOCK (ima_iint_lock );
23
+ static struct rb_root ima_iint_tree = RB_ROOT ;
24
+ static DEFINE_SPINLOCK (ima_iint_lock );
25
25
static struct kmem_cache * iint_cache __read_mostly ;
26
26
27
27
int iint_initialized = 0 ;
28
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.
29
+ /*
30
+ * __ima_iint_find - return the iint associated with an inode
33
31
*/
34
- struct ima_iint_cache * ima_iint_find_get (struct inode * inode )
32
+ static struct ima_iint_cache * __ima_iint_find (struct inode * inode )
35
33
{
36
34
struct ima_iint_cache * iint ;
35
+ struct rb_node * n = ima_iint_tree .rb_node ;
36
+
37
+ assert_spin_locked (& ima_iint_lock );
38
+
39
+ while (n ) {
40
+ iint = rb_entry (n , struct ima_iint_cache , rb_node );
41
+
42
+ if (inode < iint -> inode )
43
+ n = n -> rb_left ;
44
+ else if (inode > iint -> inode )
45
+ n = n -> rb_right ;
46
+ else
47
+ break ;
48
+ }
49
+ if (!n )
50
+ return NULL ;
37
51
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 );
43
- out :
44
- rcu_read_unlock ();
45
52
return iint ;
46
53
}
47
54
48
- /**
49
- * ima_inode_alloc - allocate an iint associated with an inode
50
- * @inode: pointer to the inode
55
+ /*
56
+ * ima_iint_find - return the iint associated with an inode
51
57
*/
52
- int ima_inode_alloc (struct inode * inode )
58
+ struct ima_iint_cache * ima_iint_find (struct inode * inode )
53
59
{
54
- struct ima_iint_cache * iint = NULL ;
55
- int rc = 0 ;
56
-
57
- iint = kmem_cache_alloc (iint_cache , GFP_NOFS );
58
- if (!iint )
59
- return - ENOMEM ;
60
+ struct ima_iint_cache * iint ;
60
61
61
- rc = radix_tree_preload (GFP_NOFS );
62
- if (rc < 0 )
63
- goto out ;
62
+ if (!IS_IMA (inode ))
63
+ return NULL ;
64
64
65
65
spin_lock (& ima_iint_lock );
66
- rc = radix_tree_insert ( & ima_iint_store , ( unsigned long ) inode , iint );
66
+ iint = __ima_iint_find ( inode );
67
67
spin_unlock (& ima_iint_lock );
68
- radix_tree_preload_end ();
69
- out :
70
- if (rc < 0 )
71
- kmem_cache_free (iint_cache , iint );
72
68
73
- return rc ;
69
+ return iint ;
74
70
}
75
71
76
- /* iint_free - called when the iint refcount goes to zero */
77
- void iint_free (struct kref * kref )
72
+ static void iint_free (struct ima_iint_cache * iint )
78
73
{
79
- struct ima_iint_cache * iint = container_of (kref , struct ima_iint_cache ,
80
- refcount );
81
74
iint -> version = 0 ;
82
75
iint -> flags = 0UL ;
83
- if (iint -> readcount != 0 ) {
84
- printk (KERN_INFO "%s: readcount: %ld\n" , __func__ ,
85
- iint -> readcount );
86
- iint -> readcount = 0 ;
87
- }
88
- if (iint -> writecount != 0 ) {
89
- printk (KERN_INFO "%s: writecount: %ld\n" , __func__ ,
90
- iint -> writecount );
91
- iint -> writecount = 0 ;
92
- }
93
- if (iint -> opencount != 0 ) {
94
- printk (KERN_INFO "%s: opencount: %ld\n" , __func__ ,
95
- iint -> opencount );
96
- iint -> opencount = 0 ;
97
- }
98
- kref_init (& iint -> refcount );
99
76
kmem_cache_free (iint_cache , iint );
100
77
}
101
78
102
- void iint_rcu_free (struct rcu_head * rcu_head )
79
+ /**
80
+ * ima_inode_alloc - allocate an iint associated with an inode
81
+ * @inode: pointer to the inode
82
+ */
83
+ int ima_inode_alloc (struct inode * inode )
103
84
{
104
- struct ima_iint_cache * iint = container_of (rcu_head ,
105
- struct ima_iint_cache , rcu );
106
- kref_put (& iint -> refcount , iint_free );
85
+ struct rb_node * * p ;
86
+ struct rb_node * new_node , * parent = NULL ;
87
+ struct ima_iint_cache * new_iint , * test_iint ;
88
+ int rc ;
89
+
90
+ new_iint = kmem_cache_alloc (iint_cache , GFP_NOFS );
91
+ if (!new_iint )
92
+ return - ENOMEM ;
93
+
94
+ new_iint -> inode = inode ;
95
+ new_node = & new_iint -> rb_node ;
96
+
97
+ mutex_lock (& inode -> i_mutex ); /* i_flags */
98
+ spin_lock (& ima_iint_lock );
99
+
100
+ p = & ima_iint_tree .rb_node ;
101
+ while (* p ) {
102
+ parent = * p ;
103
+ test_iint = rb_entry (parent , struct ima_iint_cache , rb_node );
104
+
105
+ rc = - EEXIST ;
106
+ if (inode < test_iint -> inode )
107
+ p = & (* p )-> rb_left ;
108
+ else if (inode > test_iint -> inode )
109
+ p = & (* p )-> rb_right ;
110
+ else
111
+ goto out_err ;
112
+ }
113
+
114
+ inode -> i_flags |= S_IMA ;
115
+ rb_link_node (new_node , parent , p );
116
+ rb_insert_color (new_node , & ima_iint_tree );
117
+
118
+ spin_unlock (& ima_iint_lock );
119
+ mutex_unlock (& inode -> i_mutex ); /* i_flags */
120
+
121
+ return 0 ;
122
+ out_err :
123
+ spin_unlock (& ima_iint_lock );
124
+ mutex_unlock (& inode -> i_mutex ); /* i_flags */
125
+ iint_free (new_iint );
126
+
127
+ return rc ;
107
128
}
108
129
109
130
/**
@@ -116,11 +137,20 @@ void ima_inode_free(struct inode *inode)
116
137
{
117
138
struct ima_iint_cache * iint ;
118
139
140
+ if (inode -> i_readcount )
141
+ printk (KERN_INFO "%s: readcount: %u\n" , __func__ , inode -> i_readcount );
142
+
143
+ inode -> i_readcount = 0 ;
144
+
145
+ if (!IS_IMA (inode ))
146
+ return ;
147
+
119
148
spin_lock (& ima_iint_lock );
120
- iint = radix_tree_delete (& ima_iint_store , (unsigned long )inode );
149
+ iint = __ima_iint_find (inode );
150
+ rb_erase (& iint -> rb_node , & ima_iint_tree );
121
151
spin_unlock (& ima_iint_lock );
122
- if ( iint )
123
- call_rcu ( & iint -> rcu , iint_rcu_free );
152
+
153
+ iint_free ( iint );
124
154
}
125
155
126
156
static void init_once (void * foo )
@@ -131,10 +161,6 @@ static void init_once(void *foo)
131
161
iint -> version = 0 ;
132
162
iint -> flags = 0UL ;
133
163
mutex_init (& iint -> mutex );
134
- iint -> readcount = 0 ;
135
- iint -> writecount = 0 ;
136
- iint -> opencount = 0 ;
137
- kref_init (& iint -> refcount );
138
164
}
139
165
140
166
static int __init ima_iintcache_init (void )
0 commit comments