Re: [PATCH] x86: efi: avoid BUILD_BUG_ON() for non-constant p4d_index

From: Arvind Sankar
Date: Fri Jan 15 2021 - 14:12:40 EST


On Fri, Jan 15, 2021 at 08:07:29PM +0100, Borislav Petkov wrote:
> On Fri, Jan 15, 2021 at 11:32:03AM -0700, Nathan Chancellor wrote:
> > I triggered it with CONFIG_UBSAN=y + CONFIG_UBSAN_UNSIGNED_OVERFLOW=y
> > (it can be exposed with an allyesconfig/allmodconfig on mainline
> > currently).
>
> Yah, I can trigger with that, thanks.
>
> But I'll be damned, check this out:
>
> clang preprocesses to this:
>
> do { extern void __compiletime_assert_332(void) ; if (!(!(p4d_index((-68 * ((1UL) << 30))) != p4d_index((0xffffffffff000000UL))))) __compiletime_assert_332(); } while (0);
>
> The resulting asm is:
>
> .LBB1_32:
> movabsq $-73014444032, %r13 # imm = 0xFFFFFFEF00000000
> testb $1, %al
> jne .LBB1_33
> .LBB1_34:
> xorl %r14d, %ebx
> testl $33554431, %ebx # imm = 0x1FFFFFF
> je .LBB1_36
> # %bb.35:
> callq __compiletime_assert_332
>
> so the undefined symbol is there, leading to:
>
> ld: arch/x86/platform/efi/efi_64.o: in function `efi_sync_low_kernel_mappings':
> /home/boris/kernel/linux/arch/x86/platform/efi/efi_64.c:140: undefined reference to `__compiletime_assert_332'
>
> Now look at gcc:
>
> It preprocesses to:
>
> do { extern void __compiletime_assert_332(void) __attribute__((__error__("BUILD_BUG_ON failed: " "p4d_index(EFI_VA_END) != p4d_index(MODULES_END)"))); if (!(!(p4d_index((-68 * ((1UL) << 30))) != p4d_index((0xffffffffff000000UL))))) __compiletime_assert_332(); } while (0);
>
>
> Resulting asm:
>
> $ grep __compiletime_assert_332 arch/x86/platform/efi/efi_64.s
> $
>
> That thing has been optimized away!
>
> Which means, those build assertions are gone on gcc and they don't catch
> diddly squat. I sure hope I'm missing something here...

That's how build-time assertions work: they are _supposed_ to be
optimized away completely when the assertion is true. If they're
_not_ optimized away, the build will fail.