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