Re: [PATCH] ubsan: disable unsigned-integer-overflow sanitizer with clang

From: Nathan Chancellor
Date: Wed Jan 06 2021 - 22:35:37 EST


On Wed, Jan 06, 2021 at 11:06:39PM +0100, Arnd Bergmann wrote:
> On Wed, Jan 6, 2021 at 10:38 PM Nathan Chancellor
> <natechancellor@xxxxxxxxx> wrote:
> > On Wed, Jan 06, 2021 at 10:12:51AM +0100, Arnd Bergmann wrote:
> > > On Tue, Jan 5, 2021 at 10:25 AM Arnd Bergmann <arnd@xxxxxxxxxx> wrote:
> > > >
> > > > On Mon, Jan 4, 2021 at 11:33 PM Nathan Chancellor
> > > > <natechancellor@xxxxxxxxx> wrote:
> > > > > On Wed, Dec 30, 2020 at 05:13:03PM +0100, Marco Elver wrote:
> > > > > > On Wed, 30 Dec 2020 at 16:47, Arnd Bergmann <arnd@xxxxxxxxxx> wrote:
> > > > > > >
> > > > > > > From: Arnd Bergmann <arnd@xxxxxxxx>
> > > > > > >
> > > > > > > Building ubsan kernels even for compile-testing introduced these
> > > > > > > warnings in my randconfig environment:
> > > > > > >
> > > > > > > crypto/blake2b_generic.c:98:13: error: stack frame size of 9636 bytes in function 'blake2b_compress' [-Werror,-Wframe-larger-than=]
> > > > > > > static void blake2b_compress(struct blake2b_state *S,
> > > > > > > crypto/sha512_generic.c:151:13: error: stack frame size of 1292 bytes in function 'sha512_generic_block_fn' [-Werror,-Wframe-larger-than=]
> > > > > > > static void sha512_generic_block_fn(struct sha512_state *sst, u8 const *src,
> > > > > > > lib/crypto/curve25519-fiat32.c:312:22: error: stack frame size of 2180 bytes in function 'fe_mul_impl' [-Werror,-Wframe-larger-than=]
> > > > > > > static noinline void fe_mul_impl(u32 out[10], const u32 in1[10], const u32 in2[10])
> > > > > > > lib/crypto/curve25519-fiat32.c:444:22: error: stack frame size of 1588 bytes in function 'fe_sqr_impl' [-Werror,-Wframe-larger-than=]
> > > > > > > static noinline void fe_sqr_impl(u32 out[10], const u32 in1[10])
> > > > > > >
> > > > > > > Further testing showed that this is caused by
> > > > > > > -fsanitize=unsigned-integer-overflow.
> > > > > > >
> > > > > > > The one in blake2b immediately overflows the 8KB stack area on 32-bit
> > > > > > > architectures, so better ensure this never happens by making this
> > > > > > > option gcc-only.
> > > > >
> > > > > This patch also fixes the failed BUILD_BUG issue in mm/mremap.c that you
> > > > > sent a patch for [1], along with a couple of other issues I see such as:
> > > >
> > > > I'm fairly sure I still saw that BUILD_BUG() even after I had applied this
> > > > patch, I would guess that one just depends on inlining decisions that
> > > > are influenced by all kinds of compiler options including
> > > > -fsanitize=unsigned-integer-overflow, so it becomes less likely.
> > > >
> > > > I'll revert my other patch in the randconfig tree to see if it comes back.
> > >
> > > The qcom/gpi.c failure still happens with this patch applied:
> > >
> > > In file included from /git/arm-soc/drivers/dma/qcom/gpi.c:8:
> > > In function 'field_multiplier',
> > > inlined from 'gpi_update_reg' at
> > > /git/arm-soc/include/linux/bitfield.h:124:17:
> > > /git/arm-soc/include/linux/bitfield.h:119:3: error: call to
> > > '__bad_mask' declared with attribute error: bad bitfield mask
> > > 119 | __bad_mask();
> > > | ^~~~~~~~~~~~
> > > In function 'field_multiplier',
> > > inlined from 'gpi_update_reg' at
> > > /git/arm-soc/include/linux/bitfield.h:154:1:
> > > /git/arm-soc/include/linux/bitfield.h:119:3: error: call to
> > > '__bad_mask' declared with attribute error: bad bitfield mask
> > > 119 | __bad_mask();
> > > | ^~~~~~~~~~~~
> > >
> > > See https://pastebin.com/8UH6x4A2 for the .config
> > >
> > > Arnd
> >
> > That config does not build for me, am I holding it wrong?
> >
> > $ curl -LSso .config https://pastebin.com/raw/8UH6x4A2
>
> Sorry about that, you ran into a bug that I have applied a
> local fix for. You could enable CONFIG_EPOLL, or apply
> this patch:
>
> https://lore.kernel.org/linux-arm-kernel/20200429132349.1294904-1-arnd@xxxxxxxx/
>
> Arnd

I decided to just try to build the file directly. As it turns out,
ARCH=arm allyesconfig does not show any error in get_extent or
gpi_update_reg but ARCH=arm64 allyesconfig does. Looks like this is
because of the lack of CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL for ARCH=arm.

$ rg UBSAN out/{arm,arm64}/.config
out/arm64/.config
13853:CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
13854:CONFIG_UBSAN=y
13855:CONFIG_CC_HAS_UBSAN_BOUNDS=y
13856:CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y
13857:CONFIG_UBSAN_BOUNDS=y
13858:CONFIG_UBSAN_ARRAY_BOUNDS=y
13859:CONFIG_UBSAN_SHIFT=y
13860:CONFIG_UBSAN_DIV_ZERO=y
13861:CONFIG_UBSAN_UNREACHABLE=y
13862:CONFIG_UBSAN_SIGNED_OVERFLOW=y
13863:CONFIG_UBSAN_UNSIGNED_OVERFLOW=y
13864:CONFIG_UBSAN_OBJECT_SIZE=y
13865:CONFIG_UBSAN_BOOL=y
13866:CONFIG_UBSAN_ENUM=y
13867:CONFIG_UBSAN_SANITIZE_ALL=y
13868:CONFIG_TEST_UBSAN=m

out/arm/.config
14133:CONFIG_UBSAN=y
14134:CONFIG_CC_HAS_UBSAN_BOUNDS=y
14135:CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y
14136:CONFIG_UBSAN_BOUNDS=y
14137:CONFIG_UBSAN_ARRAY_BOUNDS=y
14138:CONFIG_UBSAN_SHIFT=y
14139:CONFIG_UBSAN_DIV_ZERO=y
14140:CONFIG_UBSAN_UNREACHABLE=y
14141:CONFIG_UBSAN_SIGNED_OVERFLOW=y
14142:CONFIG_UBSAN_UNSIGNED_OVERFLOW=y
14143:CONFIG_UBSAN_OBJECT_SIZE=y
14144:CONFIG_UBSAN_BOOL=y
14145:CONFIG_UBSAN_ENUM=y
14146:CONFIG_TEST_UBSAN=m

$ llvm-nm -S out/arm64/drivers/dma/qcom/gpi.o |& rg __bad_mask
U __bad_mask

$ llvm-nm -S out/arm/drivers/dma/qcom/gpi.o |& rg __bad_mask

Applying this diff causes __bad_mask to show up:

diff --git a/drivers/dma/qcom/Makefile b/drivers/dma/qcom/Makefile
index 50f1e7014693..c261adb47960 100644
--- a/drivers/dma/qcom/Makefile
+++ b/drivers/dma/qcom/Makefile
@@ -2,6 +2,7 @@
obj-$(CONFIG_QCOM_ADM) += qcom_adm.o
obj-$(CONFIG_QCOM_BAM_DMA) += bam_dma.o
obj-$(CONFIG_QCOM_GPI_DMA) += gpi.o
+UBSAN_SANITIZE_gpi.o := y
obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mgmt.o
hdma_mgmt-objs := hidma_mgmt.o hidma_mgmt_sys.o
obj-$(CONFIG_QCOM_HIDMA) += hdma.o

$ make -skj"$(nproc)" ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- LLVM=1 \
O=out/arm distclean allyesconfig drivers/dma/qcom/gpi.o

$ llvm-nm -S out/arm/drivers/dma/qcom/gpi.o |& rg __bad_mask
U __bad_mask

So I guess I am curious how you saw this pop up. Not to mention it seems
like that error is with GCC rather than clang?

For what it's worth, when I run that .config through olddefconfig,
CONFIG_ARCH_QCOM and CONFIG_QCOM_GPI_DMA get disabled... Am I doing
something wrong?

$ curl -LSso /tmp/out/arm/.config https://pastebin.com/raw/8UH6x4A2

$ rg "CONFIG_ARCH_QCOM|CONFIG_QCOM_GPI_DMA" /tmp/out/arm/.config
377:CONFIG_ARCH_QCOM=y
4437:CONFIG_QCOM_GPI_DMA=y

$ make.sh ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- LLVM=1
O=/tmp/out/arm olddefconfig
.config:364:warning: override: ARCH_DOVE changes choice state

$ rg "CONFIG_ARCH_QCOM|CONFIG_QCOM_GPI_DMA" /tmp/out/arm/.config

Cheers,
Nathan