root/drivers/char/tpm/eventlog/common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tpm_bios_measurements_open
  2. tpm_bios_measurements_release
  3. tpm_read_log
  4. tpm_bios_log_setup
  5. tpm_bios_log_teardown

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

/* [<][>][^][v][top][bottom][index][help] */