public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Andrew Cooper <Andrew.Cooper3@citrix.com>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>,
	Borislav Petkov <bp@suse.de>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Subject: [PATCH 5.18 37/61] x86/bugs: Add retbleed=ibpb
Date: Tue, 12 Jul 2022 20:39:34 +0200	[thread overview]
Message-ID: <20220712183238.460841428@linuxfoundation.org> (raw)
In-Reply-To: <20220712183236.931648980@linuxfoundation.org>

From: Peter Zijlstra <peterz@infradead.org>

commit 3ebc170068885b6fc7bedda6c667bb2c4d533159 upstream.

jmp2ret mitigates the easy-to-attack case at relatively low overhead.
It mitigates the long speculation windows after a mispredicted RET, but
it does not mitigate the short speculation window from arbitrary
instruction boundaries.

On Zen2, there is a chicken bit which needs setting, which mitigates
"arbitrary instruction boundaries" down to just "basic block boundaries".

But there is no fix for the short speculation window on basic block
boundaries, other than to flush the entire BTB to evict all attacker
predictions.

On the spectrum of "fast & blurry" -> "safe", there is (on top of STIBP
or no-SMT):

  1) Nothing		System wide open
  2) jmp2ret		May stop a script kiddy
  3) jmp2ret+chickenbit  Raises the bar rather further
  4) IBPB		Only thing which can count as "safe".

Tentative numbers put IBPB-on-entry at a 2.5x hit on Zen2, and a 10x hit
on Zen1 according to lmbench.

  [ bp: Fixup feature bit comments, document option, 32-bit build fix. ]

Suggested-by: Andrew Cooper <Andrew.Cooper3@citrix.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 Documentation/admin-guide/kernel-parameters.txt |    3 +
 arch/x86/entry/Makefile                         |    2 -
 arch/x86/entry/entry.S                          |   22 ++++++++++++
 arch/x86/include/asm/cpufeatures.h              |    2 -
 arch/x86/include/asm/nospec-branch.h            |    8 +++-
 arch/x86/kernel/cpu/bugs.c                      |   43 ++++++++++++++++++------
 6 files changed, 67 insertions(+), 13 deletions(-)
 create mode 100644 arch/x86/entry/entry.S

--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5134,6 +5134,9 @@
 				       disabling SMT if necessary for
 				       the full mitigation (only on Zen1
 				       and older without STIBP).
+			ibpb	     - mitigate short speculation windows on
+				       basic block boundaries too. Safe, highest
+				       perf impact.
 			unret        - force enable untrained return thunks,
 				       only effective on AMD f15h-f17h
 				       based systems.
--- a/arch/x86/entry/Makefile
+++ b/arch/x86/entry/Makefile
@@ -11,7 +11,7 @@ CFLAGS_REMOVE_common.o		= $(CC_FLAGS_FTR
 
 CFLAGS_common.o			+= -fno-stack-protector
 
-obj-y				:= entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
+obj-y				:= entry.o entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
 obj-y				+= common.o
 
 obj-y				+= vdso/
--- /dev/null
+++ b/arch/x86/entry/entry.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Common place for both 32- and 64-bit entry routines.
+ */
+
+#include <linux/linkage.h>
+#include <asm/export.h>
+#include <asm/msr-index.h>
+
+.pushsection .noinstr.text, "ax"
+
+SYM_FUNC_START(entry_ibpb)
+	movl	$MSR_IA32_PRED_CMD, %ecx
+	movl	$PRED_CMD_IBPB, %eax
+	xorl	%edx, %edx
+	wrmsr
+	RET
+SYM_FUNC_END(entry_ibpb)
+/* For KVM */
+EXPORT_SYMBOL_GPL(entry_ibpb);
+
+.popsection
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -295,7 +295,7 @@
 #define X86_FEATURE_PER_THREAD_MBA	(11*32+ 7) /* "" Per-thread Memory Bandwidth Allocation */
 #define X86_FEATURE_SGX1		(11*32+ 8) /* "" Basic SGX */
 #define X86_FEATURE_SGX2		(11*32+ 9) /* "" SGX Enclave Dynamic Memory Management (EDMM) */
-/* FREE!				(11*32+10) */
+#define X86_FEATURE_ENTRY_IBPB		(11*32+10) /* "" Issue an IBPB on kernel entry */
 /* FREE!				(11*32+11) */
 #define X86_FEATURE_RETPOLINE		(11*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
 #define X86_FEATURE_RETPOLINE_LFENCE	(11*32+13) /* "" Use LFENCE for Spectre variant 2 */
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -123,14 +123,17 @@
  * return thunk isn't mapped into the userspace tables (then again, AMD
  * typically has NO_MELTDOWN).
  *
