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

ima: integrity appraisal extension

IMA currently maintains an integrity measurement list used to assert the
integrity of the running system to a third party. The IMA-appraisal
extension adds local integrity validation and enforcement of the
measurement against a "good" value stored as an extended attribute
'security.ima'. The initial methods for validating 'security.ima' are
hashed based, which provides file data integrity, and digital signature
based, which in addition to providing file data integrity, provides
authenticity.

This patch creates and maintains the 'security.ima' xattr, containing
the file data hash measurement. Protection of the xattr is provided by
EVM, if enabled and configured.

Based on policy, IMA calls evm_verifyxattr() to verify a file's metadata
integrity and, assuming success, compares the file's current hash value
with the one stored as an extended attribute in 'security.ima'.

Changelov v4:
- changed iint cache flags to hex values

Changelog v3:
- change appraisal default for filesystems without xattr support to fail

Changelog v2:
- fix audit msg 'res' value
- removed unused 'ima_appraise=' values

Changelog v1:
- removed unused iint mutex (Dmitry Kasatkin)
- setattr hook must not reset appraised (Dmitry Kasatkin)
- evm_verifyxattr() now differentiates between no 'security.evm' xattr
(INTEGRITY_NOLABEL) and no EVM 'protected' xattrs included in the
'security.evm' (INTEGRITY_NOXATTRS).
- replace hash_status with ima_status (Dmitry Kasatkin)
- re-initialize slab element ima_status on free (Dmitry Kasatkin)
- include 'security.ima' in EVM if CONFIG_IMA_APPRAISE, not CONFIG_IMA
- merged half "ima: ima_must_appraise_or_measure API change" (Dmitry Kasatkin)
- removed unnecessary error variable in process_measurement() (Dmitry Kasatkin)
- use ima_inode_post_setattr() stub function, if IMA_APPRAISE not configured
(moved ima_inode_post_setattr() to ima_appraise.c)
- make sure ima_collect_measurement() can read file

Changelog:
- add 'iint' to evm_verifyxattr() call (Dimitry Kasatkin)
- fix the race condition between chmod, which takes the i_mutex and then
iint->mutex, and ima_file_free() and process_measurement(), which take
the locks in the reverse order, by eliminating iint->mutex. (Dmitry Kasatkin)
- cleanup of ima_appraise_measurement() (Dmitry Kasatkin)
- changes as a result of the iint not allocated for all regular files, but
only for those measured/appraised.
- don't try to appraise new/empty files
- expanded ima_appraisal description in ima/Kconfig
- IMA appraise definitions required even if IMA_APPRAISE not enabled
- add return value to ima_must_appraise() stub
- unconditionally set status = INTEGRITY_PASS *after* testing status,
not before. (Found by Joe Perches)

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>

