Skip to content

KASAN Support #1087

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions scripts/Kconfig.include
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,8 @@ ld-version := $(shell,set -- $(ld-info) && echo $2)
cc-option-bit = $(if-success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null,$(1))
m32-flag := $(cc-option-bit,-m32)
m64-flag := $(cc-option-bit,-m64)

# $(rustc-option,<flag>)
# Return y if the Rust compiler supports <flag>, n otherwise
# Calls to this should be guarded so that they are not evaluated if CONFIG_HAVE_RUST is not set.
rustc-option = $(success,trap "rm -rf .tmp_$$" EXIT; mkdir .tmp_$$; $(RUSTC) $(1) --crate-type=rlib /dev/null -o .tmp_$$/tmp.rlib)
15 changes: 15 additions & 0 deletions scripts/Makefile.compiler
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,18 @@ clang-min-version = $(call test-ge, $(CONFIG_CLANG_VERSION), $1)
# ld-option
# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3))

# __rustc-option
# Usage: MY_RUSTFLAGS += $(call __rustc-option,$(RUSTC),$(MY_RUSTFLAGS),-Cinstrument-coverage,-Zinstrument-coverage)
__rustc-option = $(call try-run,\
$(1) $(2) $(3) --crate-type=rlib /dev/null -o "$$TMP",$(3),$(4))

# rustc-option
# Usage: rustflags-y += $(call rustc-option,-Cinstrument-coverage,-Zinstrument-coverage)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For flags that can be determined by the version, I wonder if it would be best to tell people to use rustc-min-version instead (I sent a (broken) patch adding that one and an example use case).

On one hand, having them versioned means we can easily grep & remove them when upgrading the compiler minimum.

On the other hand, it could be that someone has patched their compiler, e.g. backporting support for a given flag in a Linux distribution. So there is value, but I am not sure if it is just a theoretical advantage (and even then, a Linux distribution could also patch their kernel instead, too).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Of course, we still need it for rustc-param, that is what I did too -- but perhaps we can put a comment about it if we think one or the other way is better).

Copy link
Author

@maurer maurer Jul 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that in many cases rustc-min-version would be preferable, esp. because with -Z flags, the feature may be available but incomplete in some cases. However, I'd point out that users needing to look up what version of Rust added a flag they're going to use every time seems a bit more onerous than the situation in C.

I'll add a note to the docs that if you're testing for a -Z flag, you should consider rustc-min-version instead. I think rustc-option is probably better for -C options in most cases.

rustc-option = $(call __rustc-option, $(RUSTC),\
$(KBUILD_RUSTFLAGS),$(1),$(2))

# rustc-option-yn
# Usage: flag := $(call rustc-option-yn,-Cinstrument-coverage)
rustc-option-yn = $(call try-run,\
$(RUSTC) $(KBUILD_RUSTFLAGS) $(1) --crate-type=rlib /dev/null -o "$$TMP",y,n)
46 changes: 45 additions & 1 deletion scripts/Makefile.kasan
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ endif
KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)

cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1)))
rustc-param = $(call rustc-option, -Cllvm-args=-$(1),)

ifdef CONFIG_KASAN_STACK
stack_enable := 1
Expand All @@ -28,6 +29,7 @@ else
endif

CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
RUSTFLAGS_KASAN_MINIMAL := -Zsanitizer=kernel-address -Zsanitizer-recover=kernel-address

# -fasan-shadow-offset fails without -fsanitize
CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \
Expand All @@ -36,13 +38,36 @@ CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \
-mllvm -asan-mapping-offset=$(KASAN_SHADOW_OFFSET)))

ifeq ($(strip $(CFLAGS_KASAN_SHADOW)),)
KASAN_SHADOW_SUPPORTED := n
else
KASAN_SHADOW_SUPPORTED := y
endif

ifdef CONFIG_RUST
RUSTFLAGS_KASAN_SHADOW := $(call rustc-option $(RUSTFLAGS_KASAN_MINIMAL) \
-Cllvm-args=-asan-mapping-offset=$(KASAN_SHADOW_OFFSET))
ifeq ($(strip $(RUSTFLAGS_KASAN_SHADOW)),)
KASAN_SHADOW_SUPPORTED := n
endif
endif

ifeq ($(KASAN_SHADOW_SUPPORTED),y)
CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
ifdef CONFIG_RUST
RUSTFLAGS_KASAN := $(RUSTFLAGS_KASAN_MINIMAL)
endif
else
# Now add all the compiler specific options that are valid standalone
CFLAGS_KASAN := $(CFLAGS_KASAN_SHADOW) \
$(call cc-param,asan-globals=1) \
$(call cc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \
$(call cc-param,asan-instrument-allocas=1)
ifdef CONFIG_RUST
RUSTFLAGS_KASAN := $(RUSTFLAGS_KASAN_SHADOW) \
$(call rustc-param,asan-globals=1) \
$(call rustc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \
$(call rustc-param,asan-instrument-allocas=1)
endif
endif

CFLAGS_KASAN += $(call cc-param,asan-stack=$(stack_enable))
Expand All @@ -52,6 +77,11 @@ CFLAGS_KASAN += $(call cc-param,asan-stack=$(stack_enable))
# memintrinsics won't be checked by KASAN on GENERIC_ENTRY architectures.
CFLAGS_KASAN += $(call cc-param,asan-kernel-mem-intrinsic-prefix=1)

ifdef CONFIG_RUST
RUSTFLAGS_KASAN += $(call rustc-param,asan-stack=$(stack_enable))
RUSTFLAGS_KASAN += $(call rustc-param,asan-kernel-mem-intrinsic-prefix=1)
endif

endif # CONFIG_KASAN_GENERIC

ifdef CONFIG_KASAN_SW_TAGS
Expand All @@ -73,6 +103,20 @@ ifeq ($(call clang-min-version, 150000)$(call gcc-min-version, 130000),y)
CFLAGS_KASAN += $(call cc-param,hwasan-kernel-mem-intrinsic-prefix=1)
endif

ifdef CONFIG_RUST
ifdef CONFIG_KASAN_INLINE
rust_instrumentation_flags := $(call rustc-param,hwasan-mapping-offset=$(KASAN_SHADOW_OFFSET))
else
rust_instrumentation_flags := $(call rustc-param,hwasan-instrument-with-calls=1)
endif
RUSTFLAGS_KASAN := -Zsanitizer=kernel-hwaddress -Zsanitizer-recover=kernel-hwaddress \
$(call rustc-param,hwasan-instrument-stack=$(stack_enable)) \
$(call rustc-param,hwasan-use-short-granules=0) \
$(call rustc-param,hwasan-inline-all-checks=0) \
$(call rustc-param,hwasan-kernel-mem-intrinsic-prefix=1) \
$(instrumentation_flags)
endif

endif # CONFIG_KASAN_SW_TAGS

export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE
export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE RUSTFLAGS_KASAN
3 changes: 3 additions & 0 deletions scripts/Makefile.lib
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ ifneq ($(CONFIG_KASAN_HW_TAGS),y)
_c_flags += $(if $(patsubst n%,, \
$(KASAN_SANITIZE_$(target-stem).o)$(KASAN_SANITIZE)$(is-kernel-object)), \
$(CFLAGS_KASAN), $(CFLAGS_KASAN_NOSANITIZE))
_rust_flags += $(if $(patsubst n%,, \
$(KASAN_SANITIZE_$(target-stem).o)$(KASAN_SANITIZE)$(is-kernel-object)), \
$(RUSTFLAGS_KASAN))
endif
endif

Expand Down