xref: /linux/security/integrity/ima/ima_iint.c (revision 606b2f490fb80e55d05cf0e6cec0b6c0ff0fc18f)
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/slab.h>
18 #include <linux/module.h>
19 #include <linux/spinlock.h>
20 #include <linux/radix-tree.h>
21 #include "ima.h"
22 
23 RADIX_TREE(ima_iint_store, GFP_ATOMIC);
24 DEFINE_SPINLOCK(ima_iint_lock);
25 
26 static struct kmem_cache *iint_cache __read_mostly;
27 
28 /* ima_iint_find_get - return the iint associated with an inode
29  *
30  * ima_iint_find_get gets a reference to the iint. Caller must
31  * remember to put the iint reference.
32  */
33 struct ima_iint_cache *ima_iint_find_get(struct inode *inode)
34 {
35 	struct ima_iint_cache *iint;
36 
37 	rcu_read_lock();
38 	iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode);
39 	if (!iint)
40 		goto out;
41 	kref_get(&iint->refcount);
42 out:
43 	rcu_read_unlock();
44 	return iint;
45 }
46 
47 /**
48  * ima_inode_alloc - allocate an iint associated with an inode
49  * @inode: pointer to the inode
50  */
51 int ima_inode_alloc(struct inode *inode)
52 {
53 	struct ima_iint_cache *iint = NULL;
54 	int rc = 0;
55 
56 	iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
57 	if (!iint)
58 		return -ENOMEM;
59 
60 	rc = radix_tree_preload(GFP_NOFS);
61 	if (rc < 0)
62 		goto out;
63 
64 	spin_lock(&ima_iint_lock);
65 	rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
66 	spin_unlock(&ima_iint_lock);
67 	radix_tree_preload_end();
68 out:
69 	if (rc < 0)
70 		kmem_cache_free(iint_cache, iint);
71 
72 	return rc;
73 }
74 
75 /* iint_free - called when the iint refcount goes to zero */
76 void iint_free(struct kref *kref)
77 {
78 	struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
79 						   refcount);
80 	iint->version = 0;
81 	iint->flags = 0UL;
82 	if (iint->readcount != 0) {
83 		printk(KERN_INFO "%s: readcount: %ld\n", __func__,
84 		       iint->readcount);
85 		iint->readcount = 0;
86 	}
87 	if (iint->writecount != 0) {
88 		printk(KERN_INFO "%s: writecount: %ld\n", __func__,
89 		       iint->writecount);
90 		iint->writecount = 0;
91 	}
92 	if (iint->opencount != 0) {
93 		printk(KERN_INFO "%s: opencount: %ld\n", __func__,
94 		       iint->opencount);
95 		iint->opencount = 0;
96 	}
97 	kref_init(&iint->refcount);
98 	kmem_cache_free(iint_cache, iint);
99 }
100 
101 void iint_rcu_free(struct rcu_head *rcu_head)
102 {
103 	struct ima_iint_cache *iint = container_of(rcu_head,
104 						   struct ima_iint_cache, rcu);
105 	kref_put(&iint->refcount, iint_free);
106 }
107 
108 /**
109  * ima_inode_free - called on security_inode_free
110  * @inode: pointer to the inode
111  *
112  * Free the integrity information(iint) associated with an inode.
113  */
114 void ima_inode_free(struct inode *inode)
115 {
116 	struct ima_iint_cache *iint;
117 
118 	spin_lock(&ima_iint_lock);
119 	iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
120 	spin_unlock(&ima_iint_lock);
121 	if (iint)
122 		call_rcu(&iint->rcu, iint_rcu_free);
123 }
124 
125 static void init_once(void *foo)
126 {
127 	struct ima_iint_cache *iint = foo;
128 
129 	memset(iint, 0, sizeof *iint);
130 	iint->version = 0;
131 	iint->flags = 0UL;
132 	mutex_init(&iint->mutex);
133 	iint->readcount = 0;
134 	iint->writecount = 0;
135 	iint->opencount = 0;
136 	kref_init(&iint->refcount);
137 }
138 
139 static int __init ima_iintcache_init(void)
140 {
141 	iint_cache =
142 	    kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
143 			      SLAB_PANIC, init_once);
144 	return 0;
145 }
146 security_initcall(ima_iintcache_init);
147