1##############################################
2## Perform configuration steps for sanitizers.
3##############################################
4
5my_sanitize := $(strip $(LOCAL_SANITIZE))
6my_sanitize_diag := $(strip $(LOCAL_SANITIZE_DIAG))
7
8my_global_sanitize :=
9my_global_sanitize_diag :=
10ifdef LOCAL_IS_HOST_MODULE
11  ifneq ($($(my_prefix)OS),windows)
12    my_global_sanitize := $(strip $(SANITIZE_HOST))
13
14    # SANITIZE_HOST=true is a deprecated way to say SANITIZE_HOST=address.
15    my_global_sanitize := $(subst true,address,$(my_global_sanitize))
16  endif
17else
18  my_global_sanitize := $(strip $(SANITIZE_TARGET))
19  my_global_sanitize_diag := $(strip $(SANITIZE_TARGET_DIAG))
20endif
21
22# Disable global integer_overflow in excluded paths.
23ifneq ($(filter integer_overflow, $(my_global_sanitize)),)
24  combined_exclude_paths := $(INTEGER_OVERFLOW_EXCLUDE_PATHS) \
25                            $(PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS)
26
27  ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_exclude_paths)),\
28         $(filter $(dir)%,$(LOCAL_PATH)))),)
29    my_global_sanitize := $(filter-out integer_overflow,$(my_global_sanitize))
30    my_global_sanitize_diag := $(filter-out integer_overflow,$(my_global_sanitize_diag))
31  endif
32endif
33
34# Global integer sanitization doesn't support static modules.
35ifeq ($(filter SHARED_LIBRARIES EXECUTABLES,$(LOCAL_MODULE_CLASS)),)
36  my_global_sanitize := $(filter-out integer_overflow,$(my_global_sanitize))
37  my_global_sanitize_diag := $(filter-out integer_overflow,$(my_global_sanitize_diag))
38endif
39ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
40  my_global_sanitize := $(filter-out integer_overflow,$(my_global_sanitize))
41  my_global_sanitize_diag := $(filter-out integer_overflow,$(my_global_sanitize_diag))
42endif
43
44# Disable global CFI in excluded paths
45ifneq ($(filter cfi, $(my_global_sanitize)),)
46  combined_exclude_paths := $(CFI_EXCLUDE_PATHS) \
47                            $(PRODUCT_CFI_EXCLUDE_PATHS)
48
49  ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_exclude_paths)),\
50         $(filter $(dir)%,$(LOCAL_PATH)))),)
51    my_global_sanitize := $(filter-out cfi,$(my_global_sanitize))
52    my_global_sanitize_diag := $(filter-out cfi,$(my_global_sanitize_diag))
53  endif
54endif
55
56ifneq ($(my_global_sanitize),)
57  my_sanitize := $(my_global_sanitize) $(my_sanitize)
58endif
59ifneq ($(my_global_sanitize_diag),)
60  my_sanitize_diag := $(my_global_sanitize_diag) $(my_sanitize_diag)
61endif
62
63# The sanitizer specified in the product configuration wins over the previous.
64ifneq ($(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG),)
65  my_sanitize := $(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG)
66  ifeq ($(my_sanitize),never)
67    my_sanitize :=
68    my_sanitize_diag :=
69  endif
70endif
71
72ifndef LOCAL_IS_HOST_MODULE
73  # Add a filter point for 32-bit vs 64-bit sanitization (to lighten the burden)
74  SANITIZE_TARGET_ARCH ?= $(TARGET_ARCH) $(TARGET_2ND_ARCH)
75  ifeq ($(filter $(SANITIZE_TARGET_ARCH),$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
76    my_sanitize :=
77    my_sanitize_diag :=
78  endif
79endif
80
81# Add a filter point based on module owner (to lighten the burden). The format is a space- or
82# colon-separated list of owner names.
83ifneq (,$(SANITIZE_NEVER_BY_OWNER))
84  ifneq (,$(LOCAL_MODULE_OWNER))
85    ifneq (,$(filter $(LOCAL_MODULE_OWNER),$(subst :, ,$(SANITIZE_NEVER_BY_OWNER))))
86      $(warning Not sanitizing $(LOCAL_MODULE) based on module owner.)
87      my_sanitize :=
88      my_sanitize_diag :=
89    endif
90  endif
91endif
92
93# Don't apply sanitizers to NDK code.
94ifdef LOCAL_SDK_VERSION
95  my_sanitize :=
96  my_global_sanitize :=
97  my_sanitize_diag :=
98endif
99
100# Never always wins.
101ifeq ($(LOCAL_SANITIZE),never)
102  my_sanitize :=
103  my_sanitize_diag :=
104endif
105
106# Enable CFI in included paths (for Arm64 only).
107ifeq ($(filter cfi, $(my_sanitize)),)
108  ifneq ($(filter arm64,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
109    combined_include_paths := $(CFI_INCLUDE_PATHS) \
110                              $(PRODUCT_CFI_INCLUDE_PATHS)
111
112    ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_include_paths)),\
113           $(filter $(dir)%,$(LOCAL_PATH)))),)
114      my_sanitize := cfi $(my_sanitize)
115    endif
116  endif
117endif
118
119# If CFI is disabled globally, remove it from my_sanitize.
120ifeq ($(strip $(ENABLE_CFI)),false)
121  my_sanitize := $(filter-out cfi,$(my_sanitize))
122  my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag))
123endif
124
125# Disable CFI for arm32 (b/35157333).
126ifneq ($(filter arm,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
127  my_sanitize := $(filter-out cfi,$(my_sanitize))
128  my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag))
129endif
130
131# Also disable CFI if ASAN is enabled.
132ifneq ($(filter address,$(my_sanitize)),)
133  my_sanitize := $(filter-out cfi,$(my_sanitize))
134  my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag))
135endif
136
137# Disable sanitizers which need the UBSan runtime for host targets.
138ifdef LOCAL_IS_HOST_MODULE
139  my_sanitize := $(filter-out cfi,$(my_sanitize))
140  my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag))
141  my_sanitize := $(filter-out signed-integer-overflow unsigned-integer-overflow integer_overflow,$(my_sanitize))
142  my_sanitize_diag := $(filter-out signed-integer-overflow unsigned-integer-overflow integer_overflow,$(my_sanitize_diag))
143endif
144
145# Support for local sanitize blacklist paths.
146ifneq ($(my_sanitize)$(my_global_sanitize),)
147  ifneq ($(LOCAL_SANITIZE_BLACKLIST),)
148    my_cflags += -fsanitize-blacklist=$(LOCAL_PATH)/$(LOCAL_SANITIZE_BLACKLIST)
149  endif
150  ifneq ($(LOCAL_SANITIZE_BLOCKLIST),)
151    my_cflags += -fsanitize-blacklist=$(LOCAL_PATH)/$(LOCAL_SANITIZE_BLOCKLIST)
152  endif
153endif
154
155# Disable integer_overflow if LOCAL_NOSANITIZE=integer.
156ifneq ($(filter integer_overflow, $(my_global_sanitize) $(my_sanitize)),)
157  ifneq ($(filter integer, $(strip $(LOCAL_NOSANITIZE))),)
158    my_sanitize := $(filter-out integer_overflow,$(my_sanitize))
159    my_sanitize_diag := $(filter-out integer_overflow,$(my_sanitize_diag))
160  endif
161endif
162
163my_nosanitize = $(strip $(LOCAL_NOSANITIZE))
164ifneq ($(my_nosanitize),)
165  my_sanitize := $(filter-out $(my_nosanitize),$(my_sanitize))
166endif
167
168ifneq ($(filter arm x86 x86_64,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
169  my_sanitize := $(filter-out hwaddress,$(my_sanitize))
170endif
171
172ifneq ($(filter hwaddress,$(my_sanitize)),)
173  my_sanitize := $(filter-out address,$(my_sanitize))
174  my_sanitize := $(filter-out thread,$(my_sanitize))
175  my_sanitize := $(filter-out cfi,$(my_sanitize))
176endif
177
178ifneq ($(filter hwaddress,$(my_sanitize)),)
179  my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)HWADDRESS_SANITIZER_RUNTIME_LIBRARY)
180  ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
181    ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
182      my_static_libraries := $(my_static_libraries) \
183                             $($(LOCAL_2ND_ARCH_VAR_PREFIX)HWADDRESS_SANITIZER_STATIC_LIBRARY) \
184                             libdl
185    endif
186  endif
187endif
188
189# TSAN is not supported on 32-bit architectures. For non-multilib cases, make
190# its use an error. For multilib cases, don't use it for the 32-bit case.
191ifneq ($(filter thread,$(my_sanitize)),)
192  ifeq ($(my_32_64_bit_suffix),32)
193    ifeq ($(my_module_multilib),both)
194        my_sanitize := $(filter-out thread,$(my_sanitize))
195    else
196        $(error $(LOCAL_PATH): $(LOCAL_MODULE): TSAN cannot be used for 32-bit modules.)
197    endif
198  else
199    my_shared_libraries += $(TSAN_RUNTIME_LIBRARY)
200  endif
201endif
202
203ifneq ($(filter safe-stack,$(my_sanitize)),)
204  ifeq ($(my_32_64_bit_suffix),32)
205    my_sanitize := $(filter-out safe-stack,$(my_sanitize))
206  endif
207endif
208
209# Disable Scudo if ASan or TSan is enabled.
210ifneq ($(filter address thread hwaddress,$(my_sanitize)),)
211  my_sanitize := $(filter-out scudo,$(my_sanitize))
212endif
213
214# Or if disabled globally.
215ifeq ($(PRODUCT_DISABLE_SCUDO),true)
216  my_sanitize := $(filter-out scudo,$(my_sanitize))
217endif
218
219# Undefined symbols can occur if a non-sanitized library links
220# sanitized static libraries. That's OK, because the executable
221# always depends on the ASan runtime library, which defines these
222# symbols.
223ifneq ($(filter address thread,$(strip $(SANITIZE_TARGET))),)
224  ifndef LOCAL_IS_HOST_MODULE
225    ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
226      ifeq ($(my_sanitize),)
227        my_allow_undefined_symbols := true
228      endif
229    endif
230  endif
231endif
232
233ifneq ($(filter default-ub,$(my_sanitize)),)
234  my_sanitize := $(CLANG_DEFAULT_UB_CHECKS)
235endif
236
237ifneq ($(filter fuzzer,$(my_sanitize)),)
238  # SANITIZE_TARGET='fuzzer' actually means to create the fuzzer coverage
239  # information, not to link against the fuzzer main().
240  my_sanitize := $(filter-out fuzzer,$(my_sanitize))
241  my_sanitize += fuzzer-no-link
242
243  # TODO(b/131771163): Disable LTO for fuzzer builds. Note that Cfi causes
244  # dependency on LTO.
245  my_sanitize := $(filter-out cfi,$(my_sanitize))
246  my_cflags += -fno-lto
247  my_ldflags += -fno-lto
248
249  # TODO(b/133876586): Disable experimental pass manager for fuzzer builds.
250  my_cflags += -fno-experimental-new-pass-manager
251endif
252
253ifneq ($(filter integer_overflow,$(my_sanitize)),)
254  # Respect LOCAL_NOSANITIZE for integer-overflow flags.
255  ifeq ($(filter signed-integer-overflow, $(strip $(LOCAL_NOSANITIZE))),)
256    my_sanitize += signed-integer-overflow
257  endif
258  ifeq ($(filter unsigned-integer-overflow, $(strip $(LOCAL_NOSANITIZE))),)
259    my_sanitize += unsigned-integer-overflow
260  endif
261  my_cflags += $(INTEGER_OVERFLOW_EXTRA_CFLAGS)
262
263  # Check for diagnostics mode.
264  ifneq ($(filter integer_overflow,$(my_sanitize_diag)),)
265    ifneq ($(filter SHARED_LIBRARIES EXECUTABLES,$(LOCAL_MODULE_CLASS)),)
266      ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
267        my_sanitize_diag += signed-integer-overflow
268        my_sanitize_diag += unsigned-integer-overflow
269      else
270        $(call pretty-error,Make cannot apply integer overflow diagnostics to static binary.)
271      endif
272    else
273      $(call pretty-error,Make cannot apply integer overflow diagnostics to static library.)
274    endif
275  endif
276  my_sanitize := $(filter-out integer_overflow,$(my_sanitize))
277endif
278
279# Makes sure integer_overflow diagnostics is removed from the diagnostics list
280# even if integer_overflow is not set for some reason.
281ifneq ($(filter integer_overflow,$(my_sanitize_diag)),)
282  my_sanitize_diag := $(filter-out integer_overflow,$(my_sanitize_diag))
283endif
284
285ifneq ($(my_sanitize),)
286  fsanitize_arg := $(subst $(space),$(comma),$(my_sanitize))
287  my_cflags += -fsanitize=$(fsanitize_arg)
288  my_asflags += -fsanitize=$(fsanitize_arg)
289
290  # When fuzzing, we wish to crash with diagnostics on any bug.
291  ifneq ($(filter fuzzer-no-link,$(my_sanitize)),)
292    my_cflags += -fno-sanitize-trap=all
293    my_cflags += -fno-sanitize-recover=all
294    my_ldflags += -fsanitize=fuzzer-no-link
295  else ifdef LOCAL_IS_HOST_MODULE
296    my_cflags += -fno-sanitize-recover=all
297    my_ldflags += -fsanitize=$(fsanitize_arg)
298  else
299    my_cflags += -fsanitize-trap=all
300    my_cflags += -ftrap-function=abort
301    ifneq ($(filter address thread,$(my_sanitize)),)
302      my_cflags += -fno-sanitize-trap=address,thread
303      my_shared_libraries += libdl
304    endif
305  endif
306endif
307
308ifneq ($(filter cfi,$(my_sanitize)),)
309  # __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp).
310  # LLVM is not set up to do this on a function basis, so force Thumb on the
311  # entire module.
312  LOCAL_ARM_MODE := thumb
313  my_cflags += $(CFI_EXTRA_CFLAGS)
314  my_asflags += $(CFI_EXTRA_ASFLAGS)
315  # Only append the default visibility flag if -fvisibility has not already been
316  # set to hidden.
317  ifeq ($(filter -fvisibility=hidden,$(LOCAL_CFLAGS)),)
318    my_cflags += -fvisibility=default
319  endif
320  my_ldflags += $(CFI_EXTRA_LDFLAGS)
321  my_arflags += --plugin $(LLVM_PREBUILTS_PATH)/../lib64/LLVMgold.so
322
323  ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
324        my_ldflags := $(filter-out -fsanitize-cfi-cross-dso,$(my_ldflags))
325        my_cflags := $(filter-out -fsanitize-cfi-cross-dso,$(my_cflags))
326  else
327        # Apply the version script to non-static executables
328        my_ldflags += -Wl,--version-script,build/soong/cc/config/cfi_exports.map
329        LOCAL_ADDITIONAL_DEPENDENCIES += build/soong/cc/config/cfi_exports.map
330  endif
331endif
332
333# If local or global modules need ASAN, add linker flags.
334ifneq ($(filter address,$(my_global_sanitize) $(my_sanitize)),)
335  my_ldflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS)
336  ifdef LOCAL_IS_HOST_MODULE
337    # -nodefaultlibs (provided with libc++) prevents the driver from linking
338    # libraries needed with -fsanitize=address. http://b/18650275 (WAI)
339    my_ldflags += -Wl,--no-as-needed
340  else
341    # Add asan libraries unless LOCAL_MODULE is the asan library.
342    # ASan runtime library must be the first in the link order.
343    ifeq (,$(filter $(LOCAL_MODULE),$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_RUNTIME_LIBRARY)))
344      my_shared_libraries := $($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
345                             $(my_shared_libraries)
346    endif
347
348    # Do not add unnecessary dependency in shared libraries.
349    ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
350      my_ldflags += -Wl,--as-needed
351    endif
352
353    ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
354      ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
355        my_linker := $($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER)
356        # Make sure linker_asan get installed.
357        $(LOCAL_INSTALLED_MODULE) : | $(PRODUCT_OUT)$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER_FILE)
358      endif
359    endif
360  endif
361endif
362
363# If local module needs ASAN, add compiler flags.
364ifneq ($(filter address,$(my_sanitize)),)
365  # Frame pointer based unwinder in ASan requires ARM frame setup.
366  LOCAL_ARM_MODE := arm
367  my_cflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS)
368  ifndef LOCAL_IS_HOST_MODULE
369    my_cflags += -mllvm -asan-globals=0
370  endif
371endif
372
373# If local module needs HWASAN, add compiler flags.
374ifneq ($(filter hwaddress,$(my_sanitize)),)
375  my_cflags += $(HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS)
376endif
377
378# Use minimal diagnostics when integer overflow is enabled; never do it for HOST modules
379ifeq ($(LOCAL_IS_HOST_MODULE),)
380  # Pre-emptively add UBSAN minimal runtime incase a static library dependency requires it
381  ifeq ($(filter STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
382    ifndef LOCAL_SDK_VERSION
383      my_static_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_MINIMAL_RUNTIME_LIBRARY)
384      my_ldflags += -Wl,--exclude-libs,$($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_MINIMAL_RUNTIME_LIBRARY).a
385    endif
386  endif
387  ifneq ($(filter unsigned-integer-overflow signed-integer-overflow integer,$(my_sanitize)),)
388    ifeq ($(filter unsigned-integer-overflow signed-integer-overflow integer,$(my_sanitize_diag)),)
389      ifeq ($(filter cfi,$(my_sanitize_diag)),)
390        ifeq ($(filter address hwaddress fuzzer-no-link,$(my_sanitize)),)
391          my_cflags += -fsanitize-minimal-runtime
392          my_cflags += -fno-sanitize-trap=integer
393          my_cflags += -fno-sanitize-recover=integer
394        endif
395      endif
396    endif
397  endif
398endif
399
400# For Scudo, we opt for the minimal runtime, unless some diagnostics are enabled.
401ifneq ($(filter scudo,$(my_sanitize)),)
402  ifeq ($(filter unsigned-integer-overflow signed-integer-overflow integer cfi,$(my_sanitize_diag)),)
403    my_cflags += -fsanitize-minimal-runtime
404  endif
405  ifneq ($(filter -fsanitize-minimal-runtime,$(my_cflags)),)
406    my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)SCUDO_MINIMAL_RUNTIME_LIBRARY)
407  else
408    my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)SCUDO_RUNTIME_LIBRARY)
409  endif
410endif
411
412ifneq ($(strip $(LOCAL_SANITIZE_RECOVER)),)
413  recover_arg := $(subst $(space),$(comma),$(LOCAL_SANITIZE_RECOVER)),
414  my_cflags += -fsanitize-recover=$(recover_arg)
415endif
416
417ifneq ($(strip $(LOCAL_SANITIZE_NO_RECOVER)),)
418  no_recover_arg := $(subst $(space),$(comma),$(LOCAL_SANITIZE_NO_RECOVER)),
419  my_cflags += -fno-sanitize-recover=$(no_recover_arg)
420endif
421
422ifneq ($(my_sanitize_diag),)
423  # TODO(vishwath): Add diagnostic support for static executables once
424  # we switch to clang-4393122 (which adds the static ubsan runtime
425  # that this depends on)
426  ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
427    notrap_arg := $(subst $(space),$(comma),$(my_sanitize_diag)),
428    my_cflags += -fno-sanitize-trap=$(notrap_arg)
429    # Diagnostic requires a runtime library, unless ASan or TSan are also enabled.
430    ifeq ($(filter address thread scudo hwaddress,$(my_sanitize)),)
431      # Does not have to be the first DT_NEEDED unlike ASan.
432      my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_RUNTIME_LIBRARY)
433    endif
434  endif
435endif
436
437# http://b/119329758, Android core does not boot up with this sanitizer yet.
438# Previously sanitized modules might not pass new implicit-integer-sign-change check.
439# Disable this check unless it has been explicitly specified.
440ifneq ($(findstring fsanitize,$(my_cflags)),)
441  ifneq ($(findstring integer,$(my_cflags)),)
442    ifeq ($(findstring sanitize=implicit-integer-sign-change,$(my_cflags)),)
443      my_cflags += -fno-sanitize=implicit-integer-sign-change
444    endif
445  endif
446endif
447