linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] efi: deprecate/remove efivars sysfs interface
@ 2020-09-23 16:13 Ard Biesheuvel
  2020-09-23 16:13 ` [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module Ard Biesheuvel
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

This series implements the deprecation and ultimate removal of the sysfs
interface that exposes the contents of the EFI variable store.

I am fully aware that removing this sysfs interface entirely may be
premature, and so patch #7 is included for reference only, and not
proposed for inclusion right away.

Instead, patch #6 limits availability of the efivars module to X86
and IA64, which is reasonable, given that the efivars module was
superseded by the efivarfs filesystem interface before EFI support
for ARM architectures was even available in Linux.

Patches #1 to #5 remove all dependencies [true or false] on the efivars.c
code and its CONFIG_EFI_VARS Kconfig symbol, so it can be disabled [or
dropped] cleanly.

Cc: Matthew Garrett <mjg59@google.com>
Cc: Peter Jones <pjones@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: Colin Cross <ccross@android.com>
Cc: Tony Luck <tony.luck@intel.com>

Ard Biesheuvel (7):
  efi: pstore: disentangle from deprecated efivars module
  efi: pstore: move workqueue handling out of efivars
  efi: efivars: un-export efivars_sysfs_init()
  efi: gsmi: fix false dependency on CONFIG_EFI_VARS
  efi: remove some false dependencies on CONFIG_EFI_VARS
  efi: efivars: limit availability to X86 builds
  efi: efivars: remove deprecated sysfs interface

 .../ABI/stable/sysfs-firmware-efi-vars        |  75 --
 Documentation/arm/uefi.rst                    |   2 +-
 drivers/firmware/efi/Kconfig                  |  22 +-
 drivers/firmware/efi/Makefile                 |   1 -
 drivers/firmware/efi/efi-pstore.c             |  83 +-
 drivers/firmware/efi/efivars.c                | 711 ------------------
 drivers/firmware/efi/vars.c                   |  21 -
 drivers/firmware/google/Kconfig               |   2 +-
 drivers/firmware/google/gsmi.c                |   8 +-
 include/linux/efi.h                           |  18 -
 10 files changed, 85 insertions(+), 858 deletions(-)
 delete mode 100644 Documentation/ABI/stable/sysfs-firmware-efi-vars
 delete mode 100644 drivers/firmware/efi/efivars.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module
  2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
@ 2020-09-23 16:13 ` Ard Biesheuvel
  2020-09-23 18:41   ` Kees Cook
  2020-09-23 16:13 ` [PATCH 2/7] efi: pstore: move workqueue handling out of efivars Ard Biesheuvel
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

The EFI pstore implementation relies on the 'efivars' abstraction,
which encapsulates the EFI variable store in a way that can be
overridden by other backing stores, like the Google SMI one.

On top of that, the EFI pstore implementation also relies on the
efivars.ko module, which is a separate layer built on top of the
'efivars' abstraction that exposes the [deprecated] sysfs entries
for each variable that exists in the backing store.

Since the efivars.ko module is deprecated, and all users appear to
have moved to the efivarfs file system instead, let's prepare for
its removal, by removing EFI pstore's dependency on it.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/Kconfig      |  2 +-
 drivers/firmware/efi/efi-pstore.c | 76 ++++++++++++++++++--
 drivers/firmware/efi/efivars.c    | 41 +----------
 include/linux/efi.h               |  4 --
 4 files changed, 74 insertions(+), 49 deletions(-)

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 3939699e62fe..dd8d10817bdf 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -26,7 +26,7 @@ config EFI_ESRT
 
 config EFI_VARS_PSTORE
 	tristate "Register efivars backend for pstore"
-	depends on EFI_VARS && PSTORE
+	depends on PSTORE
 	default y
 	help
 	  Say Y here to enable use efivars as a backend to pstore. This
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index feb7fe6f2da7..785f5e6b3a41 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -8,6 +8,8 @@
 
 #define DUMP_NAME_LEN 66
 
+#define EFIVARS_DATA_SIZE_MAX 1024
+
 static bool efivars_pstore_disable =
 	IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
 
@@ -18,6 +20,8 @@ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
 	 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
 	 EFI_VARIABLE_RUNTIME_ACCESS)
 
+static LIST_HEAD(efi_pstore_list);
+
 static int efi_pstore_open(struct pstore_info *psi)
 {
 	psi->data = NULL;
@@ -126,7 +130,7 @@ static inline int __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry,
 	if (entry->deleting) {
 		list_del(&entry->list);
 		efivar_entry_iter_end();
-		efivar_unregister(entry);
+		kfree(entry);
 		if (efivar_entry_iter_begin())
 			return -EINTR;
 	} else if (turn_off_scanning)
@@ -169,7 +173,7 @@ static int efi_pstore_sysfs_entry_iter(struct pstore_record *record)
 {
 	struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data;
 	struct efivar_entry *entry, *n;
-	struct list_head *head = &efivar_sysfs_list;
+	struct list_head *head = &efi_pstore_list;
 	int size = 0;
 	int ret;
 
@@ -314,12 +318,12 @@ static int efi_pstore_erase_name(const char *name)
 	if (efivar_entry_iter_begin())
 		return -EINTR;
 
-	found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list,
+	found = __efivar_entry_iter(efi_pstore_erase_func, &efi_pstore_list,
 				    efi_name, &entry);
 	efivar_entry_iter_end();
 
 	if (found && !entry->scanning)
-		efivar_unregister(entry);
+		kfree(entry);
 
 	return found ? 0 : -ENOENT;
 }
@@ -354,14 +358,76 @@ static struct pstore_info efi_pstore_info = {
 	.erase		= efi_pstore_erase,
 };
 
+static int efi_pstore_callback(efi_char16_t *name, efi_guid_t vendor,
+			       unsigned long name_size, void *data)
+{
+	struct efivar_entry *entry;
+	int ret;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	memcpy(entry->var.VariableName, name, name_size);
+	entry->var.VendorGuid = vendor;
+
+	ret = efivar_entry_add(entry, &efi_pstore_list);
+	if (ret)
+		kfree(entry);
+
+	return ret;
+}
+
+static int efi_pstore_update_entry(efi_char16_t *name, efi_guid_t vendor,
+				   unsigned long name_size, void *data)
+{
+	struct efivar_entry *entry = data;
+
+	if (efivar_entry_find(name, vendor, &efi_pstore_list, false))
+		return 0;
+
+	memcpy(entry->var.VariableName, name, name_size);
+	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
+
+	return 1;
+}
+
+static void efi_pstore_update_entries(struct work_struct *work)
+{
+	struct efivar_entry *entry;
+	int err;
+
+	/* Add new sysfs entries */
+	while (1) {
+		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+		if (!entry)
+			return;
+
+		err = efivar_init(efi_pstore_update_entry, entry,
+				  false, &efi_pstore_list);
+		if (!err)
+			break;
+
+		efivar_entry_add(entry, &efi_pstore_list);
+	}
+
+	kfree(entry);
+}
+
 static __init int efivars_pstore_init(void)
 {
+	int ret;
+
 	if (!efivars_kobject() || !efivar_supports_writes())
 		return 0;
 
 	if (efivars_pstore_disable)
 		return 0;
 
+	ret = efivar_init(efi_pstore_callback, NULL, true, &efi_pstore_list);
+	if (ret)
+		return ret;
+
 	efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
 	if (!efi_pstore_info.buf)
 		return -ENOMEM;
@@ -374,6 +440,8 @@ static __init int efivars_pstore_init(void)
 		efi_pstore_info.bufsize = 0;
 	}
 
+	INIT_WORK(&efivar_work, efi_pstore_update_entries);
+
 	return 0;
 }
 
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index dcea137142b3..f39321dbc29f 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -24,8 +24,7 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(EFIVARS_VERSION);
 MODULE_ALIAS("platform:efivars");
 
