Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/security/integrity/ima/ima_iint.c
10818 views
1
/*
2
* Copyright (C) 2008 IBM Corporation
3
*
4
* Authors:
5
* Mimi Zohar <[email protected]>
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 rbtree tree.
16
*/
17
#include <linux/slab.h>
18
#include <linux/module.h>
19
#include <linux/spinlock.h>
20
#include <linux/rbtree.h>
21
#include "ima.h"
22
23
static struct rb_root ima_iint_tree = RB_ROOT;
24
static DEFINE_SPINLOCK(ima_iint_lock);
25
static struct kmem_cache *iint_cache __read_mostly;
26
27
int iint_initialized = 0;
28
29
/*
30
* __ima_iint_find - return the iint associated with an inode
31
*/
32
static struct ima_iint_cache *__ima_iint_find(struct inode *inode)
33
{
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;
51
52
return iint;
53
}
54
55
/*
56
* ima_iint_find - return the iint associated with an inode
57
*/
58
struct ima_iint_cache *ima_iint_find(struct inode *inode)
59
{
60
struct ima_iint_cache *iint;
61
62
if (!IS_IMA(inode))
63
return NULL;
64
65
spin_lock(&ima_iint_lock);
66
iint = __ima_iint_find(inode);
67
spin_unlock(&ima_iint_lock);
68
69
return iint;
70
}
71
72
static void iint_free(struct ima_iint_cache *iint)
73
{
74
iint->version = 0;
75
iint->flags = 0UL;
76
kmem_cache_free(iint_cache, iint);
77
}
78
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)
84
{
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;
128
}
129
130
/**
131
* ima_inode_free - called on security_inode_free
132
* @inode: pointer to the inode
133
*
134
* Free the integrity information(iint) associated with an inode.
135
*/
136
void ima_inode_free(struct inode *inode)
137
{
138
struct ima_iint_cache *iint;
139
140
if (!IS_IMA(inode))
141
return;
142
143
spin_lock(&ima_iint_lock);
144
iint = __ima_iint_find(inode);
145
rb_erase(&iint->rb_node, &ima_iint_tree);
146
spin_unlock(&ima_iint_lock);
147
148
iint_free(iint);
149
}
150
151
static void init_once(void *foo)
152
{
153
struct ima_iint_cache *iint = foo;
154
155
memset(iint, 0, sizeof *iint);
156
iint->version = 0;
157
iint->flags = 0UL;
158
mutex_init(&iint->mutex);
159
}
160
161
static int __init ima_iintcache_init(void)
162
{
163
iint_cache =
164
kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
165
SLAB_PANIC, init_once);
166
iint_initialized = 1;
167
return 0;
168
}
169
security_initcall(ima_iintcache_init);
170
171