Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible Bug in GCC Sanitizers?

I always compile my programs with gcc and during development always with:

gcc -g -Wall -Wextra -std=c2x -fsanitize=address,undefined

Today I noticed that the address sanitizer randomly detects SEGVs in my program. I couldn't find the error, so I pretty much just removed everything (thought I might have gotten the c23 stuff wrong, as I haven't touched that in a few months) and removed the undefined sanitizer.

The issue still persisted.

Then I tried compiling with clang and the issue was gone (at least for 10000 runs on my machine). So I guess something is wrong with GCC? Or I have some weird error in my code (but I highly doubt that given the code below). Can anyone reproduce this, or point out the error I made?

Makefile:

gcc: main.c
        gcc main.c -g -Wall -Wextra -std=c2x -fsanitize=address

clang: main.c
        clang main.c -g -Wall -Wextra -std=c2x -fsanitize=address

main.c:

#include <stdio.h>
#include <stdlib.h>

int main(void) { return EXIT_SUCCESS; }

test.sh:

#!/bin/bash

for i in {1..1000}; do
    echo $i
    ./a.out 2>> log.log
done

error:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==26035==ERROR: AddressSanitizer: SEGV on unknown address 0x62f205f20e78 (pc 0x7d61693e138f bp 0x000000000000 sp 0x7ffc6f41b390 T0)
==26035==The signal is caused by a READ memory access.
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting.

GCC and clang version:

$ clang --version
clang version 16.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

$ gcc --version
gcc (GCC) 13.2.1 20230801
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTAB`ITY or FITNESS FOR A PARTICULAR PURPOSE.

Update 1:

The issue persisted on another machine, same OS, same version of GCC and clang, but different Kernel. OS: Arch Linux Kernel:

  • Original Machine: 6.7.1-arch1-1
  • Second Machine: 6.7.0-arch3-1
like image 577
ben Avatar asked Dec 04 '25 05:12

ben


1 Answers

Update: gcc-libs version 13.2.1-4 was just released and the issue should be fixed now, simply update the package: pacman -S gcc-libs.

TL;DR: it turns out to be a bug in libasan, which has already been fixed and will be pushed to package repositories soon. Keep gcc-libs up to date and the next version after 13.2.1-3 will have the fix. Disabling ASLR may work around the issue temporarily.

Arch Linux recently applied a patch (commit) to set userspace ASLR bits to the maximum value of 32 and shipped both the LTS and non-LTS kernels with this change (commit). This was done because ASLR has been weakened/broken by Linux for a while and the issue went unnoticed until recently, so major Linux distros quickly patched and increased the ASLR bits in their kernel configs.

Having too many ASLR bits however causes issues with libasan, where high ASLR randomization breaks the ASAN allocator because it assumes less ASLR bits, reserving a memory area at an address that is too low and can collide with the randomized PIE base at runtime if the offset applied by ASLR is too high. The bug was already discovered and fixed both by libasan developers (commit) and Arch Linux maintainers in the gcc-libs package that includes libasan (commit).

The issue currently affects 6.6.11+ and 6.7.0+ Arch Linux kernels with gcc-libs version 13.2.1-3 and below. The new (fixed) version of gcc-libs still hasn't been pushed to the official Arch Linux package repositories, so we will have to wait and update gcc-libs when this happens.

If you cannot wait, the solution is to either downgrade your current kernel to 6.6.10 or below, or to build and install the latest gcc-libs package yourself. You can also try disabling ASLR to work around the issue temporarily (until next boot, or permanently if you do it through kernel command line with nokaslr, though that is not recommended as it reduces the security of your system).


Commit message from libasan explaining the issue:

D147984 was reverted because it broke lit tests on Mac. This revision is based on D147984 but maintains the old behavior for Apple.

Note that, per the follow-up discussion with MaskRay in D147984, this patch excludes Apple but includes other platforms (e.g., aarch64, MIPS64) and OSes (e.g., FreeBSD, S390X), not just x86-64 Linux.

Original commit message from D147984:

Users have discovered [*] that when CONFIG_ARCH_MMAP_RND_BITS == 32, it will frequently conflict with ASan's allocator on x86-64 Linux, because the PIE program segment base address of 0x555555555554 plus an ASLR shift of up to ((2**32) * 4K == 0x100000000000) will sometimes exceed ASan's hardcoded base address of 0x600000000000. We fix this by simply moving the allocator base to 0x500000000000, which is below the PIE program segment base address. This is cleaner than trying to move it to another location that is sandwiched between the PIE program and library segments, because if either of those grow too large, it will collide with the allocator region.

Note that we will never need to change this base address again (unless we want to increase the size of the allocator), because ASLR cannot be set above 32-bits for x86-64 Linux (the PIE program segment and library segments would collide with each other; see also ARCH_MMAP_RND_BITS_MAX in https://github.com/torvalds/linux/blob/master/arch/x86/Kconfig).

like image 121
Marco Bonelli Avatar answered Dec 07 '25 03:12

Marco Bonelli