brintos

brintos / linux-shallow public Read only

0
0
Text · 8.7 KiB · cd29e66 Raw
349 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * efi_secret module4 *5 * Copyright (C) 2022 IBM Corporation6 * Author: Dov Murik <dovmurik@linux.ibm.com>7 */8 9/**10 * DOC: efi_secret: Allow reading EFI confidential computing (coco) secret area11 * via securityfs interface.12 *13 * When the module is loaded (and securityfs is mounted, typically under14 * /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 file16 * 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 6431 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 area42 *43 * Offset   Length44 * (bytes)  (bytes)  Usage45 * -------  -------  -----46 *       0       16  Secret table header GUID (must be 1e74f542-71dd-4d66-963e-ef4287ff173b)47 *      16        4  Length of bytes of the entire secret area48 *49 *      20       16  First secret entry's GUID50 *      36        4  First secret entry's length in bytes (= 16 + 4 + x)51 *      40        x  First secret entry's data52 *53 *    40+x       16  Second secret entry's GUID54 *    56+x        4  Second secret entry's length in bytes (= 16 + 4 + y)55 *    60+x        y  Second secret entry's data56 *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 followed64 * by instances of struct secret_entry.65 * @guid:	Must be EFI_SECRET_TABLE_HEADER_GUID66 * @len:	Length in bytes of entire secret area, including header67 */68struct secret_header {69	efi_guid_t guid;70	u32 len;71} __attribute((packed));72 73/**74 * struct secret_entry - Holds one secret entry75 * @guid:	Secret-specific GUID (or NULL_GUID if this secret entry was deleted)76 * @len:	Length of secret entry, including its guid and len fields77 * @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 are110 * 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_X86116	clflush_cache_range(addr, size);117#endif118}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 reach141	 * the unlink callback when it's already locked142	 */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 secret228		 * 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 void efi_secret_remove(struct platform_device *dev)330{331	efi_secret_securityfs_teardown(dev);332	efi_secret_unmap_area();333}334 335static struct platform_driver efi_secret_driver = {336	.probe = efi_secret_probe,337	.remove_new = efi_secret_remove,338	.driver = {339		.name = "efi_secret",340	},341};342 343module_platform_driver(efi_secret_driver);344 345MODULE_DESCRIPTION("Confidential computing EFI secret area access");346MODULE_AUTHOR("IBM");347MODULE_LICENSE("GPL");348MODULE_ALIAS("platform:efi_secret");349