Skip to content

Commit

Permalink
Merge pull request torvalds#515 from rodionov/lkl_hid_fuzzer
Browse files Browse the repository at this point in the history
Lkl hid fuzzer
  • Loading branch information
tavip authored Feb 27, 2023
2 parents b00f0fb + cc563a4 commit 83a905f
Show file tree
Hide file tree
Showing 22 changed files with 696 additions and 2 deletions.
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),)
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);
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

0 comments on commit 83a905f

Please sign in to comment.