CVE-2022-36123: Insufficient Information (NVD-CWE-noinfo)
value: The Linux kernel before 5.18.13 lacks a certain clear operation for the block starting symbol (.bss). This allows Xen PV guest OS users to cause a denial of service or gain privileges.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 7.8
Published: 2022-07-29T14:15Z
Repository: https://github.com/torvalds/linux
Language: C
Files changed: arch/x86/include/asm/setup.h, arch/x86/kernel/head64.c, arch/x86/xen/enlighten_pv.c, arch/x86/xen/xen-head.S
Commit date: 2022-07-01 10:57:52 +0200
Commit message: x86/xen: Use clear_bss() for Xen PV guests

Instead of clearing the bss area in assembly code, use the clear_bss()
function.

This requires to pass the start_info address as parameter to
xen_start_kernel() in order to avoid the xen_start_info being zeroed
again.

Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Link: https://lore.kernel.org/r/20220630071441.28576-2-jgross@suse.com

Diff: diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index f8b9ee97a891..f37cbff7354c 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -118,10 +118,13 @@ void *extend_brk(size_t size, size_t align);
 #define RESERVE_BRK(name, size)					\
 	__section(".bss..brk") __aligned(1) __used	\
 	static char __brk_##name[size]
 
 extern void probe_roms(void);
+
+void clear_bss(void);
+
 #ifdef __i386__
 
 asmlinkage void __init i386_start_kernel(void);
 
 #else
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index bd4a34100ed0..e7e233209a8c 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -424,11 +424,11 @@ void __init do_early_exception(struct pt_regs *regs, int trapnr)
 	early_fixup_exception(regs, trapnr);
 }
 
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
-static void __init clear_bss(void)
+void __init clear_bss(void)
 {
 	memset(__bss_start, 0,
 	       (unsigned long) __bss_stop - (unsigned long) __bss_start);
 }
 
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index e3297b15701c..70fb2ea85e90 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1181,19 +1181,23 @@ static void __init xen_domu_set_legacy_features(void)
 }
 
 extern void early_xen_iret_patch(void);
 
 /* First C function to be called on Xen boot */
-asmlinkage __visible void __init xen_start_kernel(void)
+asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
 {
 	struct physdev_set_iopl set_iopl;
 	unsigned long initrd_start = 0;
 	int rc;
 
-	if (!xen_start_info)
+	if (!si)
 		return;
 
+	clear_bss();
+
+	xen_start_info = si;
+
 	__text_gen_insn(&early_xen_iret_patch,
 			JMP32_INSN_OPCODE, &early_xen_iret_patch, &xen_iret,
 			JMP32_INSN_SIZE);
 
 	xen_domain_type = XEN_PV_DOMAIN;
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 3a2cd93bf059..13af6fe453e3 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -46,19 +46,10 @@ SYM_CODE_END(hypercall_page)
 SYM_CODE_START(startup_xen)
 	UNWIND_HINT_EMPTY
 	ANNOTATE_NOENDBR
 	cld
 
-	/* Clear .bss */
-	xor %eax,%eax
-	mov $__bss_start, %rdi
-	mov $__bss_stop, %rcx
-	sub %rdi, %rcx
-	shr $3, %rcx
-	rep stosq
-
-	mov %rsi, xen_start_info
 	mov initial_stack(%rip), %rsp
 
 	/* Set up %gs.
 	 *
 	 * The base of %gs always points to fixed_percpu_data.  If the
@@ -69,10 +60,11 @@ SYM_CODE_START(startup_xen)
 	movl	$MSR_GS_BASE,%ecx
 	movq	$INIT_PER_CPU_VAR(fixed_percpu_data),%rax
 	cdq
 	wrmsr
 
+	mov	%rsi, %rdi
 	call xen_start_kernel
 SYM_CODE_END(startup_xen)
 	__FINIT
 
 #ifdef CONFIG_XEN_PV_SMP

Vulnerable code: static void __init clear_bss(void)
asmlinkage __visible void __init xen_start_kernel(void)
	if (!xen_start_info)
	/* Clear .bss */
	xor %eax,%eax
	mov $__bss_start, %rdi
	mov $__bss_stop, %rcx
	sub %rdi, %rcx
	shr $3, %rcx
	rep stosq

	mov %rsi, xen_start_info
Fixed code: 
void clear_bss(void);

void __init clear_bss(void)
asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
	if (!si)
	clear_bss();

	xen_start_info = si;

	mov	%rsi, %rdi