Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+277 -216
-13
include/linux/ima.h
··· 15 15 16 16 #ifdef CONFIG_IMA 17 17 extern int ima_bprm_check(struct linux_binprm *bprm); 18 - extern int ima_inode_alloc(struct inode *inode); 19 - extern void ima_inode_free(struct inode *inode); 20 18 extern int ima_file_check(struct file *file, int mask); 21 19 extern void ima_file_free(struct file *file); 22 20 extern int ima_file_mmap(struct file *file, unsigned long prot); ··· 23 25 static inline int ima_bprm_check(struct linux_binprm *bprm) 24 26 { 25 27 return 0; 26 - } 27 - 28 - static inline int ima_inode_alloc(struct inode *inode) 29 - { 30 - return 0; 31 - } 32 - 33 - static inline void ima_inode_free(struct inode *inode) 34 - { 35 - return; 36 28 } 37 29 38 30 static inline int ima_file_check(struct file *file, int mask) ··· 39 51 { 40 52 return 0; 41 53 } 42 - 43 54 #endif /* CONFIG_IMA_H */ 44 55 #endif /* _LINUX_IMA_H */
+30
include/linux/integrity.h
··· 1 + /* 2 + * Copyright (C) 2009 IBM Corporation 3 + * Author: Mimi Zohar <zohar@us.ibm.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License as published by 7 + * the Free Software Foundation, version 2 of the License. 8 + */ 9 + 10 + #ifndef _LINUX_INTEGRITY_H 11 + #define _LINUX_INTEGRITY_H 12 + 13 + #include <linux/fs.h> 14 + 15 + #ifdef CONFIG_INTEGRITY 16 + extern int integrity_inode_alloc(struct inode *inode); 17 + extern void integrity_inode_free(struct inode *inode); 18 + 19 + #else 20 + static inline int integrity_inode_alloc(struct inode *inode) 21 + { 22 + return 0; 23 + } 24 + 25 + static inline void integrity_inode_free(struct inode *inode) 26 + { 27 + return; 28 + } 29 + #endif /* CONFIG_INTEGRITY_H */ 30 + #endif /* _LINUX_INTEGRITY_H */
+1 -1
security/Kconfig
··· 186 186 source security/tomoyo/Kconfig 187 187 source security/apparmor/Kconfig 188 188 189 - source security/integrity/ima/Kconfig 189 + source security/integrity/Kconfig 190 190 191 191 choice 192 192 prompt "Default security module"
+2 -2
security/Makefile
··· 24 24 obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 25 25 26 26 # Object integrity file lists 27 - subdir-$(CONFIG_IMA) += integrity/ima 28 - obj-$(CONFIG_IMA) += integrity/ima/built-in.o 27 + subdir-$(CONFIG_INTEGRITY) += integrity 28 + obj-$(CONFIG_INTEGRITY) += integrity/built-in.o
+6
security/integrity/Kconfig
··· 1 + # 2 + config INTEGRITY 3 + def_bool y 4 + depends on IMA 5 + 6 + source security/integrity/ima/Kconfig
+10
security/integrity/Makefile
··· 1 + # 2 + # Makefile for caching inode integrity data (iint) 3 + # 4 + 5 + obj-$(CONFIG_INTEGRITY) += integrity.o 6 + 7 + integrity-y := iint.o 8 + 9 + subdir-$(CONFIG_IMA) += ima 10 + obj-$(CONFIG_IMA) += ima/built-in.o
+170
security/integrity/iint.c
··· 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);
+1
security/integrity/ima/Kconfig
··· 3 3 config IMA 4 4 bool "Integrity Measurement Architecture(IMA)" 5 5 depends on SECURITY 6 + select INTEGRITY 6 7 select SECURITYFS 7 8 select CRYPTO 8 9 select CRYPTO_HMAC
+1 -1
security/integrity/ima/Makefile
··· 6 6 obj-$(CONFIG_IMA) += ima.o 7 7 8 8 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ 9 - ima_policy.o ima_iint.o ima_audit.o 9 + ima_policy.o ima_audit.o
+9 -20
security/integrity/ima/ima.h
··· 24 24 #include <linux/tpm.h> 25 25 #include <linux/audit.h> 26 26 27 + #include "../integrity.h" 28 + 27 29 enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII }; 28 30 enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; 29 31 30 32 /* digest size for IMA, fits SHA1 or MD5 */ 31 - #define IMA_DIGEST_SIZE 20 33 + #define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE 32 34 #define IMA_EVENT_NAME_LEN_MAX 255 33 35 34 36 #define IMA_HASH_BITS 9 ··· 98 96 return hash_long(*digest, IMA_HASH_BITS); 99 97 } 100 98 101 - /* iint cache flags */ 102 - #define IMA_MEASURED 0x01 103 - 104 - /* integrity data associated with an inode */ 105 - struct ima_iint_cache { 106 - struct rb_node rb_node; /* rooted in ima_iint_tree */ 107 - struct inode *inode; /* back pointer to inode in question */ 108 - u64 version; /* track inode changes */ 109 - unsigned char flags; 110 - u8 digest[IMA_DIGEST_SIZE]; 111 - struct mutex mutex; /* protects: version, flags, digest */ 112 - }; 113 - 114 99 /* LIM API function definitions */ 115 100 int ima_must_measure(struct inode *inode, int mask, int function); 116 - int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file); 117 - void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, 101 + int ima_collect_measurement(struct integrity_iint_cache *iint, 102 + struct file *file); 103 + void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, 118 104 const unsigned char *filename); 119 105 int ima_store_template(struct ima_template_entry *entry, int violation, 120 106 struct inode *inode); 121 - void ima_template_show(struct seq_file *m, void *e, 122 - enum ima_show_type show); 107 + void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show); 123 108 124 109 /* rbtree tree calls to lookup, insert, delete 125 110 * integrity data associated with an inode. 126 111 */ 127 - struct ima_iint_cache *ima_iint_insert(struct inode *inode); 128 - struct ima_iint_cache *ima_iint_find(struct inode *inode); 112 + struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); 113 + struct integrity_iint_cache *integrity_iint_find(struct inode *inode); 129 114 130 115 /* IMA policy related functions */ 131 116 enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
+4 -3
security/integrity/ima/ima_api.c
··· 126 126 * 127 127 * Return 0 on success, error code otherwise 128 128 */ 129 - int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file) 129 + int ima_collect_measurement(struct integrity_iint_cache *iint, 130 + struct file *file) 130 131 { 131 132 int result = -EEXIST; 132 133 ··· 157 156 * 158 157 * Must be called with iint->mutex held. 159 158 */ 160 - void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, 161 - const unsigned char *filename) 159 + void ima_store_measurement(struct integrity_iint_cache *iint, 160 + struct file *file, const unsigned char *filename) 162 161 { 163 162 const char *op = "add_template_measure"; 164 163 const char *audit_cause = "ENOMEM";
-169
security/integrity/ima/ima_iint.c
··· 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 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);
+6 -6
security/integrity/ima/ima_main.c
··· 82 82 "open_writers"); 83 83 } 84 84 85 - static void ima_check_last_writer(struct ima_iint_cache *iint, 85 + static void ima_check_last_writer(struct integrity_iint_cache *iint, 86 86 struct inode *inode, 87 87 struct file *file) 88 88 { ··· 105 105 void ima_file_free(struct file *file) 106 106 { 107 107 struct inode *inode = file->f_dentry->d_inode; 108 - struct ima_iint_cache *iint; 108 + struct integrity_iint_cache *iint; 109 109 110 110 if (!iint_initialized || !S_ISREG(inode->i_mode)) 111 111 return; 112 112 113 - iint = ima_iint_find(inode); 113 + iint = integrity_iint_find(inode); 114 114 if (!iint) 115 115 return; 116 116 ··· 121 121 int mask, int function) 122 122 { 123 123 struct inode *inode = file->f_dentry->d_inode; 124 - struct ima_iint_cache *iint; 124 + struct integrity_iint_cache *iint; 125 125 int rc = 0; 126 126 127 127 if (!ima_initialized || !S_ISREG(inode->i_mode)) ··· 131 131 if (rc != 0) 132 132 return rc; 133 133 retry: 134 - iint = ima_iint_find(inode); 134 + iint = integrity_iint_find(inode); 135 135 if (!iint) { 136 - rc = ima_inode_alloc(inode); 136 + rc = integrity_inode_alloc(inode); 137 137 if (!rc || rc == -EEXIST) 138 138 goto retry; 139 139 return rc;
+35
security/integrity/integrity.h
··· 1 + /* 2 + * Copyright (C) 2009-2010 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 + */ 13 + 14 + #include <linux/types.h> 15 + #include <linux/integrity.h> 16 + #include <crypto/sha.h> 17 + 18 + /* iint cache flags */ 19 + #define IMA_MEASURED 0x01 20 + 21 + /* integrity data associated with an inode */ 22 + struct integrity_iint_cache { 23 + struct rb_node rb_node; /* rooted in integrity_iint_tree */ 24 + struct inode *inode; /* back pointer to inode in question */ 25 + u64 version; /* track inode changes */ 26 + unsigned char flags; 27 + u8 digest[SHA1_DIGEST_SIZE]; 28 + struct mutex mutex; /* protects: version, flags, digest */ 29 + }; 30 + 31 + /* rbtree tree calls to lookup, insert, delete 32 + * integrity data associated with an inode. 33 + */ 34 + struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); 35 + struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
+2 -1
security/security.c
··· 16 16 #include <linux/init.h> 17 17 #include <linux/kernel.h> 18 18 #include <linux/security.h> 19 + #include <linux/integrity.h> 19 20 #include <linux/ima.h> 20 21 21 22 #define MAX_LSM_XATTR 1 ··· 337 336 338 337 void security_inode_free(struct inode *inode) 339 338 { 340 - ima_inode_free(inode); 339 + integrity_inode_free(inode); 341 340 security_ops->inode_free_security(inode); 342 341 } 343 342