diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-02-14 12:10:09 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-02-14 12:10:09 +0100 |
commit | 91b36d1c85ae3ad667d11c1ceeffc698126ab804 (patch) | |
tree | 5b7eb70e23728a2b13fff9e3a48e43c4b614cb49 /gcc/asan.cc | |
parent | 26f4b055d97804666d6d144b2af9b9dee0854354 (diff) | |
download | gcc-91b36d1c85ae3ad667d11c1ceeffc698126ab804.zip gcc-91b36d1c85ae3ad667d11c1ceeffc698126ab804.tar.gz gcc-91b36d1c85ae3ad667d11c1ceeffc698126ab804.tar.bz2 |
asan: Add --param=asan-kernel-mem-intrinsic-prefix= [PR108777]
While in the -fsanitize=address case libasan overloads memcpy, memset,
memmove and many other builtins, such that they are always instrumented,
Linux kernel for -fsanitize=kernel-address recently changed or is changing,
such that memcpy, memset and memmove actually aren't instrumented because
they are often used also from no_sanitize ("kernel-address") functions
and wants __{,hw,}asaN_{memcpy,memset,memmove} to be used instead
for the instrumented calls. See e.g. the https://lkml.org/lkml/2023/2/9/1182
thread. Without appropriate support on the compiler side, that will mean
any time a kernel-address instrumented function (most of them) calls
memcpy/memset/memmove, they will not be instrumented and thus won't catch
kernel bugs. Apparently clang 15 has a param for this.
The following patch implements the same (except it is a usual GCC --param,
not -mllvm argument) on the GCC side. I know this isn't a regression
bugfix, but given that -fsanitize=kernel-address has a single project that
uses it which badly wants this I think it would be worthwhile to make an
exception and get this into GCC 13 rather than waiting another year, it
won't affect non-kernel code, nor even the kernel unless the new parameter
is used.
2023-02-14 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/108777
* params.opt (-param=asan-kernel-mem-intrinsic-prefix=): New param.
* asan.h (asan_memfn_rtl): Declare.
* asan.cc (asan_memfn_rtls): New variable.
(asan_memfn_rtl): New function.
* builtins.cc (expand_builtin): If
param_asan_kernel_mem_intrinsic_prefix and function is
kernel-{,hw}address sanitized, emit calls to
__{,hw}asan_{memcpy,memmove,memset} rather than
{memcpy,memmove,memset}. Use sanitize_flags_p (SANITIZE_ADDRESS)
instead of flag_sanitize & SANITIZE_ADDRESS to check if
asan_intercepted_p functions shouldn't be expanded inline.
* gcc.dg/asan/pr108777-1.c: New test.
* gcc.dg/asan/pr108777-2.c: New test.
* gcc.dg/asan/pr108777-3.c: New test.
* gcc.dg/asan/pr108777-4.c: New test.
* gcc.dg/asan/pr108777-5.c: New test.
* gcc.dg/asan/pr108777-6.c: New test.
* gcc.dg/completion-3.c: Adjust expected multiline output.
Diffstat (limited to 'gcc/asan.cc')
-rw-r--r-- | gcc/asan.cc | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/gcc/asan.cc b/gcc/asan.cc index 57834b7..f56d084 100644 --- a/gcc/asan.cc +++ b/gcc/asan.cc @@ -391,6 +391,46 @@ asan_memintrin (void) } +/* Support for --param asan-kernel-mem-intrinsic-prefix=1. */ +static GTY(()) rtx asan_memfn_rtls[3]; + +rtx +asan_memfn_rtl (tree fndecl) +{ + int i; + const char *f, *p; + char buf[sizeof ("__hwasan_memmove")]; + + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_MEMCPY: i = 0; f = "memcpy"; break; + case BUILT_IN_MEMSET: i = 1; f = "memset"; break; + case BUILT_IN_MEMMOVE: i = 2; f = "memmove"; break; + default: gcc_unreachable (); + } + if (asan_memfn_rtls[i] == NULL_RTX) + { + tree save_name = DECL_NAME (fndecl); + tree save_assembler_name = DECL_ASSEMBLER_NAME (fndecl); + rtx save_rtl = DECL_RTL (fndecl); + if (flag_sanitize & SANITIZE_KERNEL_HWADDRESS) + p = "__hwasan_"; + else + p = "__asan_"; + strcpy (buf, p); + strcat (buf, f); + DECL_NAME (fndecl) = get_identifier (buf); + DECL_ASSEMBLER_NAME_RAW (fndecl) = NULL_TREE; + SET_DECL_RTL (fndecl, NULL_RTX); + asan_memfn_rtls[i] = DECL_RTL (fndecl); + DECL_NAME (fndecl) = save_name; + DECL_ASSEMBLER_NAME_RAW (fndecl) = save_assembler_name; + SET_DECL_RTL (fndecl, save_rtl); + } + return asan_memfn_rtls[i]; +} + + /* Checks whether section SEC should be sanitized. */ static bool |