-LIST_HEAD(efivar_sysfs_list);
-EXPORT_SYMBOL_GPL(efivar_sysfs_list);
+static LIST_HEAD(efivar_sysfs_list);
 
 static struct kset *efivars_kset;
 
@@ -591,42 +590,6 @@ create_efivars_bin_attributes(void)
 	return error;
 }
 
-static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor,
-				     unsigned long name_size, void *data)
-{
-	struct efivar_entry *entry = data;
-
-	if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false))
-		return 0;
-
-	memcpy(entry->var.VariableName, name, name_size);
-	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
-
-	return 1;
-}
-
-static void efivar_update_sysfs_entries(struct work_struct *work)
-{
-	struct efivar_entry *entry;
-	int err;
-
-	/* Add new sysfs entries */
-	while (1) {
-		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-		if (!entry)
-			return;
-
-		err = efivar_init(efivar_update_sysfs_entry, entry,
-				  false, &efivar_sysfs_list);
-		if (!err)
-			break;
-
-		efivar_create_sysfs_entry(entry);
-	}
-
-	kfree(entry);
-}
-
 static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,
 				  unsigned long name_size, void *data)
 {
@@ -701,8 +664,6 @@ int efivars_sysfs_init(void)
 		return error;
 	}
 
-	INIT_WORK(&efivar_work, efivar_update_sysfs_entries);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(efivars_sysfs_init);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 73db1ae04cef..a470256f5ee3 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -984,8 +984,6 @@ struct efivar_entry {
 	bool deleting;
 };
 
-extern struct list_head efivar_sysfs_list;
-
 static inline void
 efivar_unregister(struct efivar_entry *var)
 {
@@ -1043,8 +1041,6 @@ void efivar_run_worker(void);
 #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
 int efivars_sysfs_init(void);
 
-#define EFIVARS_DATA_SIZE_MAX 1024
-
 #endif /* CONFIG_EFI_VARS */
 extern bool efi_capsule_pending(int *reset_type);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/7] efi: pstore: move workqueue handling out of efivars
  2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
  2020-09-23 16:13 ` [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module Ard Biesheuvel
@ 2020-09-23 16:13 ` Ard Biesheuvel
  2020-09-23 16:14 ` [PATCH 3/7] efi: efivars: un-export efivars_sysfs_init() Ard Biesheuvel
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

The worker thread that gets kicked off to sync the state of the
EFI variable list is only used by the EFI pstore implementation,
and is defined in its source file. So let's move its scheduling
there as well. Since our efivar_init() scan will bail on duplicate
entries, there is no need to disable the workqueue like we did
before, so we can run it unconditionally.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/efi-pstore.c |  7 +++++--
 drivers/firmware/efi/vars.c       | 21 --------------------
 include/linux/efi.h               |  3 ---
 3 files changed, 5 insertions(+), 26 deletions(-)

diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 785f5e6b3a41..0ef086e43090 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -21,6 +21,7 @@ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
 	 EFI_VARIABLE_RUNTIME_ACCESS)
 
 static LIST_HEAD(efi_pstore_list);
+static DECLARE_WORK(efivar_work, NULL);
 
 static int efi_pstore_open(struct pstore_info *psi)
 {
@@ -267,8 +268,9 @@ static int efi_pstore_write(struct pstore_record *record)
 	ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
 			      preemptible(), record->size, record->psi->buf);
 
-	if (record->reason == KMSG_DUMP_OOPS)
-		efivar_run_worker();
+	if (record->reason == KMSG_DUMP_OOPS && try_module_get(THIS_MODULE))
+		if (!schedule_work(&efivar_work))
+			module_put(THIS_MODULE);
 
 	return ret;
 };
@@ -412,6 +414,7 @@ static void efi_pstore_update_entries(struct work_struct *work)
 	}
 
 	kfree(entry);
+	module_put(THIS_MODULE);
 }
 
 static __init int efivars_pstore_init(void)
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index 973eef234b36..ffb12f6efc97 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -32,10 +32,6 @@ static struct efivars *__efivars;
  */
 static DEFINE_SEMAPHORE(efivars_lock);
 
-static bool efivar_wq_enabled = true;
-DECLARE_WORK(efivar_work, NULL);
-EXPORT_SYMBOL_GPL(efivar_work);
-
 static bool
 validate_device_path(efi_char16_t *var_name, int match, u8 *buffer,
 		     unsigned long len)
@@ -391,13 +387,6 @@ static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
 	size_t i, len8 = len16 / sizeof(efi_char16_t);
 	char *str8;
 
-	/*
-	 * Disable the workqueue since the algorithm it uses for
-	 * detecting new variables won't work with this buggy
-	 * implementation of GetNextVariableName().
-	 */
-	efivar_wq_enabled = false;
-
 	str8 = kzalloc(len8, GFP_KERNEL);
 	if (!str8)
 		return;
@@ -1157,16 +1146,6 @@ struct kobject *efivars_kobject(void)
 }
 EXPORT_SYMBOL_GPL(efivars_kobject);
 
-/**
- * efivar_run_worker - schedule the efivar worker thread
- */
-void efivar_run_worker(void)
-{
-	if (efivar_wq_enabled)
-		schedule_work(&efivar_work);
-}
-EXPORT_SYMBOL_GPL(efivar_run_worker);
-
 /**
  * efivars_register - register an efivars
  * @efivars: efivars to register
diff --git a/include/linux/efi.h b/include/linux/efi.h
index a470256f5ee3..8ae64c2a384b 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1035,9 +1035,6 @@ bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
 bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
 				  size_t len);
 
-extern struct work_struct efivar_work;
-void efivar_run_worker(void);
-
 #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
 int efivars_sysfs_init(void);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/7] efi: efivars: un-export efivars_sysfs_init()
  2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
  2020-09-23 16:13 ` [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module Ard Biesheuvel
  2020-09-23 16:13 ` [PATCH 2/7] efi: pstore: move workqueue handling out of efivars Ard Biesheuvel
@ 2020-09-23 16:14 ` Ard Biesheuvel
  2020-09-23 16:14 ` [PATCH 4/7] efi: gsmi: fix false dependency on CONFIG_EFI_VARS Ard Biesheuvel
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

efivars_sysfs_init() is only used locally in the source file that
defines it, so make it static and unexport it.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/efivars.c | 3 +--
 include/linux/efi.h            | 4 ----
 2 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index f39321dbc29f..a76f50e15e6d 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -638,7 +638,7 @@ static void efivars_sysfs_exit(void)
 	kset_unregister(efivars_kset);
 }
 
-int efivars_sysfs_init(void)
+static int efivars_sysfs_init(void)
 {
 	struct kobject *parent_kobj = efivars_kobject();
 	int error = 0;
@@ -666,7 +666,6 @@ int efivars_sysfs_init(void)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(efivars_sysfs_init);
 
 module_init(efivars_sysfs_init);
 module_exit(efivars_sysfs_exit);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 8ae64c2a384b..7defdc456dc0 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1035,10 +1035,6 @@ bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
 bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
 				  size_t len);
 
-#if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
-int efivars_sysfs_init(void);
-
-#endif /* CONFIG_EFI_VARS */
 extern bool efi_capsule_pending(int *reset_type);
 
 extern int efi_capsule_supported(efi_guid_t guid, u32 flags,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/7] efi: gsmi: fix false dependency on CONFIG_EFI_VARS
  2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2020-09-23 16:14 ` [PATCH 3/7] efi: efivars: un-export efivars_sysfs_init() Ard Biesheuvel
@ 2020-09-23 16:14 ` Ard Biesheuvel
  2020-09-23 16:14 ` [PATCH 5/7] efi: remove some false dependencies " Ard Biesheuvel
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

The gsmi code does not actually rely on CONFIG_EFI_VARS, since it only
uses the efivars abstraction that is included unconditionally when
CONFIG_EFI is defined. CONFIG_EFI_VARS controls the inclusion of the
code that exposes the sysfs entries, and which has been deprecated for
some time.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/google/Kconfig | 2 +-
 drivers/firmware/google/gsmi.c  | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index a3a6ca659ffa..97968aece54f 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -15,7 +15,7 @@ config GOOGLE_SMI
 	help
 	  Say Y here if you want to enable SMI callbacks for Google
 	  platforms.  This provides an interface for writing to and
-	  clearing the event log.  If EFI_VARS is also enabled this
+	  clearing the event log.  If CONFIG_EFI is also enabled this
 	  driver provides an interface for reading and writing NVRAM
 	  variables.
 
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index 5b2011ebbe26..7d9367b22010 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -302,7 +302,7 @@ static int gsmi_exec(u8 func, u8 sub)
 	return rc;
 }
 
