1 /* 2 * Copyright (C) 2005, 2012 IBM Corporation 3 * 4 * Authors: 5 * Kent Yoder <key@linux.vnet.ibm.com> 6 * Seiji Munetoh <munetoh@jp.ibm.com> 7 * Stefan Berger <stefanb@us.ibm.com> 8 * Reiner Sailer <sailer@watson.ibm.com> 9 * Kylene Hall <kjhall@us.ibm.com> 10 * Nayna Jain <nayna@linux.vnet.ibm.com> 11 * 12 * Access to the event log created by a system's firmware / BIOS 13 * 14 * This program is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU General Public License 16 * as published by the Free Software Foundation; either version 17 * 2 of the License, or (at your option) any later version. 18 * 19 */ 20 21 #include <linux/seq_file.h> 22 #include <linux/fs.h> 23 #include <linux/security.h> 24 #include <linux/module.h> 25 #include <linux/tpm_eventlog.h> 26 27 #include "../tpm.h" 28 #include "common.h" 29 30 static int tpm_bios_measurements_open(struct inode *inode, 31 struct file *file) 32 { 33 int err; 34 struct seq_file *seq; 35 struct tpm_chip_seqops *chip_seqops; 36 const struct seq_operations *seqops; 37 struct tpm_chip *chip; 38 39 inode_lock(inode); 40 if (!inode->i_private) { 41 inode_unlock(inode); 42 return -ENODEV; 43 } 44 chip_seqops = (struct tpm_chip_seqops *)inode->i_private; 45 seqops = chip_seqops->seqops; 46 chip = chip_seqops->chip; 47 get_device(&chip->dev); 48 inode_unlock(inode); 49 50 /* now register seq file */ 51 err = seq_open(file, seqops); 52 if (!err) { 53 seq = file->private_data; 54 seq->private = chip; 55 } 56 57 return err; 58 } 59 60 static int tpm_bios_measurements_release(struct inode *inode, 61 struct file *file) 62 { 63 struct seq_file *seq = (struct seq_file *)file->private_data; 64 struct tpm_chip *chip = (struct tpm_chip *)seq->private; 65 66 put_device(&chip->dev); 67 68 return seq_release(inode, file); 69 } 70 71 static const struct file_operations tpm_bios_measurements_ops = { 72 .owner = THIS_MODULE, 73 .open = tpm_bios_measurements_open, 74 .read = seq_read, 75 .llseek = seq_lseek, 76 .release = tpm_bios_measurements_release, 77 }; 78 79 static int tpm_read_log(struct tpm_chip *chip) 80 { 81 int rc; 82 83 if (chip->log.bios_event_log != NULL) { 84 dev_dbg(&chip->dev, 85 "%s: ERROR - event log already initialized\n", 86 __func__); 87 return -EFAULT; 88 } 89 90 rc = tpm_read_log_acpi(chip); 91 if (rc != -ENODEV) 92 return rc; 93 94 rc = tpm_read_log_efi(chip); 95 if (rc != -ENODEV) 96 return rc; 97 98 return tpm_read_log_of(chip); 99 } 100 101 /* 102 * tpm_bios_log_setup() - Read the event log from the firmware 103 * @chip: TPM chip to use. 104 * 105 * If an event log is found then the securityfs files are setup to 106 * export it to userspace, otherwise nothing is done. 107 * 108 * Returns -ENODEV if the firmware has no event log or securityfs is not 109 * supported. 110 */ 111 int tpm_bios_log_setup(struct tpm_chip *chip) 112 { 113 const char *name = dev_name(&chip->dev); 114 unsigned int cnt; 115 int log_version; 116 int rc = 0; 117 118 rc = tpm_read_log(chip); 119 if (rc < 0) 120 return rc; 121 log_version = rc; 122 123 cnt = 0; 124 chip->bios_dir[cnt] = securityfs_create_dir(name, NULL); 125 /* NOTE: securityfs_create_dir can return ENODEV if securityfs is 126 * compiled out. The caller should ignore the ENODEV return code. 127 */ 128 if (IS_ERR(chip->bios_dir[cnt])) 129 goto err; 130 cnt++; 131 132 chip->bin_log_seqops.chip = chip; 133 if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) 134 chip->bin_log_seqops.seqops = 135 &tpm2_binary_b_measurements_seqops; 136 else 137 chip->bin_log_seqops.seqops = 138 &tpm1_binary_b_measurements_seqops; 139 140 141 chip->bios_dir[cnt] = 142 securityfs_create_file("binary_bios_measurements", 143 0440, chip->bios_dir[0], 144 (void *)&chip->bin_log_seqops, 145 &tpm_bios_measurements_ops); 146 if (IS_ERR(chip->bios_dir[cnt])) 147 goto err; 148 cnt++; 149 150 if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { 151 152 chip->ascii_log_seqops.chip = chip; 153 chip->ascii_log_seqops.seqops = 154 &tpm1_ascii_b_measurements_seqops; 155 156 chip->bios_dir[cnt] = 157 securityfs_create_file("ascii_bios_measurements", 158 0440, chip->bios_dir[0], 159 (void *)&chip->ascii_log_seqops, 160 &tpm_bios_measurements_ops); 161 if (IS_ERR(chip->bios_dir[cnt])) 162 goto err; 163 cnt++; 164 } 165 166 return 0; 167 168 err: 169 rc = PTR_ERR(chip->bios_dir[cnt]); 170 chip->bios_dir[cnt] = NULL; 171 tpm_bios_log_teardown(chip); 172 return rc; 173 } 174 175 void tpm_bios_log_teardown(struct tpm_chip *chip) 176 { 177 int i; 178 struct inode *inode; 179 180 /* securityfs_remove currently doesn't take care of handling sync 181 * between removal and opening of pseudo files. To handle this, a 182 * workaround is added by making i_private = NULL here during removal 183 * and to check it during open(), both within inode_lock()/unlock(). 184 * This design ensures that open() either safely gets kref or fails. 185 */ 186 for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) { 187 if (chip->bios_dir[i]) { 188 inode = d_inode(chip->bios_dir[i]); 189 inode_lock(inode); 190 inode->i_private = NULL; 191 inode_unlock(inode); 192 securityfs_remove(chip->bios_dir[i]); 193 } 194 } 195 } 196