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
Update:
gcc-libsversion13.2.1-4was 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-libsup to date and the next version after13.2.1-3will 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-libspackage that includes libasan (commit).The issue currently affects 6.6.11+ and 6.7.0+ Arch Linux kernels with
gcc-libsversion13.2.1-3and below. The new (fixed) version ofgcc-libsstill hasn't been pushed to the official Arch Linux package repositories, so we will have to wait and updategcc-libswhen 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-libspackage 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 withnokaslr, though that is not recommended as it reduces the security of your system).Commit message from libasan explaining the issue: