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.

Reply via email to