- * Doesn't clobber any registers but does require a stable stack.
+ * While zen_untrain_ret() doesn't clobber anything but requires stack,
+ * entry_ibpb() will clobber AX, CX, DX.
  *
  * As such, this must be placed after every *SWITCH_TO_KERNEL_CR3 at a point
  * where we have a stack but before any RET instruction.
  */
 .macro UNTRAIN_RET
 #ifdef CONFIG_RETPOLINE
-	ALTERNATIVE "", "call zen_untrain_ret", X86_FEATURE_UNRET
+	ALTERNATIVE_2 "",						\
+	              "call zen_untrain_ret", X86_FEATURE_UNRET,	\
+		      "call entry_ibpb", X86_FEATURE_ENTRY_IBPB
 #endif
 .endm
 
@@ -147,6 +150,7 @@ extern retpoline_thunk_t __x86_indirect_
 
 extern void __x86_return_thunk(void);
 extern void zen_untrain_ret(void);
+extern void entry_ibpb(void);
 
 #ifdef CONFIG_RETPOLINE
 
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -798,6 +798,7 @@ static enum spectre_v2_mitigation spectr
 enum retbleed_mitigation {
 	RETBLEED_MITIGATION_NONE,
 	RETBLEED_MITIGATION_UNRET,
+	RETBLEED_MITIGATION_IBPB,
 	RETBLEED_MITIGATION_IBRS,
 	RETBLEED_MITIGATION_EIBRS,
 };
@@ -806,11 +807,13 @@ enum retbleed_mitigation_cmd {
 	RETBLEED_CMD_OFF,
 	RETBLEED_CMD_AUTO,
 	RETBLEED_CMD_UNRET,
+	RETBLEED_CMD_IBPB,
 };
 
 const char * const retbleed_strings[] = {
 	[RETBLEED_MITIGATION_NONE]	= "Vulnerable",
 	[RETBLEED_MITIGATION_UNRET]	= "Mitigation: untrained return thunk",
+	[RETBLEED_MITIGATION_IBPB]	= "Mitigation: IBPB",
 	[RETBLEED_MITIGATION_IBRS]	= "Mitigation: IBRS",
 	[RETBLEED_MITIGATION_EIBRS]	= "Mitigation: Enhanced IBRS",
 };
