forked from androidoffsec/baremetal_kasan
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7d91f96
Showing
29 changed files
with
2,584 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# How to contribute | ||
|
||
We'd love to accept your patches and contributions to this project. | ||
|
||
## Before you begin | ||
|
||
### Sign our Contributor License Agreement | ||
|
||
Contributions to this project must be accompanied by a | ||
[Contributor License Agreement](https://cla.developers.google.com/about) (CLA). | ||
You (or your employer) retain the copyright to your contribution; this simply | ||
gives us permission to use and redistribute your contributions as part of the | ||
project. | ||
|
||
If you or your current employer have already signed the Google CLA (even if it | ||
was for a different project), you probably don't need to do it again. | ||
|
||
Visit <https://cla.developers.google.com/> to see your current agreements or to | ||
sign a new one. | ||
|
||
### Review our community guidelines | ||
|
||
This project follows | ||
[Google's Open Source Community Guidelines](https://opensource.google/conduct/). | ||
|
||
## Contribution process | ||
|
||
### Code reviews | ||
|
||
All submissions, including submissions by project members, require review. We | ||
use GitHub pull requests for this purpose. Consult | ||
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more | ||
information on using pull requests. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Copyright 2024 Google LLC | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License | ||
# version 2 as published by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
CC := clang | ||
LD := ld.lld | ||
|
||
ARCH ?= arm | ||
SUPPORTED_ARCH := arm aarch64 riscv32 riscv64 x86 | ||
|
||
ifeq ($(findstring $(ARCH),$(SUPPORTED_ARCH)),) | ||
$(error Unsupported architecture $(ARCH), choose one from $(SUPPORTED_ARCH)) | ||
endif | ||
|
||
include Makefile.$(ARCH) | ||
|
||
CFLAGS := $(CFLAGS_ARCH) | ||
CFLAGS += -ffreestanding | ||
|
||
CFLAGS += -DTARGET_ARCH_$(ARCH) | ||
CFLAGS += -DKASAN_SHADOW_MAPPING_OFFSET=$(KASAN_SHADOW_MAPPING_OFFSET) | ||
CFLAGS += -DKASAN_SHADOW_MEMORY_START=$(KASAN_SHADOW_MEMORY_START) | ||
CFLAGS += -DKASAN_SHADOW_MEMORY_SIZE=$(KASAN_SHADOW_MEMORY_SIZE) | ||
CFLAGS += -DTARGET_DRAM_START=$(TARGET_DRAM_START) | ||
CFLAGS += -DTARGET_DRAM_END=$(TARGET_DRAM_END) | ||
|
||
CFLAGS += -DPRINTF_DISABLE_SUPPORT_FLOAT | ||
CFLAGS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL | ||
CFLAGS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T | ||
CFLAGS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG | ||
|
||
CFLAGS += -Wno-incompatible-library-redeclaration | ||
|
||
CFLAGS += -Ithird_party/printf -I./ | ||
|
||
LDFLAGS := -nostdlib | ||
|
||
# KASan-specific compiler options | ||
KASAN_SANITIZE_STACK := 1 | ||
KASAN_SANITIZE_GLOBALS := 1 | ||
|
||
KASAN_CC_FLAGS := -fsanitize=kernel-address | ||
KASAN_CC_FLAGS += -fno-builtin | ||
KASAN_CC_FLAGS += -mllvm -asan-mapping-offset=$(KASAN_SHADOW_MAPPING_OFFSET) | ||
KASAN_CC_FLAGS += -mllvm -asan-instrumentation-with-call-threshold=0 | ||
KASAN_CC_FLAGS += -mllvm -asan-stack=$(KASAN_SANITIZE_STACK) | ||
KASAN_CC_FLAGS += -mllvm -asan-globals=$(KASAN_SANITIZE_GLOBALS) | ||
KASAN_CC_FLAGS += -DKASAN_ENABLED | ||
|
||
SRCS := kasan.c \ | ||
heap.c \ | ||
kasan_test.c \ | ||
sanitized_lib.c \ | ||
rt_utils.c \ | ||
start_$(ARCH).S \ | ||
third_party/printf/printf.c | ||
|
||
OBJS := $(SRCS:.c=.o) | ||
OBJS := $(OBJS:.S=.o) | ||
|
||
LD_SCRIPT := kasan_test.ld | ||
LD_SCRIPT_GEN := kasan_test.lds | ||
|
||
# Use KASAN_CC_FLAGS for the code we would like to cover with KASan | ||
sanitized_lib.o: CFLAGS := $(CFLAGS) $(KASAN_CC_FLAGS) | ||
|
||
# This workaround is not needed if you build the project with the LLVM | ||
# toolchain of version 18 and higher (i.e. which includes | ||
# https://github.com/llvm/llvm-project/pull/72933) | ||
sanitized_lib.o: CFLAGS := $(subst $(ARCH_TARGET),$(KASAN_TARGET),$(CFLAGS)) | ||
|
||
%.o: %.c | ||
$(CC) $(CFLAGS) -c $< -o $@ | ||
|
||
%.o: %.S | ||
$(CC) $(CFLAGS) -c $< -o $@ | ||
|
||
$(LD_SCRIPT_GEN): $(LD_SCRIPT) | ||
$(CC) -E -P -x c $(CFLAGS) $< >> $@ | ||
|
||
kasan_test: $(LD_SCRIPT_GEN) $(OBJS) | ||
$(LD) -T $(LD_SCRIPT_GEN) $(LDFLAGS) $(OBJS) -o $@ | ||
|
||
.PHONY: run | ||
run: kasan_test | ||
$(QEMU) $< | ||
|
||
.PHONY: clean | ||
clean: | ||
rm -rf kasan_test $(OBJS) $(LD_SCRIPT_GEN) | ||
rm -rf $(foreach arch,$(SUPPORTED_ARCH),start_$(arch).o) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
TARGET_DRAM_START := 0x40000000 | ||
TARGET_DRAM_END := 0x4fffffff | ||
UART_BASE_ADDRESS := 0x09000000 | ||
|
||
KASAN_SHADOW_MAPPING_OFFSET := 0x42700000 | ||
KASAN_SHADOW_MEMORY_START := 0x4A700000 | ||
KASAN_SHADOW_MEMORY_SIZE := 0x2000000 | ||
|
||
ARCH_TARGET := aarch64-arm-none-eabi | ||
KASAN_TARGET := aarch64-arm-linux-gnu | ||
|
||
CFLAGS_ARCH := --target=$(ARCH_TARGET) -mcpu=cortex-a53+nofp+nosimd | ||
CFLAGS_ARCH += -DUART_BASE_ADDRESS=$(UART_BASE_ADDRESS) | ||
|
||
QEMU := qemu-system-aarch64 -M virt -cpu cortex-a53 -m 256M -nographic -kernel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
TARGET_DRAM_START := 0x40000000 | ||
TARGET_DRAM_END := 0x4fffffff | ||
UART_BASE_ADDRESS := 0x09000000 | ||
|
||
KASAN_SHADOW_MAPPING_OFFSET := 0x42700000 | ||
KASAN_SHADOW_MEMORY_START := 0x4A700000 | ||
KASAN_SHADOW_MEMORY_SIZE := 0x2000000 | ||
|
||
ARCH_TARGET := arm-arm-none-eabi | ||
KASAN_TARGET := arm-arm-linux-gnu | ||
|
||
CFLAGS_ARCH := --target=$(ARCH_TARGET) -mfloat-abi=soft -mcpu=cortex-a7 | ||
CFLAGS_ARCH += -DUART_BASE_ADDRESS=$(UART_BASE_ADDRESS) | ||
|
||
QEMU := qemu-system-arm -M virt -cpu cortex-a7 -m 256M -nographic -kernel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
TARGET_DRAM_START := 0x80000000 | ||
TARGET_DRAM_END := 0x8fffffff | ||
UART_BASE_ADDRESS := 0x10000000 | ||
|
||
KASAN_SHADOW_MAPPING_OFFSET := 0x77000000 | ||
KASAN_SHADOW_MEMORY_START := 0x87000000 | ||
KASAN_SHADOW_MEMORY_SIZE := 0x2000000 | ||
|
||
ARCH_TARGET := riscv32-none-none | ||
KASAN_TARGET := riscv32-linux-gnu | ||
|
||
CFLAGS_ARCH := --target=$(ARCH_TARGET) -march=rv32imafd | ||
CFLAGS_ARCH += -DUART_BASE_ADDRESS=$(UART_BASE_ADDRESS) | ||
QEMU := qemu-system-riscv32 -M virt -bios none -m 256M -nographic -kernel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
TARGET_DRAM_START := 0x80000000 | ||
TARGET_DRAM_END := 0x8fffffff | ||
UART_BASE_ADDRESS := 0x10000000 | ||
|
||
KASAN_SHADOW_MAPPING_OFFSET := 0x77000000 | ||
KASAN_SHADOW_MEMORY_START := 0x87000000 | ||
KASAN_SHADOW_MEMORY_SIZE := 0x2000000 | ||
|
||
ARCH_TARGET := riscv64-none-none | ||
KASAN_TARGET := riscv64-linux-gnu | ||
|
||
CFLAGS_ARCH := --target=$(ARCH_TARGET) -march=rv64imafd -fPIC | ||
CFLAGS_ARCH += -DUART_BASE_ADDRESS=$(UART_BASE_ADDRESS) | ||
QEMU := qemu-system-riscv64 -M virt -bios none -m 256M -nographic -kernel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
TARGET_DRAM_START := 0x00100000 | ||
TARGET_DRAM_END := 0x07ffffff | ||
|
||
KASAN_SHADOW_MAPPING_OFFSET := 0x06FE0000 | ||
KASAN_SHADOW_MEMORY_START := 0x07000000 | ||
KASAN_SHADOW_MEMORY_SIZE := 0x1000000 | ||
|
||
ARCH_TARGET := i386-none-none | ||
KASAN_TARGET := i386-linux-gnu | ||
|
||
CFLAGS_ARCH := --target=$(ARCH_TARGET) | ||
QEMU := qemu-system-i386 -nographic -m 128M -kernel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# Bare-metal KASan implementation | ||
|
||
*This is not an officially supported Google product.* | ||
|
||
This project demonstrates how to enable Kernel Address Sanitizer (KASan) for | ||
bare-metal code running on ARM, RISC-V and x86 architectures. It implements a | ||
set of KASan test cases that catch various classes of memory corruption bugs | ||
at runtime. | ||
|
||
The implementation of KASan run-time routines in this project is inspired by | ||
the corresponding implementation of | ||
[KASan](https://www.kernel.org/doc/html/v4.14/dev-tools/kasan.html) in Linux | ||
kernel. | ||
|
||
## Prerequisites | ||
|
||
To build and run the program you would need to use LLVM toolchain (`clang` and | ||
`ld.lld`) for cross complitation and QEMU system emulator for supported | ||
architectures. | ||
|
||
For example, here are the necessary Debian package names needed to build and | ||
run the project: | ||
|
||
``` | ||
sudo apt-get install build-essential gcc-multilib llvm clang lld \ | ||
qemu-system-arm qemu-system-misc qemu-system-x86 | ||
``` | ||
|
||
## Project layout | ||
|
||
The project constists of the following components: | ||
|
||
* `kasan_test.c` -- main test driver which runs KASan test cases | ||
* `sanitized_lib.c` -- this module implements the test cases and is built with | ||
the KASan instrumentation | ||
* `kasan.c` -- implementation of runtime routines needed for KASan sanitizer | ||
* `heap.c` -- simple implementation of heap management routines for testing | ||
KASan | ||
* `third_party/printf.c` -- a compact implementation of `printf` function | ||
* `rt_utils.c` -- run-time utility functions | ||
* `start_arch.S` -- architecture-specific low-level entry point in assembly | ||
for the bare-metal program | ||
* `kasan_test.ld` -- linker script for the program | ||
* `Makefile` -- in addition to instructions on how to build and run the project | ||
this file contains definitions of some important parameters, | ||
such as KASan shadow memory address, DRAM start address and KASan | ||
configuration options. | ||
* `Makefile.arch` -- Makefile fragments whith architecture-specific parameters | ||
for building and running the project in the emulator | ||
|
||
|
||
## Running | ||
|
||
To build and execute the test suite run `ARCH=target_arch make clean run` | ||
where `target_arch` is one of the supported architectures: `arm`, `aarch64`, | ||
`riscv32`, `riscv64` and `x86`. If the target architecture isn't specified | ||
(i.e. `make clean run`) then `arm` is assumed as default option. | ||
|
||
As an example, running `make clean run` should build the bare-metal program | ||
and execute it in QEMU ARM system emulator with the following expected output: | ||
|
||
``` | ||
qemu-system-arm -M virt-8.2 -cpu cortex-a7 -m 256M -nographic -kernel kasan_test | ||
Starting bare-metal KASan test driver. | ||
KASan test: heap OOB write | ||
Writing 1 byte at offset 18 in 17-byte heap buffer allocated at 40004020 | ||
[KASan] =================================================== | ||
[KASan] ERROR: Invalid memory access: address 0x40004032, size 0x1, is_write 1, ip 0x40000D98 | ||
[KASan] Shadow bytes around the buggy address 0x40004030 (shadow 0x4A700806): | ||
[KASan] 0x4A7007D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7007E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7007F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] =>0x4A700800: FA FA FA FA 00 00[01]FB FB FB FB 00 00 00 00 00 | ||
[KASan] 0x4A700810: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A700820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A700830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
KASan test: stack OOB read | ||
Reading 1 byte at offset 18 in 17-byte stack buffer at 40014f90 | ||
[KASan] =================================================== | ||
[KASan] ERROR: Invalid memory access: address 0x40014FA2, size 0x1, is_write 0, ip 0x40000E6C | ||
[KASan] Shadow bytes around the buggy address 0x40014FA0 (shadow 0x4A7029F4): | ||
[KASan] 0x4A7029C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7029D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7029E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] =>0x4A7029F0: F1 F1 00 00[01]F3 F3 F3 F3 F3 00 00 00 00 00 00 | ||
[KASan] 0x4A702A00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A702A10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A702A20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
KASan test: global OOB write | ||
Writing an integer at index 18 in 17-element global integer array at 400035a0 | ||
[KASan] =================================================== | ||
[KASan] ERROR: Invalid memory access: address 0x400035E8, size 0x4, is_write 1, ip 0x40000F38 | ||
[KASan] Shadow bytes around the buggy address 0x400035E8 (shadow 0x4A7006BD): | ||
[KASan] 0x4A700680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A700690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] =>0x4A7006B0: 01 F9 F9 F9 00 00 00 00 00 00 00 00 04[F9]F9 F9 | ||
[KASan] 0x4A7006C0: F9 F9 F9 F9 00 00 01 F9 F9 F9 F9 F9 00 00 00 00 | ||
[KASan] 0x4A7006D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
KASan test: memset OOB write in globals | ||
Memsetting global 17-byte buffer at 40003620 with 18 values of 0xaa | ||
[KASan] =================================================== | ||
[KASan] ERROR: Invalid memory access: address 0x40003620, size 0x12, is_write 1, ip 0x40000D1C | ||
[KASan] Shadow bytes around the buggy address 0x40003630 (shadow 0x4A7006C6): | ||
[KASan] 0x4A700690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006B0: 01 F9 F9 F9 00 00 00 00 00 00 00 00 04 F9 F9 F9 | ||
[KASan] =>0x4A7006C0: F9 F9 F9 F9 00 00[01]F9 F9 F9 F9 F9 00 00 00 00 | ||
[KASan] 0x4A7006D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
KASan test: memcpy OOB read from globals | ||
Memcopying 18 bytes from 17-byte global buffer into local array | ||
[KASan] =================================================== | ||
[KASan] ERROR: Invalid memory access: address 0x40003620, size 0x12, is_write 0, ip 0x40000D20 | ||
[KASan] Shadow bytes around the buggy address 0x40003630 (shadow 0x4A7006C6): | ||
[KASan] 0x4A700690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006B0: 01 F9 F9 F9 00 00 00 00 00 00 00 00 04 F9 F9 F9 | ||
[KASan] =>0x4A7006C0: F9 F9 F9 F9 00 00[01]F9 F9 F9 F9 F9 00 00 00 00 | ||
[KASan] 0x4A7006D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
[KASan] 0x4A7006F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
Press ctrl + a then x to exit. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright 2024 Google LLC | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* version 2 as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#ifndef __KASAN_COMMON_H__ | ||
#define __KASAN_COMMON_H__ | ||
|
||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
|
||
#define CALLER_PC ((unsigned long)__builtin_return_address(0)) | ||
|
||
#ifdef KASAN_ENABLED | ||
|
||
void *__kasan_memcpy(void *dst, const void *src, unsigned int size, | ||
uintptr_t pc); | ||
void *__kasan_memset(void *buf, int c, unsigned int size, uintptr_t pc); | ||
|
||
#define memcpy(dst, src, size) __kasan_memcpy(dst, src, size, CALLER_PC) | ||
#define memset(buf, c, size) __kasan_memset(buf, c, size, CALLER_PC) | ||
|
||
#else // KASAN_ENABLED | ||
|
||
void *memcpy(void *dst, const void *src, unsigned long size); | ||
void *memset(void *buf, int c, unsigned long size); | ||
|
||
#endif // KASAN_ENABLED | ||
|
||
#endif // __KASAN_COMMON_H__ |
Oops, something went wrong.