-#ifdef CONFIG_EFI_VARS
+#ifdef CONFIG_EFI
 
 static struct efivars efivars;
 
@@ -483,7 +483,7 @@ static const struct efivar_operations efivar_ops = {
 	.get_next_variable = gsmi_get_next_variable,
 };
 
-#endif /* CONFIG_EFI_VARS */
+#endif /* CONFIG_EFI */
 
 static ssize_t eventlog_write(struct file *filp, struct kobject *kobj,
 			       struct bin_attribute *bin_attr,
@@ -1007,7 +1007,7 @@ static __init int gsmi_init(void)
 		goto out_remove_bin_file;
 	}
 
-#ifdef CONFIG_EFI_VARS
+#ifdef CONFIG_EFI
 	ret = efivars_register(&efivars, &efivar_ops, gsmi_kobj);
 	if (ret) {
 		printk(KERN_INFO "gsmi: Failed to register efivars\n");
@@ -1047,7 +1047,7 @@ static void __exit gsmi_exit(void)
 	unregister_die_notifier(&gsmi_die_notifier);
 	atomic_notifier_chain_unregister(&panic_notifier_list,
 					 &gsmi_panic_notifier);
-#ifdef CONFIG_EFI_VARS
+#ifdef CONFIG_EFI
 	efivars_unregister(&efivars);
 #endif
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 5/7] efi: remove some false dependencies on CONFIG_EFI_VARS
  2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2020-09-23 16:14 ` [PATCH 4/7] efi: gsmi: fix false dependency on CONFIG_EFI_VARS Ard Biesheuvel
@ 2020-09-23 16:14 ` Ard Biesheuvel
  2020-09-23 16:14 ` [PATCH 6/7] efi: efivars: limit availability to X86 builds Ard Biesheuvel
  2020-09-23 16:14 ` [PATCH 7/7] efi: efivars: remove deprecated sysfs interface Ard Biesheuvel
  6 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

Remove some false dependencies on CONFIG_EFI_VARS, which only controls
the creation of the sysfs entries, whereas the underlying functionality
that these modules rely on is enabled unconditionally when CONFIG_EFI
is set.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/Kconfig | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index dd8d10817bdf..80f5c67e3638 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -137,7 +137,6 @@ config EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER
 
 config EFI_BOOTLOADER_CONTROL
 	tristate "EFI Bootloader Control"
-	depends on EFI_VARS
 	default n
 	help
 	  This module installs a reboot hook, such that if reboot() is
@@ -281,7 +280,7 @@ config EFI_EARLYCON
 
 config EFI_CUSTOM_SSDT_OVERLAYS
 	bool "Load custom ACPI SSDT overlay from an EFI variable"
-	depends on EFI_VARS && ACPI
+	depends on EFI && ACPI
 	default ACPI_TABLE_UPGRADE
 	help
 	  Allow loading of an ACPI SSDT overlay from an EFI variable specified
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 6/7] efi: efivars: limit availability to X86 builds
  2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
                   ` (4 preceding siblings ...)
  2020-09-23 16:14 ` [PATCH 5/7] efi: remove some false dependencies " Ard Biesheuvel
@ 2020-09-23 16:14 ` Ard Biesheuvel
  2020-09-23 16:14 ` [PATCH 7/7] efi: efivars: remove deprecated sysfs interface Ard Biesheuvel
  6 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

CONFIG_EFI_VARS controls the code that exposes EFI variables via
sysfs entries, which was deprecated before support for non-Intel
architectures was added to EFI. So let's limit its availability
to Intel architectures for the time being, and hopefully remove
it entirely in the not too distant future.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 Documentation/arm/uefi.rst   |  2 +-
 drivers/firmware/efi/Kconfig | 13 ++++---------
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/Documentation/arm/uefi.rst b/Documentation/arm/uefi.rst
index f868330df6be..f732f957421f 100644
--- a/Documentation/arm/uefi.rst
+++ b/Documentation/arm/uefi.rst
@@ -23,7 +23,7 @@ makes it possible for the kernel to support additional features:
 For actually enabling [U]EFI support, enable:
 
 - CONFIG_EFI=y
-- CONFIG_EFI_VARS=y or m
+- CONFIG_EFIVAR_FS=y or m
 
 The implementation depends on receiving information about the UEFI environment
 in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF.
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 80f5c67e3638..da1887f72a51 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -4,20 +4,15 @@ menu "EFI (Extensible Firmware Interface) Support"
 
 config EFI_VARS
 	tristate "EFI Variable Support via sysfs"
-	depends on EFI
+	depends on EFI && (X86 || IA64)
 	default n
 	help
 	  If you say Y here, you are able to get EFI (Extensible Firmware
 	  Interface) variable information via sysfs.  You may read,
 	  write, create, and destroy EFI variables through this interface.
-
-	  Note that using this driver in concert with efibootmgr requires
-	  at least test release version 0.5.0-test3 or later, which is
-	  available from:
-	  <http://linux.dell.com/efibootmgr/testing/efibootmgr-0.5.0-test3.tar.gz>
-
-	  Subsequent efibootmgr releases may be found at:
-	  <http://github.com/vathpela/efibootmgr>
+	  Note that this driver is only retained for compatibility with
+	  legacy users: new users should use the efivarfs filesystem
+	  instead.
 
 config EFI_ESRT
 	bool
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 7/7] efi: efivars: remove deprecated sysfs interface
  2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
                   ` (5 preceding siblings ...)
  2020-09-23 16:14 ` [PATCH 6/7] efi: efivars: limit availability to X86 builds Ard Biesheuvel
@ 2020-09-23 16:14 ` Ard Biesheuvel
  6 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 16:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-efi, Ard Biesheuvel, Matthew Garrett, Peter Jones,
	Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
Note: for reference only - please read cover letter before replying.

 Documentation/ABI/stable/sysfs-firmware-efi-vars |  75 ---
 drivers/firmware/efi/Kconfig                     |  12 -
 drivers/firmware/efi/Makefile                    |   1 -
 drivers/firmware/efi/efivars.c                   | 671 --------------------
 include/linux/efi.h                              |   7 -
 5 files changed, 766 deletions(-)

diff --git a/Documentation/ABI/stable/sysfs-firmware-efi-vars b/Documentation/ABI/stable/sysfs-firmware-efi-vars
deleted file mode 100644
index 5def20b9019e..000000000000
--- a/Documentation/ABI/stable/sysfs-firmware-efi-vars
+++ /dev/null
@@ -1,75 +0,0 @@
-What:		/sys/firmware/efi/vars
-Date:		April 2004
-Contact:	Matt Domsch <Matt_Domsch@dell.com>
-Description:
-		This directory exposes interfaces for interactive with
-		EFI variables.  For more information on EFI variables,
-		see 'Variable Services' in the UEFI specification
-		(section 7.2 in specification version 2.3 Errata D).
-
-		In summary, EFI variables are named, and are classified
-		into separate namespaces through the use of a vendor
-		GUID.  They also have an arbitrary binary value
-		associated with them.
-
-		The efivars module enumerates these variables and
-		creates a separate directory for each one found.  Each
-		directory has a name of the form "<key>-<vendor guid>"
-		and contains the following files:
-
-		attributes:	A read-only text file enumerating the
-				EFI variable flags.  Potential values
-				include:
-
-				EFI_VARIABLE_NON_VOLATILE
-				EFI_VARIABLE_BOOTSERVICE_ACCESS
-				EFI_VARIABLE_RUNTIME_ACCESS
-				EFI_VARIABLE_HARDWARE_ERROR_RECORD
-				EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
-
-				See the EFI documentation for an
-				explanation of each of these variables.
-
-		data:		A read-only binary file that can be read
-				to attain the value of the EFI variable
-
-		guid:		The vendor GUID of the variable.  This
-				should always match the GUID in the
-				variable's name.
-
-		raw_var:	A binary file that can be read to obtain
-				a structure that contains everything
-				there is to know about the variable.
-				For structure definition see "struct
-				efi_variable" in the kernel sources.
-
-				This file can also be written to in
-				order to update the value of a variable.
-				For this to work however, all fields of
-				the "struct efi_variable" passed must
-				match byte for byte with the structure
-				read out of the file, save for the value
-				portion.
-
-				**Note** the efi_variable structure
-				read/written with this file contains a
-				'long' type that may change widths
-				depending on your underlying
-				architecture.
-
-		size:		As ASCII representation of the size of
-				the variable's value.
-
-
-		In addition, two other magic binary files are provided
-		in the top-level directory and are used for adding and
-		removing variables:
-
-		new_var:	Takes a "struct efi_variable" and
-				instructs the EFI firmware to create a
-				new variable.
-
-		del_var:	Takes a "struct efi_variable" and
-				instructs the EFI firmware to remove any
-				variable that has a matching vendor GUID
-				and variable key name.
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index da1887f72a51..42731b4e335c 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -2,18 +2,6 @@
 menu "EFI (Extensible Firmware Interface) Support"
 	depends on EFI
 
-config EFI_VARS
-	tristate "EFI Variable Support via sysfs"
-	depends on EFI && (X86 || IA64)
-	default n
-	help
-	  If you say Y here, you are able to get EFI (Extensible Firmware
-	  Interface) variable information via sysfs.  You may read,
-	  write, create, and destroy EFI variables through this interface.
-	  Note that this driver is only retained for compatibility with
-	  legacy users: new users should use the efivarfs filesystem
-	  instead.
-
 config EFI_ESRT
 	bool
 	depends on EFI && !IA64
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 7a216984552b..00fbc1b80c84 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_ACPI_BGRT) 		+= efi-bgrt.o
 obj-$(CONFIG_EFI)			+= efi.o vars.o reboot.o memattr.o tpm.o
 obj-$(CONFIG_EFI)			+= capsule.o memmap.o
 obj-$(CONFIG_EFI_PARAMS_FROM_FDT)	+= fdtparams.o
-obj-$(CONFIG_EFI_VARS)			+= efivars.o
 obj-$(CONFIG_EFI_ESRT)			+= esrt.o
 obj-$(CONFIG_EFI_VARS_PSTORE)		+= efi-pstore.o
 obj-$(CONFIG_UEFI_CPER)			+= cper.o
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
deleted file mode 100644
index a76f50e15e6d..000000000000
--- a/drivers/firmware/efi/efivars.c
+++ /dev/null
@@ -1,671 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Originally from efivars.c,
- *
- * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
- * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
- *
- * This code takes all variables accessible from EFI runtime and
- *  exports them via sysfs
- */
-
-#include <linux/efi.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/ucs2_string.h>
-#include <linux/compat.h>
-
-#define EFIVARS_VERSION "0.08"
-#define EFIVARS_DATE "2004-May-17"
-
-MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
-MODULE_DESCRIPTION("sysfs interface to EFI Variables");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(EFIVARS_VERSION);
-MODULE_ALIAS("platform:efivars");
-
-static LIST_HEAD(efivar_sysfs_list);
-
-static struct kset *efivars_kset;
-
-static struct bin_attribute *efivars_new_var;
-static struct bin_attribute *efivars_del_var;
-
-struct compat_efi_variable {
-	efi_char16_t  VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
-	efi_guid_t    VendorGuid;
-	__u32         DataSize;
-	__u8          Data[1024];
-	__u32         Status;
-	__u32         Attributes;
-} __packed;
-
-struct efivar_attribute {
-	struct attribute attr;
-	ssize_t (*show) (struct efivar_entry *entry, char *buf);
-	ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
-};
-
-#define EFIVAR_ATTR(_name, _mode, _show, _store) \
-struct efivar_attribute efivar_attr_##_name = { \
-	.attr = {.name = __stringify(_name), .mode = _mode}, \
-	.show = _show, \
-	.store = _store, \
-};
-
-#define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
-#define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
-
-/*
- * Prototype for sysfs creation function
- */
-static int
-efivar_create_sysfs_entry(struct efivar_entry *new_var);
-
-static ssize_t
-efivar_guid_read(struct efivar_entry *entry, char *buf)
-{
-	struct efi_variable *var = &entry->var;
-	char *str = buf;
-
-	if (!entry || !buf)
-		return 0;
-
-	efi_guid_to_str(&var->VendorGuid, str);
-	str += strlen(str);
-	str += sprintf(str, "\n");
-
-	return str - buf;
-}
-
-static ssize_t
-efivar_attr_read(struct efivar_entry *entry, char *buf)
-{
-	struct efi_variable *var = &entry->var;
-	unsigned long size = sizeof(var->Data);
-	char *str = buf;
-	int ret;
-
-	if (!entry || !buf)
-		return -EINVAL;
-
-	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
-	var->DataSize = size;
-	if (ret)
-		return -EIO;
-
-	if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
-		str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
-	if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
-		str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
-	if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
-		str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
-	if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
-		str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
-	if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
-		str += sprintf(str,
-			"EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
-	if (var->Attributes &
-			EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
-		str += sprintf(str,
-			"EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
-	if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
-		str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
-	return str - buf;
-}
-
-static ssize_t
-efivar_size_read(struct efivar_entry *entry, char *buf)
-{
-	struct efi_variable *var = &entry->var;
-	unsigned long size = sizeof(var->Data);
-	char *str = buf;
-	int ret;
-
-	if (!entry || !buf)
-		return -EINVAL;
-
-	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
-	var->DataSize = size;
-	if (ret)
-		return -EIO;
-
-	str += sprintf(str, "0x%lx\n", var->DataSize);
-	return str - buf;
-}
-
-static ssize_t
-efivar_data_read(struct efivar_entry *entry, char *buf)
-{
-	struct efi_variable *var = &entry->var;
-	unsigned long size = sizeof(var->Data);
-	int ret;
-
-	if (!entry || !buf)
-		return -EINVAL;
-
-	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
-	var->DataSize = size;
-	if (ret)
-		return -EIO;
-
-	memcpy(buf, var->Data, var->DataSize);
-	return var->DataSize;
-}
-
-static inline int
-sanity_check(struct efi_variable *var, efi_char16_t *name, efi_guid_t vendor,
-	     unsigned long size, u32 attributes, u8 *data)
-{
-	/*
-	 * If only updating the variable data, then the name
-	 * and guid should remain the same
-	 */
-	if (memcmp(name, var->VariableName, sizeof(var->VariableName)) ||
-		efi_guidcmp(vendor, var->VendorGuid)) {
-		printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
-		return -EINVAL;
-	}
-
-	if ((size <= 0) || (attributes == 0)){
-		printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
-		return -EINVAL;
-	}
-
-	if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
-	    efivar_validate(vendor, name, data, size) == false) {
-		printk(KERN_ERR "efivars: Malformed variable content\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void
-copy_out_compat(struct efi_variable *dst, struct compat_efi_variable *src)
-{
-	memcpy(dst->VariableName, src->VariableName, EFI_VAR_NAME_LEN);
-	memcpy(dst->Data, src->Data, sizeof(src->Data));
-
-	dst->VendorGuid = src->VendorGuid;
-	dst->DataSize = src->DataSize;
-	dst->Attributes = src->Attributes;
-}
-
-/*
- * We allow each variable to be edited via rewriting the
- * entire efi variable structure.
- */
-static ssize_t
-efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
-{
-	struct efi_variable *new_var, *var = &entry->var;
-	efi_char16_t *name;
-	unsigned long size;
-	efi_guid_t vendor;
-	u32 attributes;
-	u8 *data;
-	int err;
-
-	if (!entry || !buf)
-		return -EINVAL;
-
-	if (in_compat_syscall()) {
-		struct compat_efi_variable *compat;
-
-		if (count != sizeof(*compat))
-			return -EINVAL;
-
-		compat = (struct compat_efi_variable *)buf;
-		attributes = compat->Attributes;
-		vendor = compat->VendorGuid;
-		name = compat->VariableName;
-		size = compat->DataSize;
-		data = compat->Data;
-
-		err = sanity_check(var, name, vendor, size, attributes, data);
-		if (err)
-			return err;
-
-		copy_out_compat(&entry->var, compat);
-	} else {
-		if (count != sizeof(struct efi_variable))
-			return -EINVAL;
-
-		new_var = (struct efi_variable *)buf;
-
-		attributes = new_var->Attributes;
-		vendor = new_var->VendorGuid;
-		name = new_var->VariableName;
-		size = new_var->DataSize;
-		data = new_var->Data;
-
-		err = sanity_check(var, name, vendor, size, attributes, data);
-		if (err)
-			return err;
-
-		memcpy(&entry->var, new_var, count);
-	}
-
-	err = efivar_entry_set(entry, attributes, size, data, NULL);
-	if (err) {
-		printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
-		return -EIO;
-	}
-
-	return count;
-}
-
-static ssize_t
-efivar_show_raw(struct efivar_entry *entry, char *buf)
-{
-	struct efi_variable *var = &entry->var;
-	struct compat_efi_variable *compat;
-	unsigned long datasize = sizeof(var->Data);
-	size_t size;
-	int ret;
-
-	if (!entry || !buf)
-		return 0;
-
-	ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data);
-	var->DataSize = datasize;
-	if (ret)
-		return -EIO;
-
-	if (in_compat_syscall()) {
-		compat = (struct compat_efi_variable *)buf;
-
-		size = sizeof(*compat);
-		memcpy(compat->VariableName, var->VariableName,
-			EFI_VAR_NAME_LEN);
-		memcpy(compat->Data, var->Data, sizeof(compat->Data));
-
-		compat->VendorGuid = var->VendorGuid;
-		compat->DataSize = var->DataSize;
-		compat->Attributes = var->Attributes;
-	} else {
-		size = sizeof(*var);
-		memcpy(buf, var, size);
-	}
-
-	return size;
-}
-
-/*
- * Generic read/write functions that call the specific functions of
- * the attributes...
- */
-static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
-				char *buf)
-{
-	struct efivar_entry *var = to_efivar_entry(kobj);
-	struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
-	ssize_t ret = -EIO;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (efivar_attr->show) {
-		ret = efivar_attr->show(var, buf);
-	}
-	return ret;
-}
-
-static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
-				const char *buf, size_t count)
-{
-	struct efivar_entry *var = to_efivar_entry(kobj);
-	struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
-	ssize_t ret = -EIO;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (efivar_attr->store)
-		ret = efivar_attr->store(var, buf, count);
-
-	return ret;
-}
-
-static const struct sysfs_ops efivar_attr_ops = {
-	.show = efivar_attr_show,
-	.store = efivar_attr_store,
-};
-
-static void efivar_release(struct kobject *kobj)
-{
-	struct efivar_entry *var = to_efivar_entry(kobj);
-	kfree(var);
-}
-
-static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
-static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
-static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
-static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
-static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
-
-static struct attribute *def_attrs[] = {
-	&efivar_attr_guid.attr,
-	&efivar_attr_size.attr,
-	&efivar_attr_attributes.attr,
-	&efivar_attr_data.attr,
-	&efivar_attr_raw_var.attr,
-	NULL,
-};
-
-static struct kobj_type efivar_ktype = {
-	.release = efivar_release,
-	.sysfs_ops = &efivar_attr_ops,
-	.default_attrs = def_attrs,
-};
-
-static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
-			     struct bin_attribute *bin_attr,
-			     char *buf, loff_t pos, size_t count)
-{
-	struct compat_efi_variable *compat = (struct compat_efi_variable *)buf;
-	struct efi_variable *new_var = (struct efi_variable *)buf;
-	struct efivar_entry *new_entry;
-	bool need_compat = in_compat_syscall();
-	efi_char16_t *name;
-	unsigned long size;
-	u32 attributes;
-	u8 *data;
-	int err;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (need_compat) {
-		if (count != sizeof(*compat))
-			return -EINVAL;
-
-		attributes = compat->Attributes;
-		name = compat->VariableName;
-		size = compat->DataSize;
-		data = compat->Data;
-	} else {
-		if (count != sizeof(*new_var))
-			return -EINVAL;
-
-		attributes = new_var->Attributes;
-		name = new_var->VariableName;
-		size = new_var->DataSize;
-		data = new_var->Data;
-	}
-
-	if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
-	    efivar_validate(new_var->VendorGuid, name, data,
-			    size) == false) {
-		printk(KERN_ERR "efivars: Malformed variable content\n");
-		return -EINVAL;
-	}
-
-	new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
-	if (!new_entry)
-		return -ENOMEM;
-
-	if (need_compat)
-		copy_out_compat(&new_entry->var, compat);
-	else
-		memcpy(&new_entry->var, new_var, sizeof(*new_var));
-
-	err = efivar_entry_set(new_entry, attributes, size,
-			       data, &efivar_sysfs_list);
-	if (err) {
-		if (err == -EEXIST)
-			err = -EINVAL;
-		goto out;
-	}
-
-	if (efivar_create_sysfs_entry(new_entry)) {
-		printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
-		kfree(new_entry);
-	}
-	return count;
-
-out:
-	kfree(new_entry);
-	return err;
-}
-
-static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
-			     struct bin_attribute *bin_attr,
-			     char *buf, loff_t pos, size_t count)
-{
-	struct efi_variable *del_var = (struct efi_variable *)buf;
-	struct compat_efi_variable *compat;
-	struct efivar_entry *entry;
-	efi_char16_t *name;
-	efi_guid_t vendor;
-	int err = 0;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (in_compat_syscall()) {
-		if (count != sizeof(*compat))
-			return -EINVAL;
-
-		compat = (struct compat_efi_variable *)buf;
-		name = compat->VariableName;
-		vendor = compat->VendorGuid;
-	} else {
-		if (count != sizeof(*del_var))
-			return -EINVAL;
-
-		name = del_var->VariableName;
-		vendor = del_var->VendorGuid;
-	}
-
-	if (efivar_entry_iter_begin())
-		return -EINTR;
-	entry = efivar_entry_find(name, vendor, &efivar_sysfs_list, true);
-	if (!entry)
-		err = -EINVAL;
-	else if (__efivar_entry_delete(entry))
-		err = -EIO;
-
-	if (err) {
-		efivar_entry_iter_end();
-		return err;
-	}
-
-	if (!entry->scanning) {
-		efivar_entry_iter_end();
-		efivar_unregister(entry);
-	} else
-		efivar_entry_iter_end();
-
-	/* It's dead Jim.... */
-	return count;
-}
-
-/**
- * efivar_create_sysfs_entry - create a new entry in sysfs
- * @new_var: efivar entry to create
- *
- * Returns 0 on success, negative error code on failure
- */
-static int
-efivar_create_sysfs_entry(struct efivar_entry *new_var)
-{
-	int short_name_size;
-	char *short_name;
-	unsigned long utf8_name_size;
-	efi_char16_t *variable_name = new_var->var.VariableName;
-	int ret;
-
-	/*
-	 * Length of the variable bytes in UTF8, plus the '-' separator,
-	 * plus the GUID, plus trailing NUL
-	 */
-	utf8_name_size = ucs2_utf8size(variable_name);
-	short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
-
-	short_name = kmalloc(short_name_size, GFP_KERNEL);
-	if (!short_name)
-		return -ENOMEM;
-
-	ucs2_as_utf8(short_name, variable_name, short_name_size);
-
-	/* This is ugly, but necessary to separate one vendor's
-	   private variables from another's.         */
-	short_name[utf8_name_size] = '-';
-	efi_guid_to_str(&new_var->var.VendorGuid,
-			 short_name + utf8_name_size + 1);
-
-	new_var->kobj.kset = efivars_kset;
-
-	ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
-				   NULL, "%s", short_name);
-	kfree(short_name);
-	if (ret) {
-		kobject_put(&new_var->kobj);
-		return ret;
-	}
-
-	kobject_uevent(&new_var->kobj, KOBJ_ADD);
-	if (efivar_entry_add(new_var, &efivar_sysfs_list)) {
-		efivar_unregister(new_var);
-		return -EINTR;
-	}
-
-	return 0;
-}
-
-static int
-create_efivars_bin_attributes(void)
-{
-	struct bin_attribute *attr;
-	int error;
-
-	/* new_var */
-	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
-	if (!attr)
-		return -ENOMEM;
-
-	attr->attr.name = "new_var";
-	attr->attr.mode = 0200;
-	attr->write = efivar_create;
-	efivars_new_var = attr;
-
-	/* del_var */
-	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
-	if (!attr) {
-		error = -ENOMEM;
-		goto out_free;
-	}
-	attr->attr.name = "del_var";
-	attr->attr.mode = 0200;
-	attr->write = efivar_delete;
-	efivars_del_var = attr;
-
-	sysfs_bin_attr_init(efivars_new_var);
-	sysfs_bin_attr_init(efivars_del_var);
-
-	/* Register */
-	error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var);
-	if (error) {
-		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
-			" due to error %d\n", error);
-		goto out_free;
-	}
-
-	error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var);
-	if (error) {
-		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
-			" due to error %d\n", error);
-		sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
-		goto out_free;
-	}
-
-	return 0;
-out_free:
-	kfree(efivars_del_var);
-	efivars_del_var = NULL;
-	kfree(efivars_new_var);
-	efivars_new_var = NULL;
-	return error;
-}
-
-static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,
-				  unsigned long name_size, void *data)
-{
-	struct efivar_entry *entry;
-
-	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-	if (!entry)
-		return -ENOMEM;
-
-	memcpy(entry->var.VariableName, name, name_size);
-	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
-
-	efivar_create_sysfs_entry(entry);
-
-	return 0;
-}
-
-static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data)
-{
-	int err = efivar_entry_remove(entry);
-
-	if (err)
-		return err;
-	efivar_unregister(entry);
-	return 0;
-}
-
-static void efivars_sysfs_exit(void)
-{
-	/* Remove all entries and destroy */
-	int err;
-
-	err = __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list,
-				  NULL, NULL);
-	if (err) {
-		pr_err("efivars: Failed to destroy sysfs entries\n");
-		return;
-	}
-
-	if (efivars_new_var)
-		sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
-	if (efivars_del_var)
-		sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var);
-	kfree(efivars_new_var);
-	kfree(efivars_del_var);
-	kset_unregister(efivars_kset);
-}
-
-static int efivars_sysfs_init(void)
-{
-	struct kobject *parent_kobj = efivars_kobject();
-	int error = 0;
-
-	/* No efivars has been registered yet */
-	if (!parent_kobj || !efivar_supports_writes())
-		return 0;
-
-	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
-	       EFIVARS_DATE);
-
-	efivars_kset = kset_create_and_add("vars", NULL, parent_kobj);
-	if (!efivars_kset) {
-		printk(KERN_ERR "efivars: Subsystem registration failed.\n");
-		return -ENOMEM;
-	}
-
-	efivar_init(efivars_sysfs_callback, NULL, true, &efivar_sysfs_list);
-
-	error = create_efivars_bin_attributes();
-	if (error) {
-		efivars_sysfs_exit();
-		return error;
-	}
-
-	return 0;
-}
-
-module_init(efivars_sysfs_init);
-module_exit(efivars_sysfs_exit);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 7defdc456dc0..6f9dc44d6d8e 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -979,17 +979,10 @@ struct efi_variable {
 struct efivar_entry {
 	struct efi_variable var;
 	struct list_head list;
-	struct kobject kobj;
 	bool scanning;
 	bool deleting;
 };
 
-static inline void
-efivar_unregister(struct efivar_entry *var)
-{
-	kobject_put(&var->kobj);
-}
-
 int efivars_register(struct efivars *efivars,
 		     const struct efivar_operations *ops,
 		     struct kobject *kobject);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module
  2020-09-23 16:13 ` [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module Ard Biesheuvel
@ 2020-09-23 18:41   ` Kees Cook
  2020-09-23 18:43     ` Ard Biesheuvel
  0 siblings, 1 reply; 13+ messages in thread
From: Kees Cook @ 2020-09-23 18:41 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-kernel, linux-efi, Matthew Garrett, Peter Jones,
	Anton Vorontsov, Colin Cross, Tony Luck

On Wed, Sep 23, 2020 at 06:13:58PM +0200, Ard Biesheuvel wrote:
> The EFI pstore implementation relies on the 'efivars' abstraction,
> which encapsulates the EFI variable store in a way that can be
> overridden by other backing stores, like the Google SMI one.
> 
> On top of that, the EFI pstore implementation also relies on the
> efivars.ko module, which is a separate layer built on top of the
> 'efivars' abstraction that exposes the [deprecated] sysfs entries
> for each variable that exists in the backing store.
> 
> Since the efivars.ko module is deprecated, and all users appear to
> have moved to the efivarfs file system instead, let's prepare for
> its removal, by removing EFI pstore's dependency on it.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

With this and the other pstore patch, do the pstore self-tests still
pass on an EFI system?

If so, please consider both:

Acked-by: Kees Cook <keescook@chromium.org>

Thanks!

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module
  2020-09-23 18:41   ` Kees Cook
@ 2020-09-23 18:43     ` Ard Biesheuvel
  2020-09-23 21:02       ` Kees Cook
  0 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-23 18:43 UTC (permalink / raw)
  To: Kees Cook
  Cc: Linux Kernel Mailing List, linux-efi, Matthew Garrett,
	Peter Jones, Anton Vorontsov, Colin Cross, Tony Luck

On Wed, 23 Sep 2020 at 20:41, Kees Cook <keescook@chromium.org> wrote:
>
> On Wed, Sep 23, 2020 at 06:13:58PM +0200, Ard Biesheuvel wrote:
> > The EFI pstore implementation relies on the 'efivars' abstraction,
> > which encapsulates the EFI variable store in a way that can be
> > overridden by other backing stores, like the Google SMI one.
> >
> > On top of that, the EFI pstore implementation also relies on the
> > efivars.ko module, which is a separate layer built on top of the
> > 'efivars' abstraction that exposes the [deprecated] sysfs entries
> > for each variable that exists in the backing store.
> >
> > Since the efivars.ko module is deprecated, and all users appear to
> > have moved to the efivarfs file system instead, let's prepare for
> > its removal, by removing EFI pstore's dependency on it.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> With this and the other pstore patch, do the pstore self-tests still
> pass on an EFI system?
>
> If so, please consider both:
>
> Acked-by: Kees Cook <keescook@chromium.org>
>

Selftests? Excellent! Are they documented too?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module
  2020-09-23 18:43     ` Ard Biesheuvel
@ 2020-09-23 21:02       ` Kees Cook
  2020-09-24  9:45         ` Ard Biesheuvel
  0 siblings, 1 reply; 13+ messages in thread
From: Kees Cook @ 2020-09-23 21:02 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Linux Kernel Mailing List, linux-efi, Matthew Garrett,
	Peter Jones, Anton Vorontsov, Colin Cross, Tony Luck

On Wed, Sep 23, 2020 at 08:43:21PM +0200, Ard Biesheuvel wrote:
> On Wed, 23 Sep 2020 at 20:41, Kees Cook <keescook@chromium.org> wrote:
> >
> > On Wed, Sep 23, 2020 at 06:13:58PM +0200, Ard Biesheuvel wrote:
> > > The EFI pstore implementation relies on the 'efivars' abstraction,
> > > which encapsulates the EFI variable store in a way that can be
> > > overridden by other backing stores, like the Google SMI one.
> > >
> > > On top of that, the EFI pstore implementation also relies on the
> > > efivars.ko module, which is a separate layer built on top of the
> > > 'efivars' abstraction that exposes the [deprecated] sysfs entries
> > > for each variable that exists in the backing store.
> > >
> > > Since the efivars.ko module is deprecated, and all users appear to
> > > have moved to the efivarfs file system instead, let's prepare for
> > > its removal, by removing EFI pstore's dependency on it.
> > >
> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >
> > With this and the other pstore patch, do the pstore self-tests still
> > pass on an EFI system?
> >
> > If so, please consider both:
> >
> > Acked-by: Kees Cook <keescook@chromium.org>
> >
> 
> Selftests? Excellent! Are they documented too?

Not really, but they're pretty simple:

cd tools/testing/selftests/pstore
*double-check "config" against running kernel config*
./pstore_tests
./pstore_crash_test
*wait for system to reboot*
cd tools/testing/selftests/pstore
./pstore_post_reboot_tests

(though please test before/after, just to make sure other deltas haven't
broken things before your series -- I don't test EFI pstore with high
frequency)

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module
  2020-09-23 21:02       ` Kees Cook
@ 2020-09-24  9:45         ` Ard Biesheuvel
  2020-09-24 10:30           ` Ard Biesheuvel
  0 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-24  9:45 UTC (permalink / raw)
  To: Kees Cook
  Cc: Linux Kernel Mailing List, linux-efi, Matthew Garrett,
	Peter Jones, Anton Vorontsov, Colin Cross, Tony Luck

On Wed, 23 Sep 2020 at 23:02, Kees Cook <keescook@chromium.org> wrote:
>
> On Wed, Sep 23, 2020 at 08:43:21PM +0200, Ard Biesheuvel wrote:
> > On Wed, 23 Sep 2020 at 20:41, Kees Cook <keescook@chromium.org> wrote:
> > >
> > > On Wed, Sep 23, 2020 at 06:13:58PM +0200, Ard Biesheuvel wrote:
> > > > The EFI pstore implementation relies on the 'efivars' abstraction,
> > > > which encapsulates the EFI variable store in a way that can be
> > > > overridden by other backing stores, like the Google SMI one.
> > > >
> > > > On top of that, the EFI pstore implementation also relies on the
> > > > efivars.ko module, which is a separate layer built on top of the
> > > > 'efivars' abstraction that exposes the [deprecated] sysfs entries
> > > > for each variable that exists in the backing store.
> > > >
> > > > Since the efivars.ko module is deprecated, and all users appear to
> > > > have moved to the efivarfs file system instead, let's prepare for
> > > > its removal, by removing EFI pstore's dependency on it.
> > > >
> > > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > >
> > > With this and the other pstore patch, do the pstore self-tests still
> > > pass on an EFI system?
> > >
> > > If so, please consider both:
> > >
> > > Acked-by: Kees Cook <keescook@chromium.org>
> > >
> >
> > Selftests? Excellent! Are they documented too?
>
> Not really, but they're pretty simple:
>
> cd tools/testing/selftests/pstore
> *double-check "config" against running kernel config*
> ./pstore_tests
> ./pstore_crash_test
> *wait for system to reboot*
> cd tools/testing/selftests/pstore
> ./pstore_post_reboot_tests
>
> (though please test before/after, just to make sure other deltas haven't
> broken things before your series -- I don't test EFI pstore with high
> frequency)
>

I have done the 'before' test on three different EFI Linux systems
(x86, arm64 and ARM), and they all give me something like the below

=== Pstore unit tests (pstore_tests) ===
UUID=109d02e6-9395-4274-9554-2c078e87a662
Checking pstore backend is registered ... ok
  backend=efi
  cmdline=BOOT_IMAGE=/vmlinuz-5.3.0-59-generic
root=/dev/mapper/crypt-root ro quiet splash vt.handoff=1
Checking pstore console is registered ... FAIL
Checking /dev/pmsg0 exists ... FAIL
Writing unique string to /dev/pmsg0 ... FAIL

So I'm not sure if there is any point to doing the 'after' test if
this is the baseline.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module
  2020-09-24  9:45         ` Ard Biesheuvel
@ 2020-09-24 10:30           ` Ard Biesheuvel
  0 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-09-24 10:30 UTC (permalink / raw)
  To: Kees Cook
  Cc: Linux Kernel Mailing List, linux-efi, Matthew Garrett,
	Peter Jones, Anton Vorontsov, Colin Cross, Tony Luck

On Thu, 24 Sep 2020 at 11:45, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Wed, 23 Sep 2020 at 23:02, Kees Cook <keescook@chromium.org> wrote:
> >
> > On Wed, Sep 23, 2020 at 08:43:21PM +0200, Ard Biesheuvel wrote:
> > > On Wed, 23 Sep 2020 at 20:41, Kees Cook <keescook@chromium.org> wrote:
> > > >
> > > > On Wed, Sep 23, 2020 at 06:13:58PM +0200, Ard Biesheuvel wrote:
> > > > > The EFI pstore implementation relies on the 'efivars' abstraction,
> > > > > which encapsulates the EFI variable store in a way that can be
> > > > > overridden by other backing stores, like the Google SMI one.
> > > > >
> > > > > On top of that, the EFI pstore implementation also relies on the
> > > > > efivars.ko module, which is a separate layer built on top of the
> > > > > 'efivars' abstraction that exposes the [deprecated] sysfs entries
> > > > > for each variable that exists in the backing store.
> > > > >
> > > > > Since the efivars.ko module is deprecated, and all users appear to
> > > > > have moved to the efivarfs file system instead, let's prepare for
> > > > > its removal, by removing EFI pstore's dependency on it.
> > > > >
> > > > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > > >
> > > > With this and the other pstore patch, do the pstore self-tests still
> > > > pass on an EFI system?
> > > >
> > > > If so, please consider both:
> > > >
> > > > Acked-by: Kees Cook <keescook@chromium.org>
> > > >
> > >
> > > Selftests? Excellent! Are they documented too?
> >
> > Not really, but they're pretty simple:
> >
> > cd tools/testing/selftests/pstore
> > *double-check "config" against running kernel config*
> > ./pstore_tests
> > ./pstore_crash_test
> > *wait for system to reboot*
> > cd tools/testing/selftests/pstore
> > ./pstore_post_reboot_tests
> >
> > (though please test before/after, just to make sure other deltas haven't
> > broken things before your series -- I don't test EFI pstore with high
> > frequency)
> >
>
> I have done the 'before' test on three different EFI Linux systems
> (x86, arm64 and ARM), and they all give me something like the below
>
> === Pstore unit tests (pstore_tests) ===
> UUID=109d02e6-9395-4274-9554-2c078e87a662
> Checking pstore backend is registered ... ok
>   backend=efi
>   cmdline=BOOT_IMAGE=/vmlinuz-5.3.0-59-generic
> root=/dev/mapper/crypt-root ro quiet splash vt.handoff=1
> Checking pstore console is registered ... FAIL
> Checking /dev/pmsg0 exists ... FAIL
> Writing unique string to /dev/pmsg0 ... FAIL
>
> So I'm not sure if there is any point to doing the 'after' test if
> this is the baseline.

In any case, I confirmed that  the new efi-pstore module
- exposes existing pstore dmesg entries correctly
- captures oops and panic messages as dmesg-efi-xxxx entries as before

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-09-24 10:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-23 16:13 [PATCH 0/7] efi: deprecate/remove efivars sysfs interface Ard Biesheuvel
2020-09-23 16:13 ` [PATCH 1/7] efi: pstore: disentangle from deprecated efivars module Ard Biesheuvel
2020-09-23 18:41   ` Kees Cook
2020-09-23 18:43     ` Ard Biesheuvel
2020-09-23 21:02       ` Kees Cook
2020-09-24  9:45         ` Ard Biesheuvel
2020-09-24 10:30           ` Ard Biesheuvel
2020-09-23 16:13 ` [PATCH 2/7] efi: pstore: move workqueue handling out of efivars Ard Biesheuvel
2020-09-23 16:14 ` [PATCH 3/7] efi: efivars: un-export efivars_sysfs_init() Ard Biesheuvel
2020-09-23 16:14 ` [PATCH 4/7] efi: gsmi: fix false dependency on CONFIG_EFI_VARS Ard Biesheuvel
2020-09-23 16:14 ` [PATCH 5/7] efi: remove some false dependencies " Ard Biesheuvel
2020-09-23 16:14 ` [PATCH 6/7] efi: efivars: limit availability to X86 builds Ard Biesheuvel
2020-09-23 16:14 ` [PATCH 7/7] efi: efivars: remove deprecated sysfs interface Ard Biesheuvel

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).