1 /* 2 * Copyright (C) 2008 IBM Corporation 3 * 4 * Author: Mimi Zohar <zohar@us.ibm.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2 of the 9 * License. 10 * 11 * File: ima_api.c 12 * Implements must_appraise_or_measure, collect_measurement, 13 * appraise_measurement, store_measurement and store_template. 14 */ 15 #include <linux/module.h> 16 #include <linux/slab.h> 17 #include <linux/file.h> 18 #include <linux/fs.h> 19 #include <linux/xattr.h> 20 #include <linux/evm.h> 21 #include "ima.h" 22 23 static const char *IMA_TEMPLATE_NAME = "ima"; 24 25 /* 26 * ima_store_template - store ima template measurements 27 * 28 * Calculate the hash of a template entry, add the template entry 29 * to an ordered list of measurement entries maintained inside the kernel, 30 * and also update the aggregate integrity value (maintained inside the 31 * configured TPM PCR) over the hashes of the current list of measurement 32 * entries. 33 * 34 * Applications retrieve the current kernel-held measurement list through 35 * the securityfs entries in /sys/kernel/security/ima. The signed aggregate 36 * TPM PCR (called quote) can be retrieved using a TPM user space library 37 * and is used to validate the measurement list. 38 * 39 * Returns 0 on success, error code otherwise 40 */ 41 int ima_store_template(struct ima_template_entry *entry, 42 int violation, struct inode *inode) 43 { 44 const char *op = "add_template_measure"; 45 const char *audit_cause = "hashing_error"; 46 int result; 47 struct ima_digest_data hash; 48 49 memset(entry->digest, 0, sizeof(entry->digest)); 50 entry->template_name = IMA_TEMPLATE_NAME; 51 entry->template_len = sizeof(entry->template); 52 53 if (!violation) { 54 result = ima_calc_buffer_hash(&entry->template, 55 entry->template_len, &hash); 56 if (result < 0) { 57 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, 58 entry->template_name, op, 59 audit_cause, result, 0); 60 return result; 61 } 62 memcpy(entry->digest, hash.digest, hash.length); 63 } 64 result = ima_add_template_entry(entry, violation, op, inode); 65 return result; 66 } 67 68 /* 69 * ima_add_violation - add violation to measurement list. 70 * 71 * Violations are flagged in the measurement list with zero hash values. 72 * By extending the PCR with 0xFF's instead of with zeroes, the PCR 73 * value is invalidated. 74 */ 75 void ima_add_violation(struct inode *inode, const unsigned char *filename, 76 const char *op, const char *cause) 77 { 78 struct ima_template_entry *entry; 79 int violation = 1; 80 int result; 81 82 /* can overflow, only indicator */ 83 atomic_long_inc(&ima_htable.violations); 84 85 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 86 if (!entry) { 87 result = -ENOMEM; 88 goto err_out; 89 } 90 memset(&entry->template, 0, sizeof(entry->template)); 91 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX); 92 result = ima_store_template(entry, violation, inode); 93 if (result < 0) 94 kfree(entry); 95 err_out: 96 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, 97 op, cause, result, 0); 98 } 99 100 /** 101 * ima_get_action - appraise & measure decision based on policy. 102 * @inode: pointer to inode to measure 103 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) 104 * @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK) 105 * 106 * The policy is defined in terms of keypairs: 107 * subj=, obj=, type=, func=, mask=, fsmagic= 108 * subj,obj, and type: are LSM specific. 109 * func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK 110 * mask: contains the permission mask 111 * fsmagic: hex value 112 * 113 * Returns IMA_MEASURE, IMA_APPRAISE mask. 114 * 115 */ 116 int ima_get_action(struct inode *inode, int mask, int function) 117 { 118 int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE; 119 120 if (!ima_appraise) 121 flags &= ~IMA_APPRAISE; 122 123 return ima_match_policy(inode, function, mask, flags); 124 } 125 126 int ima_must_measure(struct inode *inode, int mask, int function) 127 { 128 return ima_match_policy(inode, function, mask, IMA_MEASURE); 129 } 130 131 /* 132 * ima_collect_measurement - collect file measurement 133 * 134 * Calculate the file hash, if it doesn't already exist, 135 * storing the measurement and i_version in the iint. 136 * 137 * Must be called with iint->mutex held. 138 * 139 * Return 0 on success, error code otherwise 140 */ 141 int ima_collect_measurement(struct integrity_iint_cache *iint, 142 struct file *file) 143 { 144 struct inode *inode = file_inode(file); 145 const char *filename = file->f_dentry->d_name.name; 146 int result = 0; 147 148 if (!(iint->flags & IMA_COLLECTED)) { 149 u64 i_version = file_inode(file)->i_version; 150 151 /* use default hash algorithm */ 152 iint->ima_hash.algo = ima_hash_algo; 153 result = ima_calc_file_hash(file, &iint->ima_hash); 154 if (!result) { 155 iint->version = i_version; 156 iint->flags |= IMA_COLLECTED; 157 } 158 } 159 if (result) 160 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 161 filename, "collect_data", "failed", 162 result, 0); 163 return result; 164 } 165 166 /* 167 * ima_store_measurement - store file measurement 168 * 169 * Create an "ima" template and then store the template by calling 170 * ima_store_template. 171 * 172 * We only get here if the inode has not already been measured, 173 * but the measurement could already exist: 174 * - multiple copies of the same file on either the same or 175 * different filesystems. 176 * - the inode was previously flushed as well as the iint info, 177 * containing the hashing info. 178 * 179 * Must be called with iint->mutex held. 180 */ 181 void ima_store_measurement(struct integrity_iint_cache *iint, 182 struct file *file, const unsigned char *filename) 183 { 184 const char *op = "add_template_measure"; 185 const char *audit_cause = "ENOMEM"; 186 int result = -ENOMEM; 187 struct inode *inode = file_inode(file); 188 struct ima_template_entry *entry; 189 int violation = 0; 190 191 if (iint->flags & IMA_MEASURED) 192 return; 193 194 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 195 if (!entry) { 196 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, 197 op, audit_cause, result, 0); 198 return; 199 } 200 memset(&entry->template, 0, sizeof(entry->template)); 201 if (iint->ima_hash.algo != ima_hash_algo) { 202 struct ima_digest_data hash; 203 204 hash.algo = ima_hash_algo; 205 result = ima_calc_file_hash(file, &hash); 206 if (result) 207 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 208 filename, "collect_data", "failed", 209 result, 0); 210 else 211 memcpy(entry->template.digest, hash.digest, 212 hash.length); 213 } else 214 memcpy(entry->template.digest, iint->ima_hash.digest, 215 iint->ima_hash.length); 216 strcpy(entry->template.file_name, 217 (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ? 218 file->f_dentry->d_name.name : filename); 219 220 result = ima_store_template(entry, violation, inode); 221 if (!result || result == -EEXIST) 222 iint->flags |= IMA_MEASURED; 223 if (result < 0) 224 kfree(entry); 225 } 226 227 void ima_audit_measurement(struct integrity_iint_cache *iint, 228 const unsigned char *filename) 229 { 230 struct audit_buffer *ab; 231 char hash[(iint->ima_hash.length * 2) + 1]; 232 int i; 233 234 if (iint->flags & IMA_AUDITED) 235 return; 236 237 for (i = 0; i < iint->ima_hash.length; i++) 238 hex_byte_pack(hash + (i * 2), iint->ima_hash.digest[i]); 239 hash[i * 2] = '\0'; 240 241 ab = audit_log_start(current->audit_context, GFP_KERNEL, 242 AUDIT_INTEGRITY_RULE); 243 if (!ab) 244 return; 245 246 audit_log_format(ab, "file="); 247 audit_log_untrustedstring(ab, filename); 248 audit_log_format(ab, " hash="); 249 audit_log_untrustedstring(ab, hash); 250 251 audit_log_task_info(ab, current); 252 audit_log_end(ab); 253 254 iint->flags |= IMA_AUDITED; 255 } 256 257 const char *ima_d_path(struct path *path, char **pathbuf) 258 { 259 char *pathname = NULL; 260 261 /* We will allow 11 spaces for ' (deleted)' to be appended */ 262 *pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); 263 if (*pathbuf) { 264 pathname = d_path(path, *pathbuf, PATH_MAX + 11); 265 if (IS_ERR(pathname)) { 266 kfree(*pathbuf); 267 *pathbuf = NULL; 268 pathname = NULL; 269 } 270 } 271 return pathname; 272 } 273