https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128362
Bug ID: 128362
Summary: opts.cc: -fno-sanitize=kernel-hwaddress clears
SANITIZE_HWADDRESS and leaves sticky kernel param
reductions under -fsanitize=hwaddress
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: 220245569 at seu dot edu.cn
CC: 220255623 at seu dot edu.cn, dodji at gcc dot gnu.org,
dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org,
jianhao.xu at seu dot edu.cn, kcc at gcc dot gnu.org
Target Milestone: ---
Target: aarch64-*-*
Reproducer
----------
$ cat trigger.c
void escape (char *);
int probe_hwasan (int n)
{
char local[32];
char *dyn = (char *) __builtin_alloca (n > 0 ? n : 1);
local[0] = 1;
dyn[0] = 2;
escape (local);
escape (dyn);
return local[0] + dyn[0];
}
Compile flag: aarch64-linux-gnu-gcc -O2 -fsanitize=hwaddress
-fno-sanitize=kernel-hwaddress -S trigger.c
probe_hwasan:
cmp w0, 0
stp x29, x30, [sp, -64]!
...
bl escape # no __hwasan_* checks, no __hwasan_init, no
stack tagging
mov x0, sp
bl escape
...
ret
Root cause
----------
1. parse_sanitizer_options (gcc/opts.cc:2388-2395):
hwaddress has mask SANITIZE_HWADDRESS | SANITIZE_USER_HWADDRESS and
kernel-hwaddress has mask SANITIZE_HWADDRESS | SANITIZE_KERNEL_HWADDRESS.
When negating an option (value == 0), parse_sanitizer_options clears
~sanitizer_opts[i].flag and restores SANITIZE_ADDRESS if either
SANITIZE_KERNEL_ADDRESS | SANITIZE_USER_ADDRESS remains set, but omits the
same restoration for SANITIZE_HWADDRESS:
flags &= ~sanitizer_opts[i].flag;
if (flags & (SANITIZE_KERNEL_ADDRESS | SANITIZE_USER_ADDRESS))
flags |= SANITIZE_ADDRESS;
With -fsanitize=hwaddress -fno-sanitize=kernel-hwaddress,
SANITIZE_USER_HWADDRESS stays set while SANITIZE_HWADDRESS is cleared, so
the driver links -lhwasan (gcc.cc:10594) while gate_hwasan and
hwasan_sanitize_p (asan.cc:1865, 5063) emit no instrumentation.
2. common_handle_option (gcc/opts.cc:2842-2860) zeroes
param_hwasan_instrument_stack, param_hwasan_random_frame_tag, and
param_hwasan_instrument_allocas as soon as -fsanitize=kernel-hwaddress is
seen rather than in finish_options, so a later
-fno-sanitize=kernel-hwaddress
-fsanitize=hwaddress leaves stack/alloca tagging disabled.
Suggested Fix
-------------
1. In parse_sanitizer_options (gcc/opts.cc:2395), add:
if (flags & (SANITIZE_KERNEL_HWADDRESS | SANITIZE_USER_HWADDRESS))
flags |= SANITIZE_HWADDRESS;
2. Move the SANITIZE_KERNEL_ADDRESS / SANITIZE_KERNEL_HWADDRESS parameter
defaults from common_handle_option into finish_options.