+358 -53
+4
Documentation/kernel-parameters.txt
··· 1051 1051 ihash_entries= [KNL] 1052 1052 Set number of hash buckets for inode cache. 1053 1053 1054 + ima_appraise= [IMA] appraise integrity measurements 1055 + Format: { "off" | "enforce" | "fix" } 1056 + default: "enforce" 1057 + 1054 1058 ima_audit= [IMA] 1055 1059 Format: { "0" | "1" } 1056 1060 0 -- integrity auditing messages. (Default)
+3
include/linux/xattr.h
··· 33 33 #define XATTR_EVM_SUFFIX "evm" 34 34 #define XATTR_NAME_EVM XATTR_SECURITY_PREFIX XATTR_EVM_SUFFIX 35 35 36 + #define XATTR_IMA_SUFFIX "ima" 37 + #define XATTR_NAME_IMA XATTR_SECURITY_PREFIX XATTR_IMA_SUFFIX 38 + 36 39 #define XATTR_SELINUX_SUFFIX "selinux" 37 40 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX 38 41
+3
security/integrity/evm/evm_main.c
··· 34 34 #ifdef CONFIG_SECURITY_SMACK 35 35 XATTR_NAME_SMACK, 36 36 #endif 37 + #ifdef CONFIG_IMA_APPRAISE 38 + XATTR_NAME_IMA, 39 + #endif 37 40 XATTR_NAME_CAPS, 38 41 NULL 39 42 };
+2 -1
security/integrity/iint.c
··· 74 74 { 75 75 iint->version = 0; 76 76 iint->flags = 0UL; 77 + iint->ima_status = INTEGRITY_UNKNOWN; 77 78 iint->evm_status = INTEGRITY_UNKNOWN; 78 79 kmem_cache_free(iint_cache, iint); 79 80 } ··· 158 157 memset(iint, 0, sizeof *iint); 159 158 iint->version = 0; 160 159 iint->flags = 0UL; 161 - mutex_init(&iint->mutex); 160 + iint->ima_status = INTEGRITY_UNKNOWN; 162 161 iint->evm_status = INTEGRITY_UNKNOWN; 163 162 } 164 163
+15
security/integrity/ima/Kconfig
··· 56 56 default y 57 57 help 58 58 Disabling this option will disregard LSM based policy rules. 59 + 60 + config IMA_APPRAISE 61 + bool "Appraise integrity measurements" 62 + depends on IMA 63 + default n 64 + help 65 + This option enables local measurement integrity appraisal. 66 + It requires the system to be labeled with a security extended 67 + attribute containing the file hash measurement. To protect 68 + the security extended attributes from offline attack, enable 69 + and configure EVM. 70 + 71 + For more information on integrity appraisal refer to: 72 + <http://linux-ima.sourceforge.net> 73 + If unsure, say N.
+1
security/integrity/ima/Makefile
··· 8 8 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ 9 9 ima_policy.o 10 10 ima-$(CONFIG_IMA_AUDIT) += ima_audit.o 11 + ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
+35 -2
security/integrity/ima/ima.h
··· 40 40 extern int ima_initialized; 41 41 extern int ima_used_chip; 42 42 extern char *ima_hash; 43 + extern int ima_appraise; 43 44 44 45 /* IMA inode template definition */ 45 46 struct ima_template_data { ··· 108 107 } 109 108 110 109 /* LIM API function definitions */ 110 + int ima_must_appraise_or_measure(struct inode *inode, int mask, int function); 111 111 int ima_must_measure(struct inode *inode, int mask, int function); 112 112 int ima_collect_measurement(struct integrity_iint_cache *iint, 113 113 struct file *file); ··· 125 123 struct integrity_iint_cache *integrity_iint_find(struct inode *inode); 126 124 127 125 /* IMA policy related functions */ 128 - enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; 126 + enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, POST_SETATTR }; 129 127 130 - int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); 128 + int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, 129 + int flags); 131 130 void ima_init_policy(void); 132 131 void ima_update_policy(void); 133 132 ssize_t ima_parse_add_rule(char *); 134 133 void ima_delete_rules(void); 134 + 135 + /* Appraise integrity measurements */ 136 + #define IMA_APPRAISE_ENFORCE 0x01 137 + #define IMA_APPRAISE_FIX 0x02 138 + 139 + #ifdef CONFIG_IMA_APPRAISE 140 + int ima_appraise_measurement(struct integrity_iint_cache *iint, 141 + struct file *file, const unsigned char *filename); 142 + int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask); 143 + void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); 144 + 145 + #else 146 + static inline int ima_appraise_measurement(struct integrity_iint_cache *iint, 147 + struct file *file, 148 + const unsigned char *filename) 149 + { 150 + return INTEGRITY_UNKNOWN; 151 + } 152 + 153 + static inline int ima_must_appraise(struct inode *inode, 154 + enum ima_hooks func, int mask) 155 + { 156 + return 0; 157 + } 158 + 159 + static inline void ima_update_xattr(struct integrity_iint_cache *iint, 160 + struct file *file) 161 + { 162 + } 163 + #endif 135 164 136 165 /* LSM based policy rules require audit */ 137 166 #ifdef CONFIG_IMA_LSM_RULES
+36 -14
security/integrity/ima/ima_api.c
··· 9 9 * License. 10 10 * 11 11 * File: ima_api.c 12 - * Implements must_measure, collect_measurement, store_measurement, 13 - * and store_template. 12 + * Implements must_appraise_or_measure, collect_measurement, 13 + * appraise_measurement, store_measurement and store_template. 14 14 */ 15 15 #include <linux/module.h> 16 16 #include <linux/slab.h> 17 - 17 + #include <linux/file.h> 18 + #include <linux/fs.h> 19 + #include <linux/xattr.h> 20 + #include <linux/evm.h> 18 21 #include "ima.h" 22 + 19 23 static const char *IMA_TEMPLATE_NAME = "ima"; 20 24 21 25 /* ··· 97 93 } 98 94 99 95 /** 100 - * ima_must_measure - measure decision based on policy. 96 + * ima_must_appraise_or_measure - appraise & measure decision based on policy. 101 97 * @inode: pointer to inode to measure 102 98 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) 103 99 * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) ··· 109 105 * mask: contains the permission mask 110 106 * fsmagic: hex value 111 107 * 112 - * Return 0 to measure. For matching a DONT_MEASURE policy, no policy, 113 - * or other error, return an error code. 114 - */ 108 + * Returns IMA_MEASURE, IMA_APPRAISE mask. 109 + * 110 + */ 111 + int ima_must_appraise_or_measure(struct inode *inode, int mask, int function) 112 + { 113 + int flags = IMA_MEASURE | IMA_APPRAISE; 114 + 115 + if (!ima_appraise) 116 + flags &= ~IMA_APPRAISE; 117 + 118 + return ima_match_policy(inode, function, mask, flags); 119 + } 120 + 115 121 int ima_must_measure(struct inode *inode, int mask, int function) 116 122 { 117 - int must_measure; 118 - 119 - must_measure = ima_match_policy(inode, function, mask); 120 - return must_measure ? 0 : -EACCES; 123 + return ima_match_policy(inode, function, mask, IMA_MEASURE); 121 124 } 122 125 123 126 /* ··· 140 129 int ima_collect_measurement(struct integrity_iint_cache *iint, 141 130 struct file *file) 142 131 { 143 - int result = -EEXIST; 132 + struct inode *inode = file->f_dentry->d_inode; 133 + const char *filename = file->f_dentry->d_name.name; 134 + int result = 0; 144 135 145 - if (!(iint->flags & IMA_MEASURED)) { 136 + if (!(iint->flags & IMA_COLLECTED)) { 146 137 u64 i_version = file->f_dentry->d_inode->i_version; 147 138 148 139 memset(iint->digest, 0, IMA_DIGEST_SIZE); 149 140 result = ima_calc_hash(file, iint->digest); 150 - if (!result) 141 + if (!result) { 151 142 iint->version = i_version; 143 + iint->flags |= IMA_COLLECTED; 144 + } 152 145 } 146 + if (result) 147 + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 148 + filename, "collect_data", "failed", 149 + result, 0); 153 150 return result; 154 151 } 155 152 ··· 185 166 struct inode *inode = file->f_dentry->d_inode; 186 167 struct ima_template_entry *entry; 187 168 int violation = 0; 169 + 170 + if (iint->flags & IMA_MEASURED) 171 + return; 188 172 189 173 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 190 174 if (!entry) {
+168
security/integrity/ima/ima_appraise.c
··· 1 + /* 2 + * Copyright (C) 2011 IBM Corporation 3 + * 4 + * Author: 5 + * Mimi Zohar <zohar@us.ibm.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation, version 2 of the License. 10 + */ 11 + #include <linux/module.h> 12 + #include <linux/file.h> 13 + #include <linux/fs.h> 14 + #include <linux/xattr.h> 15 + #include <linux/magic.h> 16 + #include <linux/ima.h> 17 + #include <linux/evm.h> 18 + 19 + #include "ima.h" 20 + 21 + static int __init default_appraise_setup(char *str) 22 + { 23 + if (strncmp(str, "off", 3) == 0) 24 + ima_appraise = 0; 25 + else if (strncmp(str, "fix", 3) == 0) 26 + ima_appraise = IMA_APPRAISE_FIX; 27 + return 1; 28 + } 29 + 30 + __setup("ima_appraise=", default_appraise_setup); 31 + 32 + /* 33 + * ima_must_appraise - set appraise flag 34 + * 35 + * Return 1 to appraise 36 + */ 37 + int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask) 38 + { 39 + return 0; 40 + } 41 + 42 + static void ima_fix_xattr(struct dentry *dentry, 43 + struct integrity_iint_cache *iint) 44 + { 45 + iint->digest[0] = IMA_XATTR_DIGEST; 46 + __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, 47 + iint->digest, IMA_DIGEST_SIZE + 1, 0); 48 + } 49 + 50 + /* 51 + * ima_appraise_measurement - appraise file measurement 52 + * 53 + * Call evm_verifyxattr() to verify the integrity of 'security.ima'. 54 + * Assuming success, compare the xattr hash with the collected measurement. 55 + * 56 + * Return 0 on success, error code otherwise 57 + */ 58 + int ima_appraise_measurement(struct integrity_iint_cache *iint, 59 + struct file *file, const unsigned char *filename) 60 + { 61 + struct dentry *dentry = file->f_dentry; 62 + struct inode *inode = dentry->d_inode; 63 + u8 xattr_value[IMA_DIGEST_SIZE]; 64 + enum integrity_status status = INTEGRITY_UNKNOWN; 65 + const char *op = "appraise_data"; 66 + char *cause = "unknown"; 67 + int rc; 68 + 69 + if (!ima_appraise) 70 + return 0; 71 + if (!inode->i_op->getxattr) 72 + return INTEGRITY_UNKNOWN; 73 + 74 + if (iint->flags & IMA_APPRAISED) 75 + return iint->ima_status; 76 + 77 + rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, xattr_value, 78 + IMA_DIGEST_SIZE); 79 + if (rc <= 0) { 80 + if (rc && rc != -ENODATA) 81 + goto out; 82 + 83 + cause = "missing-hash"; 84 + status = 85 + (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL; 86 + goto out; 87 + } 88 + 89 + status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint); 90 + if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) { 91 + if ((status == INTEGRITY_NOLABEL) 92 + || (status == INTEGRITY_NOXATTRS)) 93 + cause = "missing-HMAC"; 94 + else if (status == INTEGRITY_FAIL) 95 + cause = "invalid-HMAC"; 96 + goto out; 97 + } 98 + 99 + rc = memcmp(xattr_value, iint->digest, IMA_DIGEST_SIZE); 100 + if (rc) { 101 + status = INTEGRITY_FAIL; 102 + cause = "invalid-hash"; 103 + print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE, 104 + xattr_value, IMA_DIGEST_SIZE); 105 + print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE, 106 + iint->digest, IMA_DIGEST_SIZE); 107 + goto out; 108 + } 109 + status = INTEGRITY_PASS; 110 + iint->flags |= IMA_APPRAISED; 111 + out: 112 + if (status != INTEGRITY_PASS) { 113 + if (ima_appraise & IMA_APPRAISE_FIX) { 114 + ima_fix_xattr(dentry, iint); 115 + status = INTEGRITY_PASS; 116 + } 117 + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, 118 + op, cause, rc, 0); 119 + } 120 + iint->ima_status = status; 121 + return status; 122 + } 123 + 124 + /* 125 + * ima_update_xattr - update 'security.ima' hash value 126 + */ 127 + void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) 128 + { 129 + struct dentry *dentry = file->f_dentry; 130 + int rc = 0; 131 + 132 + rc = ima_collect_measurement(iint, file); 133 + if (rc < 0) 134 + return; 135 + ima_fix_xattr(dentry, iint); 136 + } 137 + 138 + /** 139 + * ima_inode_post_setattr - reflect file metadata changes 140 + * @dentry: pointer to the affected dentry 141 + * 142 + * Changes to a dentry's metadata might result in needing to appraise. 143 + * 144 + * This function is called from notify_change(), which expects the caller 145 + * to lock the inode's i_mutex. 146 + */ 147 + void ima_inode_post_setattr(struct dentry *dentry) 148 + { 149 + struct inode *inode = dentry->d_inode; 150 + struct integrity_iint_cache *iint; 151 + int must_appraise, rc; 152 + 153 + if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode) 154 + || !inode->i_op->removexattr) 155 + return; 156 + 157 + must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); 158 + iint = integrity_iint_find(inode); 159 + if (iint) { 160 + if (must_appraise) 161 + iint->flags |= IMA_APPRAISE; 162 + else 163 + iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED); 164 + } 165 + if (!must_appraise) 166 + rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); 167 + return; 168 + }
+7 -1
security/integrity/ima/ima_crypto.c
··· 48 48 struct scatterlist sg[1]; 49 49 loff_t i_size, offset = 0; 50 50 char *rbuf; 51 - int rc; 51 + int rc, read = 0; 52 52 53 53 rc = init_desc(&desc); 54 54 if (rc != 0) ··· 58 58 if (!rbuf) { 59 59 rc = -ENOMEM; 60 60 goto out; 61 + } 62 + if (!(file->f_mode & FMODE_READ)) { 63 + file->f_mode |= FMODE_READ; 64 + read = 1; 61 65 } 62 66 i_size = i_size_read(file->f_dentry->d_inode); 63 67 while (offset < i_size) { ··· 84 80 kfree(rbuf); 85 81 if (!rc) 86 82 rc = crypto_hash_final(&desc, digest); 83 + if (read) 84 + file->f_mode &= ~FMODE_READ; 87 85 out: 88 86 crypto_free_hash(desc.tfm); 89 87 return rc;
+54 -25
security/integrity/ima/ima_main.c
··· 22 22 #include <linux/mount.h> 23 23 #include <linux/mman.h> 24 24 #include <linux/slab.h> 25 + #include <linux/xattr.h> 25 26 #include <linux/ima.h> 26 27 27 28 #include "ima.h" 28 29 29 30 int ima_initialized; 31 + 32 + #ifdef CONFIG_IMA_APPRAISE 33 + int ima_appraise = IMA_APPRAISE_ENFORCE; 34 + #else 35 + int ima_appraise; 36 + #endif 30 37 31 38 char *ima_hash = "sha1"; 32 39 static int __init hash_setup(char *str) ··· 59 52 struct dentry *dentry = file->f_path.dentry; 60 53 struct inode *inode = dentry->d_inode; 61 54 fmode_t mode = file->f_mode; 62 - int rc; 55 + int must_measure; 63 56 bool send_tomtou = false, send_writers = false; 64 57 unsigned char *pathname = NULL, *pathbuf = NULL; 65 58 ··· 74 67 goto out; 75 68 } 76 69 77 - rc = ima_must_measure(inode, MAY_READ, FILE_CHECK); 78 - if (rc < 0) 70 + must_measure = ima_must_measure(inode, MAY_READ, FILE_CHECK); 71 + if (!must_measure) 79 72 goto out; 80 73 81 74 if (atomic_read(&inode->i_writecount) > 0) ··· 107 100 } 108 101 109 102 static void ima_check_last_writer(struct integrity_iint_cache *iint, 110 - struct inode *inode, 111 - struct file *file) 103 + struct inode *inode, struct file *file) 112 104 { 113 105 fmode_t mode = file->f_mode; 114 106 115 - mutex_lock(&iint->mutex); 116 - if (mode & FMODE_WRITE && 117 - atomic_read(&inode->i_writecount) == 1 && 118 - iint->version != inode->i_version) 119 - iint->flags &= ~IMA_MEASURED; 120 - mutex_unlock(&iint->mutex); 107 + if (!(mode & FMODE_WRITE)) 108 + return; 109 + 110 + mutex_lock(&inode->i_mutex); 111 + if (atomic_read(&inode->i_writecount) == 1 && 112 + iint->version != inode->i_version) { 113 + iint->flags &= ~(IMA_COLLECTED | IMA_APPRAISED | IMA_MEASURED); 114 + if (iint->flags & IMA_APPRAISE) 115 + ima_update_xattr(iint, file); 116 + } 117 + mutex_unlock(&inode->i_mutex); 121 118 } 122 119 123 120 /** ··· 151 140 struct inode *inode = file->f_dentry->d_inode; 152 141 struct integrity_iint_cache *iint; 153 142 unsigned char *pathname = NULL, *pathbuf = NULL; 154 - int rc = 0; 143 + int rc = -ENOMEM, action, must_appraise; 155 144 156 145 if (!ima_initialized || !S_ISREG(inode->i_mode)) 157 146 return 0; 158 147 159 - rc = ima_must_measure(inode, mask, function); 160 - if (rc != 0) 161 - return rc; 148 + /* Determine if in appraise/measurement policy, 149 + * returns IMA_MEASURE, IMA_APPRAISE bitmask. */ 150 + action = ima_must_appraise_or_measure(inode, mask, function); 151 + if (!action) 152 + return 0; 153 + 162 154 retry: 163 155 iint = integrity_iint_find(inode); 164 156 if (!iint) { ··· 171 157 return rc; 172 158 } 173 159 174 - mutex_lock(&iint->mutex); 160 + must_appraise = action & IMA_APPRAISE; 175 161 176 - rc = iint->flags & IMA_MEASURED ? 1 : 0; 177 - if (rc != 0) 162 + mutex_lock(&inode->i_mutex); 163 + 164 + /* Determine if already appraised/measured based on bitmask 165 + * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED) */ 166 + iint->flags |= action; 167 + action &= ~((iint->flags & (IMA_MEASURED | IMA_APPRAISED)) >> 1); 168 + 169 + /* Nothing to do, just return existing appraised status */ 170 + if (!action) { 171 + if (iint->flags & IMA_APPRAISED) 172 + rc = iint->ima_status; 178 173 goto out; 174 + } 179 175 180 176 rc = ima_collect_measurement(iint, file); 181 177 if (rc != 0) ··· 201 177 pathname = NULL; 202 178 } 203 179 } 204 - ima_store_measurement(iint, file, !pathname ? filename : pathname); 180 + if (action & IMA_MEASURE) 181 + ima_store_measurement(iint, file, 182 + !pathname ? filename : pathname); 183 + if (action & IMA_APPRAISE) 184 + rc = ima_appraise_measurement(iint, file, 185 + !pathname ? filename : pathname); 205 186 kfree(pathbuf); 206 187 out: 207 - mutex_unlock(&iint->mutex); 208 - return rc; 188 + mutex_unlock(&inode->i_mutex); 189 + return (rc && must_appraise) ? -EACCES : 0; 209 190 } 210 191 211 192 /** ··· 226 197 */ 227 198 int ima_file_mmap(struct file *file, unsigned long prot) 228 199 { 229 - int rc; 200 + int rc = 0; 230 201 231 202 if (!file) 232 203 return 0; 233 204 if (prot & PROT_EXEC) 234 205 rc = process_measurement(file, file->f_dentry->d_name.name, 235 206 MAY_EXEC, FILE_MMAP); 236 - return 0; 207 + return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; 237 208 } 238 209 239 210 /** ··· 257 228 (strcmp(bprm->filename, bprm->interp) == 0) ? 258 229 bprm->filename : bprm->interp, 259 230 MAY_EXEC, BPRM_CHECK); 260 - return 0; 231 + return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; 261 232 } 262 233 263 234 /** ··· 278 249 rc = process_measurement(file, file->f_dentry->d_name.name, 279 250 mask & (MAY_READ | MAY_WRITE | MAY_EXEC), 280 251 FILE_CHECK); 281 - return 0; 252 + return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; 282 253 } 283 254 EXPORT_SYMBOL_GPL(ima_file_check); 284 255
+24 -8
security/integrity/ima/ima_policy.c
··· 25 25 #define IMA_FSMAGIC 0x0004 26 26 #define IMA_UID 0x0008 27 27 28 - enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE }; 28 + #define UNKNOWN 0 29 + #define MEASURE 1 /* same as IMA_MEASURE */ 30 + #define DONT_MEASURE 2 31 + #define MEASURE_MASK 3 32 + #define APPRAISE 4 /* same as IMA_APPRAISE */ 33 + #define DONT_APPRAISE 8 34 + #define APPRAISE_MASK 12 29 35 30 36 #define MAX_LSM_RULES 6 31 37 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, ··· 40 34 41 35 struct ima_measure_rule_entry { 42 36 struct list_head list; 43 - enum ima_action action; 37 + int action; 44 38 unsigned int flags; 45 39 enum ima_hooks func; 46 40 int mask; ··· 169 163 * as elements in the list are never deleted, nor does the list 170 164 * change.) 171 165 */ 172 - int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) 166 + int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, 167 + int flags) 173 168 { 174 169 struct ima_measure_rule_entry *entry; 170 + int action = 0, actmask = flags | (flags << 1); 175 171 176 172 list_for_each_entry(entry, ima_measure, list) { 177 - bool rc; 178 173 179 - rc = ima_match_rules(entry, inode, func, mask); 180 - if (rc) 181 - return entry->action; 174 + if (!(entry->action & actmask)) 175 + continue; 176 + 177 + if (!ima_match_rules(entry, inode, func, mask)) 178 + continue; 179 + 180 + action |= (entry->action & (IMA_APPRAISE | IMA_MEASURE)); 181 + actmask &= (entry->action & APPRAISE_MASK) ? 182 + ~APPRAISE_MASK : ~MEASURE_MASK; 183 + if (!actmask) 184 + break; 182 185 } 183 - return 0; 186 + 187 + return action; 184 188 } 185 189 186 190 /**
+6 -2
security/integrity/integrity.h
··· 16 16 #include <crypto/sha.h> 17 17 18 18 /* iint cache flags */ 19 - #define IMA_MEASURED 0x01 19 + #define IMA_MEASURE 0x01 20 + #define IMA_MEASURED 0x02 21 + #define IMA_APPRAISE 0x04 22 + #define IMA_APPRAISED 0x08 23 + #define IMA_COLLECTED 0x10 20 24 21 25 enum evm_ima_xattr_type { 22 26 IMA_XATTR_DIGEST = 0x01, ··· 40 36 u64 version; /* track inode changes */ 41 37 unsigned char flags; 42 38 u8 digest[SHA1_DIGEST_SIZE]; 43 - struct mutex mutex; /* protects: version, flags, digest */ 39 + enum integrity_status ima_status; 44 40 enum integrity_status evm_status; 45 41 }; 46 42