Skip to content
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

Lkl hid fuzzer #515

Merged
merged 6 commits into from
Feb 27, 2023
Merged
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 .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ jobs:
runs_on: ubuntu-22.04
shell: bash
build_options: "LLVM=1 CROSS_COMPILE=x86_64-linux-gnu"
- displayTargetName: lkl-fuzzers
os: unix
runs_on: ubuntu-22.04
shell: bash
build_options: "LKL_FUZZING=1 fuzzers"
timeout-minutes: 100
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
Expand Down
20 changes: 20 additions & 0 deletions arch/lkl/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ config LKL
select GENERIC_STRNLEN_USER
select HAVE_ARCH_KASAN

config LKL_FUZZING
bool "LLVM fuzzing instrumentation"
default n
help
This configuration option enables fuzzing instrumentation
for the Linux kernel source files to enable coverage-guided
fuzzing. At the moment LKL supports libFuzzer fuzzing
engine only.

config LKL_LINE_COV
bool "Code coverage instrumentation for fuzzers"
depends on LKL_FUZZING && CC_IS_CLANG
default n
help
This configuration option enables line code coverage
instrumentation for the Linux kernel to generate fuzzing
code coverage reports. When this option is enabled the
kernel source files are built with LLVM SanitizerCoverage
instrumentation.

config OUTPUT_FORMAT
string "Output format"
default ""
Expand Down
24 changes: 23 additions & 1 deletion arch/lkl/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ else # e.g., FreeBSD
NPROC=$(shell sysctl -n hw.ncpu)
endif

ifdef CONFIG_CC_IS_CLANG
# LKL fuzzing is based on libFuzzer which depends on clang compiler.
ifdef CONFIG_LKL_FUZZING
# This makes sure assembly code is compiled with clang's integerated assembler
# so the result object files are compatible with the fuzzing flag.
KBUILD_CFLAGS += -integrated-as

# We want debug symbols for fuzzing (e.g. better stack trace in gdb).
KBUILD_CFLAGS += -g

# Enabling libfuzzer instrumentation
KBUILD_CFLAGS += -fsanitize=fuzzer-no-link

KEEP_EH_FRAMES := true
endif

# This flag enables clang's extra instrumentation for visualizing line coverage.
ifdef CONFIG_LKL_LINE_COV
KBUILD_CFLAGS += -fprofile-instr-generate -fcoverage-mapping
endif
endif

LDFLAGS_vmlinux += -r
LKL_ENTRY_POINTS := lkl_start_kernel lkl_sys_halt lkl_syscall lkl_trigger_irq \
lkl_get_free_irq lkl_put_irq lkl_is_running lkl_bug lkl_printf \
Expand All @@ -45,7 +67,7 @@ core-y += arch/lkl/drivers/
all: lkl.o arch/lkl/include/generated/uapi/asm/syscall_defs.h

lkl.o: vmlinux
$(OBJCOPY) -R .eh_frame -R .syscall_defs $(foreach sym,$(LKL_ENTRY_POINTS),-G$(prefix)$(sym)) --prefix-symbols=$(prefix) vmlinux lkl.o
$(OBJCOPY) $(if $(KEEP_EH_FRAMES),,-R .eh_frame) -R .syscall_defs $(foreach sym,$(LKL_ENTRY_POINTS),-G$(prefix)$(sym)) --prefix-symbols=$(prefix) vmlinux lkl.o

arch/lkl/include/generated/uapi/asm/syscall_defs.h: vmlinux
$(OBJCOPY) -j .syscall_defs -O binary --set-section-flags .syscall_defs=alloc $< $@
Expand Down
53 changes: 53 additions & 0 deletions arch/lkl/Makefile.postlink
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# The post-link vmlinux pass is only relevant when LKL is being built with
# libFuzzer instrumentation (-fsanitize=fuzzer). SanitizerCoverage
# emits GRP_COMDAT sections in the generated object files to group sections
# with instrumented code, coverage counters and relocations respectively.
# The linker semantics for incremental linking with section groups is unclear
# and results in the link-time errors. This extra post-link pass implements a
# workaround for this problem:
#
# 1) Vmlinux is incrementally linked with an empty linker script. Thus, the input
# sections aren't merged in the generated vmlinux image (ld and lld do still
# merge some common sections such as .text. .rela.text, .data and etc but it
# doesn't casue a problem).
#
# 2) Remove GRP_COMDAT group sections with name .group from the original vmlinux.
#
# 3) Relink the stripped vmlinux using the original LKL linker script.
# As there is no group sections in the input object, merging sections doesn't
# cause any issues.
#
# TODO: The above steps aren't solution to the problem but rather a short-term
# workaround. At the moment removing .group sections from the incrementally
# linked vmlinux doesn't seem to cause any issues as the only GRP_COMDAT sections
# present in the object files are the ones emited by SanitizerCoverage
# instrumentation. However, here is a couple of other things to take into
# consideration:
#
# * --gc-sections linker option could remove __sancov_pcs sections, thus, this
# option shouldn't be used when building fuzzers.
#
# * If the linker removes a function there might be 'dangling' __sancov_xxx
# sections. However, this isn't an issue for fuzzing.
#
# * __sancov_pcs and __sancov_cntrs sections need to be merged in the corresponding
# order (so that the value of the counters match to values of PC of their
# corresponding basic blocks). With this workaround this seem to be the case
# (while the linker might not guarantee this). However, even if these sections
# aren't merged in the order, technically, this won't be a problem for fuzzing.
ifneq ($(LKL_FUZZING),)
tavip marked this conversation as resolved.
Show resolved Hide resolved
include scripts/Kbuild.include

