cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

efi_secret.c (8906B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * efi_secret module
      4 *
      5 * Copyright (C) 2022 IBM Corporation
      6 * Author: Dov Murik <dovmurik@linux.ibm.com>
      7 */
      8
      9/**
     10 * DOC: efi_secret: Allow reading EFI confidential computing (coco) secret area
     11 * via securityfs interface.
     12 *
     13 * When the module is loaded (and securityfs is mounted, typically under
     14 * /sys/kernel/security), a "secrets/coco" directory is created in securityfs.
     15 * In it, a file is created for each secret entry.  The name of each such file
     16 * is the GUID of the secret entry, and its content is the secret data.
     17 */
     18
     19#include <linux/platform_device.h>
     20#include <linux/seq_file.h>
     21#include <linux/fs.h>
     22#include <linux/kernel.h>
     23#include <linux/init.h>
     24#include <linux/module.h>
     25#include <linux/io.h>
     26#include <linux/security.h>
     27#include <linux/efi.h>
     28#include <linux/cacheflush.h>
     29
     30#define EFI_SECRET_NUM_FILES 64
     31
     32struct efi_secret {
     33	struct dentry *secrets_dir;
     34	struct dentry *fs_dir;
     35	struct dentry *fs_files[EFI_SECRET_NUM_FILES];
     36	void __iomem *secret_data;
     37	u64 secret_data_len;
     38};
     39
     40/*
     41 * Structure of the EFI secret area
     42 *
     43 * Offset   Length
     44 * (bytes)  (bytes)  Usage
     45 * -------  -------  -----
     46 *       0       16  Secret table header GUID (must be 1e74f542-71dd-4d66-963e-ef4287ff173b)
     47 *      16        4  Length of bytes of the entire secret area
     48 *
     49 *      20       16  First secret entry's GUID
     50 *      36        4  First secret entry's length in bytes (= 16 + 4 + x)
     51 *      40        x  First secret entry's data
     52 *
     53 *    40+x       16  Second secret entry's GUID
     54 *    56+x        4  Second secret entry's length in bytes (= 16 + 4 + y)
     55 *    60+x        y  Second secret entry's data
     56 *
     57 * (... and so on for additional entries)
     58 *
     59 * The GUID of each secret entry designates the usage of the secret data.
     60 */
     61
     62/**
     63 * struct secret_header - Header of entire secret area; this should be followed
     64 * by instances of struct secret_entry.
     65 * @guid:	Must be EFI_SECRET_TABLE_HEADER_GUID
     66 * @len:	Length in bytes of entire secret area, including header
     67 */
     68struct secret_header {
     69	efi_guid_t guid;
     70	u32 len;
     71} __attribute((packed));
     72
     73/**
     74 * struct secret_entry - Holds one secret entry
     75 * @guid:	Secret-specific GUID (or NULL_GUID if this secret entry was deleted)
     76 * @len:	Length of secret entry, including its guid and len fields
     77 * @data:	The secret data (full of zeros if this secret entry was deleted)
     78 */
     79struct secret_entry {
     80	efi_guid_t guid;
     81	u32 len;
     82	u8 data[];
     83} __attribute((packed));
     84
     85static size_t secret_entry_data_len(struct secret_entry *e)
     86{
     87	return e->len - sizeof(*e);
     88}
     89
     90static struct efi_secret the_efi_secret;
     91
     92static inline struct efi_secret *efi_secret_get(void)
     93{
     94	return &the_efi_secret;
     95}
     96
     97static int efi_secret_bin_file_show(struct seq_file *file, void *data)
     98{
     99	struct secret_entry *e = file->private;
    100
    101	if (e)
    102		seq_write(file, e->data, secret_entry_data_len(e));
    103
    104	return 0;
    105}
    106DEFINE_SHOW_ATTRIBUTE(efi_secret_bin_file);
    107
    108/*
    109 * Overwrite memory content with zeroes, and ensure that dirty cache lines are
    110 * actually written back to memory, to clear out the secret.
    111 */
    112static void wipe_memory(void *addr, size_t size)
    113{
    114	memzero_explicit(addr, size);
    115#ifdef CONFIG_X86
    116	clflush_cache_range(addr, size);
    117#endif
    118}
    119
    120static int efi_secret_unlink(struct inode *dir, struct dentry *dentry)
    121{
    122	struct efi_secret *s = efi_secret_get();
    123	struct inode *inode = d_inode(dentry);
    124	struct secret_entry *e = (struct secret_entry *)inode->i_private;
    125	int i;
    126
    127	if (e) {
    128		/* Zero out the secret data */
    129		wipe_memory(e->data, secret_entry_data_len(e));
    130		e->guid = NULL_GUID;
    131	}
    132
    133	inode->i_private = NULL;
    134
    135	for (i = 0; i < EFI_SECRET_NUM_FILES; i++)
    136		if (s->fs_files[i] == dentry)
    137			s->fs_files[i] = NULL;
    138
    139	/*
    140	 * securityfs_remove tries to lock the directory's inode, but we reach
    141	 * the unlink callback when it's already locked
    142	 */
    143	inode_unlock(dir);
    144	securityfs_remove(dentry);
    145	inode_lock(dir);
    146
    147	return 0;
    148}
    149
    150static const struct inode_operations efi_secret_dir_inode_operations = {
    151	.lookup         = simple_lookup,
    152	.unlink         = efi_secret_unlink,
    153};
    154
    155static int efi_secret_map_area(struct platform_device *dev)
    156{
    157	int ret;
    158	struct efi_secret *s = efi_secret_get();
    159	struct linux_efi_coco_secret_area *secret_area;
    160
    161	if (efi.coco_secret == EFI_INVALID_TABLE_ADDR) {
    162		dev_err(&dev->dev, "Secret area address is not available\n");
    163		return -EINVAL;
    164	}
    165
    166	secret_area = memremap(efi.coco_secret, sizeof(*secret_area), MEMREMAP_WB);
    167	if (secret_area == NULL) {
    168		dev_err(&dev->dev, "Could not map secret area EFI config entry\n");
    169		return -ENOMEM;
    170	}
    171	if (!secret_area->base_pa || secret_area->size < sizeof(struct secret_header)) {
    172		dev_err(&dev->dev,
    173			"Invalid secret area memory location (base_pa=0x%llx size=0x%llx)\n",
    174			secret_area->base_pa, secret_area->size);
    175		ret = -EINVAL;
    176		goto unmap;
    177	}
    178
    179	s->secret_data = ioremap_encrypted(secret_area->base_pa, secret_area->size);
    180	if (s->secret_data == NULL) {
    181		dev_err(&dev->dev, "Could not map secret area\n");
    182		ret = -ENOMEM;
    183		goto unmap;
    184	}
    185
    186	s->secret_data_len = secret_area->size;
    187	ret = 0;
    188
    189unmap:
    190	memunmap(secret_area);
    191	return ret;
    192}
    193
    194static void efi_secret_securityfs_teardown(struct platform_device *dev)
    195{
    196	struct efi_secret *s = efi_secret_get();
    197	int i;
    198
    199	for (i = (EFI_SECRET_NUM_FILES - 1); i >= 0; i--) {
    200		securityfs_remove(s->fs_files[i]);
    201		s->fs_files[i] = NULL;
    202	}
    203
    204	securityfs_remove(s->fs_dir);
    205	s->fs_dir = NULL;
    206
    207	securityfs_remove(s->secrets_dir);
    208	s->secrets_dir = NULL;
    209
    210	dev_dbg(&dev->dev, "Removed securityfs entries\n");
    211}
    212
    213static int efi_secret_securityfs_setup(struct platform_device *dev)
    214{
    215	struct efi_secret *s = efi_secret_get();
    216	int ret = 0, i = 0, bytes_left;
    217	unsigned char *ptr;
    218	struct secret_header *h;
    219	struct secret_entry *e;
    220	struct dentry *dent;
    221	char guid_str[EFI_VARIABLE_GUID_LEN + 1];
    222
    223	ptr = (void __force *)s->secret_data;
    224	h = (struct secret_header *)ptr;
    225	if (efi_guidcmp(h->guid, EFI_SECRET_TABLE_HEADER_GUID)) {
    226		/*
    227		 * This is not an error: it just means that EFI defines secret
    228		 * area but it was not populated by the Guest Owner.
    229		 */
    230		dev_dbg(&dev->dev, "EFI secret area does not start with correct GUID\n");
    231		return -ENODEV;
    232	}
    233	if (h->len < sizeof(*h)) {
    234		dev_err(&dev->dev, "EFI secret area reported length is too small\n");
    235		return -EINVAL;
    236	}
    237	if (h->len > s->secret_data_len) {
    238		dev_err(&dev->dev, "EFI secret area reported length is too big\n");
    239		return -EINVAL;
    240	}
    241
    242	s->secrets_dir = NULL;
    243	s->fs_dir = NULL;
    244	memset(s->fs_files, 0, sizeof(s->fs_files));
    245
    246	dent = securityfs_create_dir("secrets", NULL);
    247	if (IS_ERR(dent)) {
    248		dev_err(&dev->dev, "Error creating secrets securityfs directory entry err=%ld\n",
    249			PTR_ERR(dent));
    250		return PTR_ERR(dent);
    251	}
    252	s->secrets_dir = dent;
    253
    254	dent = securityfs_create_dir("coco", s->secrets_dir);
    255	if (IS_ERR(dent)) {
    256		dev_err(&dev->dev, "Error creating coco securityfs directory entry err=%ld\n",
    257			PTR_ERR(dent));
    258		return PTR_ERR(dent);
    259	}
    260	d_inode(dent)->i_op = &efi_secret_dir_inode_operations;
    261	s->fs_dir = dent;
    262
    263	bytes_left = h->len - sizeof(*h);
    264	ptr += sizeof(*h);
    265	while (bytes_left >= (int)sizeof(*e) && i < EFI_SECRET_NUM_FILES) {
    266		e = (struct secret_entry *)ptr;
    267		if (e->len < sizeof(*e) || e->len > (unsigned int)bytes_left) {
    268			dev_err(&dev->dev, "EFI secret area is corrupted\n");
    269			ret = -EINVAL;
    270			goto err_cleanup;
    271		}
    272
    273		/* Skip deleted entries (which will have NULL_GUID) */
    274		if (efi_guidcmp(e->guid, NULL_GUID)) {
    275			efi_guid_to_str(&e->guid, guid_str);
    276
    277			dent = securityfs_create_file(guid_str, 0440, s->fs_dir, (void *)e,
    278						      &efi_secret_bin_file_fops);
    279			if (IS_ERR(dent)) {
    280				dev_err(&dev->dev, "Error creating efi_secret securityfs entry\n");
    281				ret = PTR_ERR(dent);
    282				goto err_cleanup;
    283			}
    284
    285			s->fs_files[i++] = dent;
    286		}
    287		ptr += e->len;
    288		bytes_left -= e->len;
    289	}
    290
    291	dev_info(&dev->dev, "Created %d entries in securityfs secrets/coco\n", i);
    292	return 0;
    293
    294err_cleanup:
    295	efi_secret_securityfs_teardown(dev);
    296	return ret;
    297}
    298
    299static void efi_secret_unmap_area(void)
    300{
    301	struct efi_secret *s = efi_secret_get();
    302
    303	if (s->secret_data) {
    304		iounmap(s->secret_data);
    305		s->secret_data = NULL;
    306		s->secret_data_len = 0;
    307	}
    308}
    309
    310static int efi_secret_probe(struct platform_device *dev)
    311{
    312	int ret;
    313
    314	ret = efi_secret_map_area(dev);
    315	if (ret)
    316		return ret;
    317
    318	ret = efi_secret_securityfs_setup(dev);
    319	if (ret)
    320		goto err_unmap;
    321
    322	return ret;
    323
    324err_unmap:
    325	efi_secret_unmap_area();
    326	return ret;
    327}
    328
    329static int efi_secret_remove(struct platform_device *dev)
    330{
    331	efi_secret_securityfs_teardown(dev);
    332	efi_secret_unmap_area();
    333	return 0;
    334}
    335
    336static struct platform_driver efi_secret_driver = {
    337	.probe = efi_secret_probe,
    338	.remove = efi_secret_remove,
    339	.driver = {
    340		.name = "efi_secret",
    341	},
    342};
    343
    344module_platform_driver(efi_secret_driver);
    345
    346MODULE_DESCRIPTION("Confidential computing EFI secret area access");
    347MODULE_AUTHOR("IBM");
    348MODULE_LICENSE("GPL");
    349MODULE_ALIAS("platform:efi_secret");