@@ -840,6 +843,8 @@ static int __init retbleed_parse_cmdline
 			retbleed_cmd = RETBLEED_CMD_AUTO;
 		} else if (!strcmp(str, "unret")) {
 			retbleed_cmd = RETBLEED_CMD_UNRET;
+		} else if (!strcmp(str, "ibpb")) {
+			retbleed_cmd = RETBLEED_CMD_IBPB;
 		} else if (!strcmp(str, "nosmt")) {
 			retbleed_nosmt = true;
 		} else {
@@ -854,11 +859,13 @@ static int __init retbleed_parse_cmdline
 early_param("retbleed", retbleed_parse_cmdline);
 
 #define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n"
-#define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler!\n"
+#define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler; falling back to IBPB!\n"
 #define RETBLEED_INTEL_MSG "WARNING: Spectre v2 mitigation leaves CPU vulnerable to RETBleed attacks, data leaks possible!\n"
 
 static void __init retbleed_select_mitigation(void)
 {
+	bool mitigate_smt = false;
+
 	if (!boot_cpu_has_bug(X86_BUG_RETBLEED) || cpu_mitigations_off())
 		return;
 
@@ -870,11 +877,21 @@ static void __init retbleed_select_mitig
 		retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
 		break;
 
+	case RETBLEED_CMD_IBPB:
+		retbleed_mitigation = RETBLEED_MITIGATION_IBPB;
+		break;
+
 	case RETBLEED_CMD_AUTO:
 	default:
 		if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
-		    boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
-			retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
+		    boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
+
+			if (IS_ENABLED(CONFIG_RETPOLINE) &&
+			    IS_ENABLED(CONFIG_CC_HAS_RETURN_THUNK))
+				retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
+			else
+				retbleed_mitigation = RETBLEED_MITIGATION_IBPB;
+		}
 
 		/*
 		 * The Intel mitigation (IBRS) was already selected in
@@ -890,26 +907,34 @@ static void __init retbleed_select_mitig
 		if (!IS_ENABLED(CONFIG_RETPOLINE) ||
 		    !IS_ENABLED(CONFIG_CC_HAS_RETURN_THUNK)) {
 			pr_err(RETBLEED_COMPILER_MSG);
-			retbleed_mitigation = RETBLEED_MITIGATION_NONE;
-			break;
+			retbleed_mitigation = RETBLEED_MITIGATION_IBPB;
+			goto retbleed_force_ibpb;
 		}
 
 		setup_force_cpu_cap(X86_FEATURE_RETHUNK);
 		setup_force_cpu_cap(X86_FEATURE_UNRET);
 
-		if (!boot_cpu_has(X86_FEATURE_STIBP) &&
-		    (retbleed_nosmt || cpu_mitigations_auto_nosmt()))
-			cpu_smt_disable(false);
-
 		if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
 		    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
 			pr_err(RETBLEED_UNTRAIN_MSG);
+
+		mitigate_smt = true;
+		break;
+
+	case RETBLEED_MITIGATION_IBPB:
+retbleed_force_ibpb:
+		setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB);
+		mitigate_smt = true;
 		break;
 
 	default:
 		break;
 	}
 
+	if (mitigate_smt && !boot_cpu_has(X86_FEATURE_STIBP) &&
+	    (retbleed_nosmt || cpu_mitigations_auto_nosmt()))
+		cpu_smt_disable(false);
+
 	/*
 	 * Let IBRS trump all on Intel without affecting the effects of the
 	 * retbleed= cmdline option.



  parent reply	other threads:[~2022-07-12 19:12 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-12 18:38 [PATCH 5.18 00/61] 5.18.12-rc1 review Greg Kroah-Hartman
2022-07-12 18:38 ` [PATCH 5.18 01/61] x86/traps: Use pt_regs directly in fixup_bad_iret() Greg Kroah-Hartman
2022-07-12 18:38 ` [PATCH 5.18 02/61] x86/entry: Switch the stack after error_entry() returns Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 03/61] x86/entry: Move PUSH_AND_CLEAR_REGS out of error_entry() Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 04/61] x86/entry: Dont call error_entry() for XENPV Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 05/61] x86/entry: Remove skip_r11rcx Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 06/61] x86/kvm/vmx: Make noinstr clean Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 07/61] x86/cpufeatures: Move RETPOLINE flags to word 11 Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 08/61] x86/retpoline: Cleanup some #ifdefery Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 09/61] x86/retpoline: Swizzle retpoline thunk Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 10/61] x86/retpoline: Use -mfunction-return Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 11/61] x86: Undo return-thunk damage Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 12/61] x86,objtool: Create .return_sites Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 13/61] objtool: skip non-text sections when adding return-thunk sites Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 14/61] x86,static_call: Use alternative RET encoding Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 15/61] x86/ftrace: " Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 16/61] x86/bpf: " Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 17/61] x86/kvm: Fix SETcc emulation for return thunks Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 18/61] x86/vsyscall_emu/64: Dont use RET in vsyscall emulation Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 19/61] x86/sev: Avoid using __x86_return_thunk Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 20/61] x86: Use return-thunk in asm code Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 21/61] x86/entry: Avoid very early RET Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 22/61] objtool: Treat .text.__x86.* as noinstr Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 23/61] x86: Add magic AMD return-thunk Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 24/61] x86/bugs: Report AMD retbleed vulnerability Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 25/61] x86/bugs: Add AMD retbleed= boot parameter Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 26/61] x86/bugs: Enable STIBP for JMP2RET Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 27/61] x86/bugs: Keep a per-CPU IA32_SPEC_CTRL value Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 28/61] x86/entry: Add kernel IBRS implementation Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 29/61] x86/bugs: Optimize SPEC_CTRL MSR writes Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 30/61] x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 31/61] x86/bugs: Split spectre_v2_select_mitigation() and spectre_v2_user_select_mitigation() Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 32/61] x86/bugs: Report Intel retbleed vulnerability Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 33/61] intel_idle: Disable IBRS during long idle Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 34/61] objtool: Update Retpoline validation Greg Kroah-Hartman
2022-07-13  7:45   ` Jiri Slaby
2022-07-13  7:54     ` Jiri Slaby
2022-07-13  8:17       ` Greg Kroah-Hartman
2022-07-13  9:21         ` Borislav Petkov
2022-07-13  9:50           ` [PATCH] x86/asm/32: fix ANNOTATE_UNRET_SAFE use on 32bit Jiri Slaby
2022-07-13 10:45     ` [tip: x86/urgent] x86/asm/32: Fix ANNOTATE_UNRET_SAFE use on 32-bit tip-bot2 for Jiri Slaby
2022-07-13 10:52     ` tip-bot2 for Jiri Slaby
2022-07-12 18:39 ` [PATCH 5.18 35/61] x86/xen: Rename SYS* entry points Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 36/61] x86/xen: Add UNTRAIN_RET Greg Kroah-Hartman
2022-07-12 18:39 ` Greg Kroah-Hartman [this message]
2022-07-12 18:39 ` [PATCH 5.18 38/61] x86/bugs: Do IBPB fallback check only once Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 39/61] objtool: Add entry UNRET validation Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 40/61] x86/cpu/amd: Add Spectral Chicken Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 41/61] x86/speculation: Fix RSB filling with CONFIG_RETPOLINE=n Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 42/61] x86/speculation: Fix firmware entry SPEC_CTRL handling Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 43/61] x86/speculation: Fix SPEC_CTRL write on SMT state change Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 44/61] x86/speculation: Use cached host SPEC_CTRL value for guest entry/exit Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 45/61] x86/speculation: Remove x86_spec_ctrl_mask Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 46/61] objtool: Re-add UNWIND_HINT_{SAVE_RESTORE} Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 47/61] KVM: VMX: Flatten __vmx_vcpu_run() Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 48/61] KVM: VMX: Convert launched argument to flags Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 49/61] KVM: VMX: Prevent guest RSB poisoning attacks with eIBRS Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 50/61] KVM: VMX: Fix IBRS handling after vmexit Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 51/61] x86/speculation: Fill RSB on vmexit for IBRS Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 52/61] KVM: VMX: Prevent RSB underflow before vmenter Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 53/61] x86/common: Stamp out the stepping madness Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 54/61] x86/cpu/amd: Enumerate BTC_NO Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 55/61] x86/retbleed: Add fine grained Kconfig knobs Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 56/61] x86/bugs: Add Cannon lake to RETBleed affected CPU list Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 57/61] x86/entry: Move PUSH_AND_CLEAR_REGS() back into error_entry Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 58/61] x86/bugs: Do not enable IBPB-on-entry when IBPB is not supported Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 59/61] x86/kexec: Disable RET on kexec Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 60/61] x86/speculation: Disable RRSBA behavior Greg Kroah-Hartman
2022-07-12 18:39 ` [PATCH 5.18 61/61] x86/static_call: Serialize __static_call_fixup() properly Greg Kroah-Hartman
2022-07-12 23:52 ` [PATCH 5.18 00/61] 5.18.12-rc1 review Florian Fainelli
2022-07-13  0:43 ` Zan Aziz
2022-07-13  3:16 ` Shuah Khan
2022-07-13  8:30 ` Bagas Sanjaya
2022-07-13 10:06 ` Sudip Mukherjee (Codethink)
2022-07-13 10:17 ` Ron Economos
2022-07-13 11:03 ` Naresh Kamboju
2022-07-13 13:03   ` Greg Kroah-Hartman
2022-07-13 13:58     ` Naresh Kamboju
2022-07-13 16:54       ` Thadeu Lima de Souza Cascardo
2022-07-13 14:12     ` Peter Zijlstra
2022-07-13 22:18 ` Guenter Roeck
2022-07-13 22:21 ` Rudi Heitbaum
2022-07-15 11:27 ` Greg Kroah-Hartman

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=20220712183238.460841428@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=Andrew.Cooper3@citrix.com \
    --cc=bp@suse.de \
    --cc=cascardo@canonical.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=stable@vger.kernel.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