LKL_FUZZING_LDS := arch/lkl/kernel/vmlinux-fuzzing-postlink.lds

.PHONY: vmlinux
vmlinux: $(LKL_FUZZING_LDS)
$(OBJCOPY) --remove-section=.group $@ [email protected]_groups
$(LD) -r --build-id=sha1 -o $@ -T $< [email protected]_groups

clean: ; rm -rf $(LKL_FUZZING_LDS) vmlinux.no_groups
else # LKL_FUZZING
clean: ;
endif # LKL_FUZZING

.PHONY: clean
193 changes: 193 additions & 0 deletions arch/lkl/configs/fuzzing_defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_NO_HZ_IDLE=y
# CONFIG_SYSFS_SYSCALL is not set
CONFIG_KALLSYMS_USE_DATA_SECTION=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_BASE_FULL is not set
# CONFIG_FUTEX is not set
# CONFIG_SIGNALFD is not set
# CONFIG_TIMERFD is not set
# CONFIG_AIO is not set
# CONFIG_ADVISE_SYSCALLS is not set
CONFIG_EMBEDDED=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_COMPAT_BRK is not set
# CONFIG_BLK_DEV_BSG is not set
CONFIG_NET=y
CONFIG_INET=y
# CONFIG_WIRELESS is not set
# CONFIG_UEVENT_HELPER is not set
# CONFIG_FW_LOADER is not set
CONFIG_VIRTIO_BLK=y
CONFIG_NETDEVICES=y
CONFIG_VIRTIO_NET=y
CONFIG_VHOST_VSOCK=y
CONFIG_VIRTIO_VSOCKETS=y
CONFIG_VSOCKETS=y
# CONFIG_ETHERNET is not set
# CONFIG_WLAN is not set
# CONFIG_VT is not set
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
# CONFIG_FILE_LOCKING is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
CONFIG_VFAT_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_737=y
CONFIG_NLS_CODEPAGE_775=y
CONFIG_NLS_CODEPAGE_850=y
CONFIG_NLS_CODEPAGE_852=y
CONFIG_NLS_CODEPAGE_855=y
CONFIG_NLS_CODEPAGE_857=y
CONFIG_NLS_CODEPAGE_860=y
CONFIG_NLS_CODEPAGE_861=y
CONFIG_NLS_CODEPAGE_862=y
CONFIG_NLS_CODEPAGE_863=y
CONFIG_NLS_CODEPAGE_864=y
CONFIG_NLS_CODEPAGE_865=y
CONFIG_NLS_CODEPAGE_866=y
CONFIG_NLS_CODEPAGE_869=y
CONFIG_NLS_CODEPAGE_936=y
CONFIG_NLS_CODEPAGE_950=y
CONFIG_NLS_CODEPAGE_932=y
CONFIG_NLS_CODEPAGE_949=y
CONFIG_NLS_CODEPAGE_874=y
CONFIG_NLS_ISO8859_8=y
CONFIG_NLS_CODEPAGE_1250=y
CONFIG_NLS_CODEPAGE_1251=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_2=y
CONFIG_NLS_ISO8859_3=y
CONFIG_NLS_ISO8859_4=y
CONFIG_NLS_ISO8859_5=y
CONFIG_NLS_ISO8859_6=y
CONFIG_NLS_ISO8859_7=y
CONFIG_NLS_ISO8859_9=y
CONFIG_NLS_ISO8859_13=y
CONFIG_NLS_ISO8859_14=y
CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_KOI8_R=y
CONFIG_NLS_KOI8_U=y
CONFIG_NLS_MAC_ROMAN=y
CONFIG_NLS_MAC_CELTIC=y
CONFIG_NLS_MAC_CENTEURO=y
CONFIG_NLS_MAC_CROATIAN=y
CONFIG_NLS_MAC_CYRILLIC=y
CONFIG_NLS_MAC_GAELIC=y
CONFIG_NLS_MAC_GREEK=y
CONFIG_NLS_MAC_ICELAND=y
CONFIG_NLS_MAC_INUIT=y
CONFIG_NLS_MAC_ROMANIAN=y
CONFIG_NLS_MAC_TURKISH=y
CONFIG_NLS_UTF8=y
CONFIG_HZ_100=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_REDUCED=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set

