1 /* 2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation 3 * 4 * Authors: 5 * Kylene Hall <kjhall@us.ibm.com> 6 * Reiner Sailer <sailer@us.ibm.com> 7 * Mimi Zohar <zohar@us.ibm.com> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation, version 2 of the 12 * License. 13 * 14 * File: ima_fs.c 15 * implemenents security file system for reporting 16 * current measurement list and IMA statistics 17 */ 18 #include <linux/module.h> 19 #include <linux/seq_file.h> 20 #include <linux/rculist.h> 21 #include <linux/rcupdate.h> 22 #include <linux/parser.h> 23 24 #include "ima.h" 25 26 static int valid_policy = 1; 27 #define TMPBUFLEN 12 28 static ssize_t ima_show_htable_value(char __user *buf, size_t count, 29 loff_t *ppos, atomic_long_t *val) 30 { 31 char tmpbuf[TMPBUFLEN]; 32 ssize_t len; 33 34 len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val)); 35 return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); 36 } 37 38 static ssize_t ima_show_htable_violations(struct file *filp, 39 char __user *buf, 40 size_t count, loff_t *ppos) 41 { 42 return ima_show_htable_value(buf, count, ppos, &ima_htable.violations); 43 } 44 45 static struct file_operations ima_htable_violations_ops = { 46 .read = ima_show_htable_violations 47 }; 48 49 static ssize_t ima_show_measurements_count(struct file *filp, 50 char __user *buf, 51 size_t count, loff_t *ppos) 52 { 53 return ima_show_htable_value(buf, count, ppos, &ima_htable.len); 54 55 } 56 57 static struct file_operations ima_measurements_count_ops = { 58 .read = ima_show_measurements_count 59 }; 60 61 /* returns pointer to hlist_node */ 62 static void *ima_measurements_start(struct seq_file *m, loff_t *pos) 63 { 64 loff_t l = *pos; 65 struct ima_queue_entry *qe; 66 67 /* we need a lock since pos could point beyond last element */ 68 rcu_read_lock(); 69 list_for_each_entry_rcu(qe, &ima_measurements, later) { 70 if (!l--) { 71 rcu_read_unlock(); 72 return qe; 73 } 74 } 75 rcu_read_unlock(); 76 return NULL; 77 } 78 79 static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) 80 { 81 struct ima_queue_entry *qe = v; 82 83 /* lock protects when reading beyond last element 84 * against concurrent list-extension 85 */ 86 rcu_read_lock(); 87 qe = list_entry(rcu_dereference(qe->later.next), 88 struct ima_queue_entry, later); 89 rcu_read_unlock(); 90 (*pos)++; 91 92 return (&qe->later == &ima_measurements) ? NULL : qe; 93 } 94 95 static void ima_measurements_stop(struct seq_file *m, void *v) 96 { 97 } 98 99 static void ima_putc(struct seq_file *m, void *data, int datalen) 100 { 101 while (datalen--) 102 seq_putc(m, *(char *)data++); 103 } 104 105 /* print format: 106 * 32bit-le=pcr# 107 * char[20]=template digest 108 * 32bit-le=template name size 109 * char[n]=template name 110 * eventdata[n]=template specific data 111 */ 112 static int ima_measurements_show(struct seq_file *m, void *v) 113 { 114 /* the list never shrinks, so we don't need a lock here */ 115 struct ima_queue_entry *qe = v; 116 struct ima_template_entry *e; 117 int namelen; 118 u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; 119 120 /* get entry */ 121 e = qe->entry; 122 if (e == NULL) 123 return -1; 124 125 /* 126 * 1st: PCRIndex 127 * PCR used is always the same (config option) in 128 * little-endian format 129 */ 130 ima_putc(m, &pcr, sizeof pcr); 131 132 /* 2nd: template digest */ 133 ima_putc(m, e->digest, IMA_DIGEST_SIZE); 134 135 /* 3rd: template name size */ 136 namelen = strlen(e->template_name); 137 ima_putc(m, &namelen, sizeof namelen); 138 139 /* 4th: template name */ 140 ima_putc(m, e->template_name, namelen); 141 142 /* 5th: template specific data */ 143 ima_template_show(m, (struct ima_template_data *)&e->template, 144 IMA_SHOW_BINARY); 145 return 0; 146 } 147 148 static struct seq_operations ima_measurments_seqops = { 149 .start = ima_measurements_start, 150 .next = ima_measurements_next, 151 .stop = ima_measurements_stop, 152 .show = ima_measurements_show 153 }; 154 155 static int ima_measurements_open(struct inode *inode, struct file *file) 156 { 157 return seq_open(file, &ima_measurments_seqops); 158 } 159 160 static struct file_operations ima_measurements_ops = { 161 .open = ima_measurements_open, 162 .read = seq_read, 163 .llseek = seq_lseek, 164 .release = seq_release, 165 }; 166 167 static void ima_print_digest(struct seq_file *m, u8 *digest) 168 { 169 int i; 170 171 for (i = 0; i < IMA_DIGEST_SIZE; i++) 172 seq_printf(m, "%02x", *(digest + i)); 173 } 174 175 void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show) 176 { 177 struct ima_template_data *entry = e; 178 int namelen; 179 180 switch (show) { 181 case IMA_SHOW_ASCII: 182 ima_print_digest(m, entry->digest); 183 seq_printf(m, " %s\n", entry->file_name); 184 break; 185 case IMA_SHOW_BINARY: 186 ima_putc(m, entry->digest, IMA_DIGEST_SIZE); 187 188 namelen = strlen(entry->file_name); 189 ima_putc(m, &namelen, sizeof namelen); 190 ima_putc(m, entry->file_name, namelen); 191 default: 192 break; 193 } 194 } 195 196 /* print in ascii */ 197 static int ima_ascii_measurements_show(struct seq_file *m, void *v) 198 { 199 /* the list never shrinks, so we don't need a lock here */ 200 struct ima_queue_entry *qe = v; 201 struct ima_template_entry *e; 202 203 /* get entry */ 204 e = qe->entry; 205 if (e == NULL) 206 return -1; 207 208 /* 1st: PCR used (config option) */ 209 seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX); 210 211 /* 2nd: SHA1 template hash */ 212 ima_print_digest(m, e->digest); 213 214 /* 3th: template name */ 215 seq_printf(m, " %s ", e->template_name); 216 217 /* 4th: template specific data */ 218 ima_template_show(m, (struct ima_template_data *)&e->template, 219 IMA_SHOW_ASCII); 220 return 0; 221 } 222 223 static struct seq_operations ima_ascii_measurements_seqops = { 224 .start = ima_measurements_start, 225 .next = ima_measurements_next, 226 .stop = ima_measurements_stop, 227 .show = ima_ascii_measurements_show 228 }; 229 230 static int ima_ascii_measurements_open(struct inode *inode, struct file *file) 231 { 232 return seq_open(file, &ima_ascii_measurements_seqops); 233 } 234 235 static struct file_operations ima_ascii_measurements_ops = { 236 .open = ima_ascii_measurements_open, 237 .read = seq_read, 238 .llseek = seq_lseek, 239 .release = seq_release, 240 }; 241 242 static ssize_t ima_write_policy(struct file *file, const char __user *buf, 243 size_t datalen, loff_t *ppos) 244 { 245 char *data; 246 int rc; 247 248 if (datalen >= PAGE_SIZE) 249 return -ENOMEM; 250 if (*ppos != 0) { 251 /* No partial writes. */ 252 return -EINVAL; 253 } 254 data = kmalloc(datalen + 1, GFP_KERNEL); 255 if (!data) 256 return -ENOMEM; 257 258 if (copy_from_user(data, buf, datalen)) { 259 kfree(data); 260 return -EFAULT; 261 } 262 *(data + datalen) = '\0'; 263 rc = ima_parse_add_rule(data); 264 if (rc < 0) { 265 datalen = -EINVAL; 266 valid_policy = 0; 267 } 268 269 kfree(data); 270 return datalen; 271 } 272 273 static struct dentry *ima_dir; 274 static struct dentry *binary_runtime_measurements; 275 static struct dentry *ascii_runtime_measurements; 276 static struct dentry *runtime_measurements_count; 277 static struct dentry *violations; 278 static struct dentry *ima_policy; 279 280 /* 281 * ima_release_policy - start using the new measure policy rules. 282 * 283 * Initially, ima_measure points to the default policy rules, now 284 * point to the new policy rules, and remove the securityfs policy file. 285 */ 286 static int ima_release_policy(struct inode *inode, struct file *file) 287 { 288 if (!valid_policy) { 289 ima_delete_rules(); 290 return 0; 291 } 292 ima_update_policy(); 293 securityfs_remove(ima_policy); 294 ima_policy = NULL; 295 return 0; 296 } 297 298 static struct file_operations ima_measure_policy_ops = { 299 .write = ima_write_policy, 300 .release = ima_release_policy 301 }; 302 303 int ima_fs_init(void) 304 { 305 ima_dir = securityfs_create_dir("ima", NULL); 306 if (IS_ERR(ima_dir)) 307 return -1; 308 309 binary_runtime_measurements = 310 securityfs_create_file("binary_runtime_measurements", 311 S_IRUSR | S_IRGRP, ima_dir, NULL, 312 &ima_measurements_ops); 313 if (IS_ERR(binary_runtime_measurements)) 314 goto out; 315 316 ascii_runtime_measurements = 317 securityfs_create_file("ascii_runtime_measurements", 318 S_IRUSR | S_IRGRP, ima_dir, NULL, 319 &ima_ascii_measurements_ops); 320 if (IS_ERR(ascii_runtime_measurements)) 321 goto out; 322 323 runtime_measurements_count = 324 securityfs_create_file("runtime_measurements_count", 325 S_IRUSR | S_IRGRP, ima_dir, NULL, 326 &ima_measurements_count_ops); 327 if (IS_ERR(runtime_measurements_count)) 328 goto out; 329 330 violations = 331 securityfs_create_file("violations", S_IRUSR | S_IRGRP, 332 ima_dir, NULL, &ima_htable_violations_ops); 333 if (IS_ERR(violations)) 334 goto out; 335 336 ima_policy = securityfs_create_file("policy", 337 S_IRUSR | S_IRGRP | S_IWUSR, 338 ima_dir, NULL, 339 &ima_measure_policy_ops); 340 if (IS_ERR(ima_policy)) 341 goto out; 342 343 return 0; 344 out: 345 securityfs_remove(runtime_measurements_count); 346 securityfs_remove(ascii_runtime_measurements); 347 securityfs_remove(binary_runtime_measurements); 348 securityfs_remove(ima_dir); 349 securityfs_remove(ima_policy); 350 return -1; 351 } 352 353 void __exit ima_fs_cleanup(void) 354 { 355 securityfs_remove(violations); 356 securityfs_remove(runtime_measurements_count); 357 securityfs_remove(ascii_runtime_measurements); 358 securityfs_remove(binary_runtime_measurements); 359 securityfs_remove(ima_dir); 360 securityfs_remove(ima_policy); 361 } 362