From: Nayna Jain <nayna@linux.ibm.com>
To: linuxppc-dev@lists.ozlabs.org, linux-fsdevel@vger.kernel.org
Cc: linux-efi@vger.kernel.org,
linux-security-module <linux-security-module@vger.kernel.org>,
linux-kernel@vger.kernel.org,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Michael Ellerman <mpe@ellerman.id.au>,
Dov Murik <dovmurik@linux.ibm.com>,
George Wilson <gcwilson@linux.ibm.com>,
gjoyce@ibm.com, Matthew Garrett <mjg59@srcf.ucam.org>,
Dave Hansen <dave.hansen@intel.com>,
Benjamin Herrenschmidt <benh@kernel.crashing.org>,
Paul Mackerras <paulus@samba.org>,
Nayna Jain <nayna@linux.ibm.com>
Subject: [RFC PATCH v2 3/3] powerpc/pseries: expose authenticated variables stored in LPAR PKS
Date: Wed, 22 Jun 2022 17:56:48 -0400 [thread overview]
Message-ID: <20220622215648.96723-4-nayna@linux.ibm.com> (raw)
In-Reply-To: <20220622215648.96723-1-nayna@linux.ibm.com>
PowerVM Guest Secure boot feature need to expose firmware managed
secure variables for user management. These variables store keys for
grub/kernel verification and also corresponding denied list.
Expose these variables to the userpace via fwsecurityfs.
Example:
Example:
# cd /sys/firmware/security/secvars
# pwd
/sys/firmware/security/secvars
# cat /tmp/PK.bin > PK
# ls -l
total 0
-rw-r--r-- 1 root root 2497 Jun 22 08:34 PK
# hexdump -C PK
00000000 00 00 00 00 00 08 00 00 a1 59 c0 a5 e4 94 a7 4a |.........Y.....J|
00000010 87 b5 ab 15 5c 2b f0 72 3f 03 00 00 00 00 00 00 |....\+.r?.......|
00000020 23 03 00 00 ca 18 1d 1c 01 7d eb 11 9a 71 08 94 |#........}...q..|
00000030 ef 31 fb e4 30 82 03 0f 30 82 01 f7 a0 03 02 01 |.1..0...0.......|
00000040 02 02 14 22 ab 18 2f d5 aa dd c5 ba 98 27 60 26 |..."../......'`&|
00000050 f1 63 89 54 4c 52 d9 30 0d 06 09 2a 86 48 86 f7 |.c.TLR.0...*.H..|
...
Signed-off-by: Nayna Jain <nayna@linux.ibm.com>
---
arch/powerpc/platforms/pseries/Kconfig | 17 ++
arch/powerpc/platforms/pseries/plpks/Makefile | 2 +
.../pseries/plpks/fwsecurityfs_arch.c | 16 ++
.../platforms/pseries/plpks/internal.h | 18 ++
.../powerpc/platforms/pseries/plpks/secvars.c | 239 ++++++++++++++++++
include/linux/fwsecurityfs.h | 4 +
6 files changed, 296 insertions(+)
create mode 100644 arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c
create mode 100644 arch/powerpc/platforms/pseries/plpks/internal.h
create mode 100644 arch/powerpc/platforms/pseries/plpks/secvars.c
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 6c1ca487103f..9c52095e20c4 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -152,6 +152,23 @@ config PSERIES_PLPKS
config to enable operating system interface to hypervisor to
access this space.
+config PSERIES_FWSECURITYFS_ARCH
+ depends on FWSECURITYFS
+ bool "Support fwsecurityfs for pseries"
+ help
+ Enable fwsecuirtyfs arch specific code. This would initialize
+ the firmware security filesystem with initial platform specific
+ structure.
+
+config PSERIES_PLPKS_SECVARS
+ depends on PSERIES_PLPKS
+ select PSERIES_FWSECURITYFS_ARCH
+ tristate "Support for secvars"
+ help
+ This interface exposes authenticated variables stored in the LPAR
+ Platform KeyStore using fwsecurityfs interface.
+ If you are unsure how to use it, say N.
+
config PAPR_SCM
depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM
tristate "Support for the PAPR Storage Class Memory interface"
diff --git a/arch/powerpc/platforms/pseries/plpks/Makefile b/arch/powerpc/platforms/pseries/plpks/Makefile
index e651ace920db..ff3d4b4cd3d7 100644
--- a/arch/powerpc/platforms/pseries/plpks/Makefile
+++ b/arch/powerpc/platforms/pseries/plpks/Makefile
@@ -5,3 +5,5 @@
#
obj-$(CONFIG_PSERIES_PLPKS) += plpks.o
+obj-$(CONFIG_PSERIES_FWSECURITYFS_ARCH) += fwsecurityfs_arch.o
+obj-$(CONFIG_PSERIES_PLPKS_SECVARS) += secvars.o
diff --git a/arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c b/arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c
new file mode 100644
index 000000000000..6ccdfe4000a6
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER LPAR Platform KeyStore (PLPKS)
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain <nayna@linux.ibm.com>
+ *
+ */
+
+#include <linux/fwsecurityfs.h>
+
+#include "internal.h"
+
+int arch_fwsecurity_init(void)
+{
+ return plpks_secvars_init();
+}
diff --git a/arch/powerpc/platforms/pseries/plpks/internal.h b/arch/powerpc/platforms/pseries/plpks/internal.h
new file mode 100644
index 000000000000..6061ffd37677
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks/internal.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain <nayna@linux.ibm.com>
+ *
+ */
+#ifndef PKS_FWSEC_INTERNAL
+#define PKS_FWSEC_INTERNAL
+
+#ifdef CONFIG_PSERIES_PLPKS_SECVARS
+int plpks_secvars_init(void);
+#else
+int plpks_secvars_init(void)
+{
+ return 0;
+}
+#endif
+#endif
diff --git a/arch/powerpc/platforms/pseries/plpks/secvars.c b/arch/powerpc/platforms/pseries/plpks/secvars.c
new file mode 100644
index 000000000000..8852cb8f2f3c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks/secvars.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER LPAR Platform KeyStore (PLPKS)
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain <nayna@linux.ibm.com>
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/fs_context.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/namei.h>
+#include <linux/ctype.h>
+#include <linux/fwsecurityfs.h>
+#include <asm/plpks.h>
+
+#include "internal.h"
+
+static struct dentry *secvar_dir;
+
+static const char * const names[] = {
+ "PK",
+ "KEK",
+ "db",
+ "dbx",
+ "grubdb",
+ "sbat",
+ "moduledb",
+ "trustedcadb",
+ NULL
+};
+
+static int validate_name(char *name)
+{
+ int i = 0;
+
+ while (names[i] != NULL) {
+ if ((strlen(names[i]) == strlen(name))
+ && (strncmp(name, names[i], strlen(names[i])) == 0))
+ return 0;
+ i++;
+ }
+ pr_err("Invalid name, allowed ones are (dbx,grubdb,sbat,moduledb,trustedcadb)\n");
+
+ return -EINVAL;
+}
+
+static u32 get_policy(char *name)
+{
+ if ((strncmp(name, "PK", 2) == 0)
+ || (strncmp(name, "KEK", 3) == 0)
+ || (strncmp(name, "db", 2) == 0)
+ || (strncmp(name, "dbx", 3) == 0)
+ || (strncmp(name, "grubdb", 6) == 0)
+ || (strncmp(name, "sbat", 4) == 0))
+ return (WORLDREADABLE & SIGNEDUPDATE);
+ else
+ return SIGNEDUPDATE;
+}
+
+static ssize_t plpks_secvar_file_write(struct file *file,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct plpks_var var;
+ void *data;
+ struct inode *inode = file->f_mapping->host;
+ u16 datasize = count;
+ ssize_t bytes;
+
+ data = memdup_user(userbuf, datasize);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ var.component = NULL;
+ var.name = file->f_path.dentry->d_iname;
+ var.namelen = strlen(var.name);
+ var.policy = get_policy(var.name);
+ var.datalen = datasize;
+ var.data = data;
+ bytes = plpks_signed_update_var(var);
+
+ if (bytes) {
+ pr_err("Update of the variable failed with error %ld\n", bytes);
+ goto out;
+ }
+
+ inode_lock(inode);
+ i_size_write(inode, datasize);
+ inode->i_mtime = current_time(inode);
+ inode_unlock(inode);
+
+ bytes = count;
+out:
+ kfree(data);
+
+ return bytes;
+
+}
+
+static ssize_t plpks_secvar_file_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct plpks_var var;
+ char *out;
+ u32 outlen;
+ int rc;
+ size_t size;
+
+ var.name = file->f_path.dentry->d_iname;
+ var.namelen = strlen(var.name);
+ var.component = NULL;
+ rc = plpks_read_os_var(&var);
+ if (rc) {
+ pr_err("Error reading object %d\n", rc);
+ return rc;
+ }
+
+ outlen = sizeof(var.policy) + var.datalen;
+ out = kzalloc(outlen, GFP_KERNEL);
+ memcpy(out, &var.policy, sizeof(var.policy));
+
+ memcpy(out + sizeof(var.policy), var.data, var.datalen);
+
+ size = simple_read_from_buffer(userbuf, count, ppos,
+ out, outlen);
+ kfree(out);
+ return size;
+}
+
+
+static const struct file_operations plpks_secvar_file_operations = {
+ .open = simple_open,
+ .read = plpks_secvar_file_read,
+ .write = plpks_secvar_file_write,
+ .llseek = no_llseek,
+};
+
+static int plpks_secvar_create(struct user_namespace *mnt_userns, struct inode *dir,
+ struct dentry *dentry, umode_t mode, bool excl)
+{
+ int namelen, i = 0;
+ char *varname;
+ int rc = 0;
+
+ namelen = dentry->d_name.len;
+
+ varname = kzalloc(namelen + 1, GFP_KERNEL);
+ if (!varname)
+ return -ENOMEM;
+
+ for (i = 0; i < namelen; i++)
+ varname[i] = dentry->d_name.name[i];
+ varname[i] = '\0';
+
+ rc = validate_name(varname);
+ if (rc)
+ goto out;
+
+ rc = validate_name(varname);
+ if (rc)
+ goto out;
+
+ rc = fwsecurityfs_create_file(varname, S_IFREG|0644, 0, secvar_dir,
+ dentry, &plpks_secvar_file_operations);
+ if (rc)
+ pr_err("Error creating file\n");
+
+out:
+ kfree(varname);
+
+ return rc;
+}
+
+static const struct inode_operations plpks_secvar_dir_inode_operations = {
+ .lookup = simple_lookup,
+ .create = plpks_secvar_create,
+};
+
+static int plpks_fill_secvars(struct super_block *sb)
+{
+ struct plpks_var *var = NULL;
+ int err;
+ int i = 0;
+
+ while (names[i] != NULL) {
+ var = kzalloc(sizeof(struct plpks_var), GFP_KERNEL);
+ var->name = (char *)names[i];
+ var->namelen = strlen(names[i]);
+ pr_debug("name is %s\n", var->name);
+ var->component = NULL;
+ i++;
+ err = plpks_read_os_var(var);
+ if (err) {
+ kfree(var);
+ continue;
+ }
+
+ err = fwsecurityfs_create_file(var->name, S_IFREG|0644,
+ var->datalen, secvar_dir,
+ NULL,
+ &plpks_secvar_file_operations);
+
+ kfree(var);
+ if (err) {
+ pr_err("Error creating file\n");
+ break;
+ }
+ }
+ return err;
+};
+
+int plpks_secvars_init(void)
+{
+ int error;
+
+ struct super_block *sb;
+
+ secvar_dir = fwsecurityfs_create_dir("secvars", S_IFDIR | 0755, NULL,
+ &plpks_secvar_dir_inode_operations);
+ if (IS_ERR(secvar_dir)) {
+ int ret = PTR_ERR(secvar_dir);
+
+ if (ret != -ENODEV)
+ pr_err("Unable to create integrity sysfs dir: %d\n",
+ ret);
+ secvar_dir = NULL;
+ return ret;
+ }
+
+ sb = fwsecurityfs_get_superblock();
+ error = plpks_fill_secvars(sb);
+ if (error)
+ pr_err("Filling secvars failed\n");
+
+ return 0;
+};
diff --git a/include/linux/fwsecurityfs.h b/include/linux/fwsecurityfs.h
index c079ce939f42..d5fd51aa6322 100644
--- a/include/linux/fwsecurityfs.h
+++ b/include/linux/fwsecurityfs.h
@@ -21,9 +21,13 @@ struct dentry *fwsecurityfs_create_dir(const char *name, umode_t mode,
const struct inode_operations *iops);
int fwsecurityfs_remove_dir(struct dentry *dentry);
+#ifdef CONFIG_PSERIES_FWSECURITYFS_ARCH
+int arch_fwsecurity_init(void);
+#else
static int arch_fwsecurity_init(void)
{
return 0;
}
+#endif
#endif /* _FWSECURITYFS_H_ */
--
2.27.0
next prev parent reply other threads:[~2022-06-22 22:01 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-22 21:56 [RFC PATCH v2 0/3] powerpc/pseries: add support for local secure storage called Platform KeyStore(PKS) Nayna Jain
2022-06-22 21:56 ` [RFC PATCH v2 1/3] powerpc/pseries: define driver for Platform KeyStore Nayna Jain
2022-06-22 21:56 ` [RFC PATCH v2 2/3] fs: define a firmware security filesystem named fwsecurityfs Nayna Jain
2022-06-22 22:29 ` Casey Schaufler
2022-06-23 1:50 ` Nayna
2022-06-23 8:54 ` Greg Kroah-Hartman
2022-06-23 13:23 ` James Bottomley
2022-06-26 15:48 ` Mimi Zohar
2022-06-27 7:37 ` Greg Kroah-Hartman
2022-06-28 13:25 ` Christian Brauner
2022-06-22 21:56 ` Nayna Jain [this message]
2022-06-23 2:36 ` [RFC PATCH v2 3/3] powerpc/pseries: expose authenticated variables stored in LPAR PKS Randy Dunlap
2022-06-27 21:10 ` [RFC PATCH v2 0/3] powerpc/pseries: add support for local secure storage called Platform KeyStore(PKS) Dave Hansen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220622215648.96723-4-nayna@linux.ibm.com \
--to=nayna@linux.ibm.com \
--cc=benh@kernel.crashing.org \
--cc=dave.hansen@intel.com \
--cc=dovmurik@linux.ibm.com \
--cc=gcwilson@linux.ibm.com \
--cc=gjoyce@ibm.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=mjg59@srcf.ucam.org \
--cc=mpe@ellerman.id.au \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).