#
# HID support
#
CONFIG_HID=y
CONFIG_HID_BATTERY_STRENGTH=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_GENERIC=y
#
# Special HID drivers
#
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_ASUS=y
CONFIG_HID_AUREAL=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_COUGAR=y
CONFIG_HID_MACALLY=y
CONFIG_HID_CMEDIA=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GEMBIRD=y
CONFIG_HID_GFRM=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_WALTOP=y
CONFIG_HID_VIEWSONIC=y
CONFIG_HID_GYRATION=y
CONFIG_HID_ICADE=y
CONFIG_HID_ITE=y
CONFIG_HID_JABRA=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LED=y
CONFIG_HID_LENOVO=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_HIDPP=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_LOGIWHEELS_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MALTRON=y
CONFIG_HID_MAYFLASH=y
CONFIG_HID_REDRAGON=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTI=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PICOLCD_BACKLIGHT=y
CONFIG_HID_PICOLCD_LCD=y
CONFIG_HID_PICOLCD_LEDS=y
CONFIG_HID_PLANTRONICS=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_STEAM=y
CONFIG_HID_STEELSERIES=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_RMI=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THINGM=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_THRUSTMASTER_FF=y
CONFIG_HID_UDRAW_PS3=y
CONFIG_HID_WIIMOTE=y
CONFIG_HID_XINMO=y
CONFIG_HID_ZEROPLUS=y
CONFIG_ZEROPLUS_FF=y
CONFIG_HID_ZYDACRON=y
CONFIG_HID_SENSOR_HUB=y
CONFIG_HID_SENSOR_CUSTOM_SENSOR=y
CONFIG_HID_ALPS=y
# end of Special HID drivers
# end of HID support

CONFIG_KASAN=y
CONFIG_KASAN_STACK_ENABLE=y
CONFIG_KASAN_GENERIC=y
CONFIG_KASAN_OUTLINE=y
CONFIG_FRAME_WARN=0
1 change: 1 addition & 0 deletions arch/lkl/kernel/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
extra-y := vmlinux.lds
extra-y += vmlinux-fuzzing-postlink.lds

KASAN_SANITIZE_init.o := n
KASAN_SANITIZE_stacktrace.o := n
Expand Down
6 changes: 5 additions & 1 deletion arch/lkl/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,11 @@ static int __init fs_setup(void)
{
int fd;

fd = sys_open("/init", O_CREAT, 0700);
// Pad '/init' to make sure it's 8 bytes, otherwise KASan would
// emit an error. The kernel's strncpy implementation attempts to read
// 8 bytes at once and, thus, triggers KASan violation for the 6-byte
// string.
fd = sys_open("/init\0\0", O_CREAT, 0700);
tavip marked this conversation as resolved.
Show resolved Hide resolved
WARN_ON(fd < 0);
sys_close(fd);

Expand Down
3 changes: 3 additions & 0 deletions arch/lkl/kernel/vmlinux-fuzzing-postlink.lds.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0 */
#define LKL_FUZZING_POSTLINK
#include "vmlinux.lds.S"
10 changes: 10 additions & 0 deletions arch/lkl/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
// When building LKL with libFuzzer instrumentation (-fsanitize=fuzzer) provide
// an empty linker script to avoid section merging. For additional information
// refer to arch/lkl/Makefile.postlink.
#if !defined(CONFIG_LKL_FUZZING) || defined(LKL_FUZZING_POSTLINK)
#include <asm/vmlinux.lds.h>
#include <asm/thread_info.h>
#include <asm/page.h>
Expand Down Expand Up @@ -67,5 +72,10 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG

// Don't include DISCARDS section to build the target with code coverage.
#if !defined(CONFIG_LKL_FUZZING)
DISCARDS
#endif // !defined(CONFIG_LKL_FUZZING)
}

#endif // !defined(CONFIG_LKL_FUZZING) || defined(LKL_FUZZING_POSTLINK)
2 changes: 2 additions & 0 deletions arch/lkl/scripts/headers_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ def replace(h):

find_headers("arch/lkl/include/uapi/asm/syscalls.h")
headers.add("arch/lkl/include/uapi/asm/host_ops.h")
find_headers("include/uapi/linux/uhid.h")
find_headers("include/uapi/linux/input-event-codes.h")

if 'LKL_INSTALL_ADDITIONAL_HEADERS' in os.environ:
with open(os.environ['LKL_INSTALL_ADDITIONAL_HEADERS'], 'rU') as f:
Expand Down
6 changes: 6 additions & 0 deletions tools/lkl/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ install: headers_install libraries_install programs_install
run-tests:
./tests/run.py $(tests)

# Enable libFuzzer fuzzing instrumentation for the LKL fuzzers
$(OUTPUT)fuzzers/%$(EXESUF): LDFLAGS += -fsanitize=fuzzer --coverage

FUZZ_TARGETS := $(fuzzers-y:%=$(OUTPUT)%$(EXESUF))
fuzzers: $(FUZZ_TARGETS)

FORCE: ;
.PHONY: all clean FORCE run-tests
.PHONY: headers_install libraries_install programs_install install
Expand Down
Loading