Skip to content

Commit 9da40d4

Browse files
authored
Merge pull request torvalds#564 from rodionov/binder_fuzzer
Android Binder fuzzer
2 parents 8807976 + 07b74e7 commit 9da40d4

File tree

14 files changed

+1936
-16
lines changed

14 files changed

+1936
-16
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,6 @@ jobs:
3737
runs_on: ubuntu-22.04
3838
shell: bash
3939
build_options: "LLVM=1 CROSS_COMPILE=x86_64-linux-gnu"
40-
- displayTargetName: lkl-fuzzers
41-
os: unix
42-
runs_on: ubuntu-22.04
43-
shell: bash
44-
build_options: "LKL_FUZZING=1 fuzzers"
4540
- displayTargetName: zpoline
4641
# maybe integrate with default Linux build once the function becomes stable
4742
os: unix
@@ -178,3 +173,27 @@ jobs:
178173
run: sudo pip install ply GitPython
179174
- name: Check coding style
180175
run: tools/lkl/scripts/checkpatch.sh
176+
177+
fuzzers:
178+
runs-on: ubuntu-22.04
179+
name: fuzzers
180+
env:
181+
PROTOBUF_MUTATOR_DIR: /tmp/libprotobuf-mutator
182+
steps:
183+
- name: Checkout
184+
with:
185+
fetch-depth: 0
186+
uses: actions/checkout@v4
187+
- name: Install clang toolchain
188+
run: |
189+
sudo apt update -y
190+
sudo apt install -y clang lld llvm
191+
- name: Install libprotobuf-mutator prerequisites
192+
run: |
193+
sudo apt update -y
194+
sudo apt install -y binutils cmake ninja-build liblzma-dev libz-dev \
195+
pkg-config autoconf libtool
196+
- name: Build libprotobuf-mutator
197+
run: tools/lkl/scripts/libprotobuf-mutator-build.sh
198+
- name: Build fuzzers
199+
run: make -j4 -C tools/lkl LKL_FUZZING=1 MMU=1 fuzzers

arch/lkl/configs/fuzzing_defconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,5 @@ CONFIG_KASAN_STACK_ENABLE=y
191191
CONFIG_KASAN_GENERIC=y
192192
CONFIG_KASAN_OUTLINE=y
193193
CONFIG_FRAME_WARN=0
194+
195+
CONFIG_DEVTMPFS=y

arch/lkl/scripts/headers_install.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ def replace(h):
132132

133133
find_headers("arch/lkl/include/uapi/asm/syscalls.h")
134134
headers.add("arch/lkl/include/uapi/asm/host_ops.h")
135+
find_headers("include/uapi/linux/android/binder.h")
135136
find_headers("include/uapi/linux/uhid.h")
136137
find_headers("include/uapi/linux/mman.h")
137138
find_headers("include/uapi/linux/input-event-codes.h")
@@ -181,7 +182,7 @@ def replace(h):
181182
p = re.compile(r"static\s+__always_inline(\s+\w+)+\s+(\w+)\([^)]*\)\s")
182183
find_symbols(p, defines)
183184
p = re.compile(r"enum\s+(\w*)\s*{([^}]*)}", re.M|re.S)
184-
q = re.compile(r"(\w+)\s*(,|=[^,]*|$)", re.M|re.S)
185+
q = re.compile(r"(\w+)\s*(,|=\s*\w+\s*\([^()]*\)|=[^,]*|$)", re.M|re.S)
185186
find_enums(p, q, defines)
186187

187188
# needed for i386

tools/lkl/Makefile

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ ifeq (,$(srctree))
2424
endif
2525
export srctree
2626

27-
-include ../scripts/Makefile.include
27+
include ../scripts/Makefile.include
2828

2929
# OUTPUT fixup should be *after* include ../scripts/Makefile.include
3030
ifneq ($(OUTPUT),)
@@ -42,13 +42,13 @@ conf: $(OUTPUT)Makefile.conf
4242
$(OUTPUT)Makefile.conf $(OUTPUT)include/kernel_config.h $(OUTPUT)/kernel.config: Makefile.autoconf
4343
$(call QUIET_AUTOCONF, headers)$(MAKE) -f Makefile.autoconf -s
4444

45-
-include $(OUTPUT)Makefile.conf
45+
include $(OUTPUT)Makefile.conf
4646

4747
export CFLAGS += -I$(OUTPUT)/include -Iinclude -Wall -g -O2 -Wextra \
4848
-Wno-unused-parameter \
4949
-Wno-missing-field-initializers -fno-strict-aliasing
5050

51-
-include Targets
51+
include Targets
5252

5353
# Expand targets to output location and suffix but preserve special
5454
# targets (e.g. .WAIT)
@@ -114,13 +114,58 @@ $(OUTPUT)%-in.o: $(OUTPUT)lib/lkl.o FORCE
114114
$(OUTPUT)cpfromfs$(EXESUF): cptofs$(EXESUF)
115115
$(Q)if ! [ -e $@ ]; then ln -s $< $@; fi
116116

117+
# START: fuzzing-related build-rules
118+
FUZZ_TARGETS := $(fuzzers-y:%=$(OUTPUT)%$(EXESUF))
119+
fuzzers: $(FUZZ_TARGETS)
120+
121+
# Enable libFuzzer fuzzing instrumentation for the LKL fuzzers
122+
$(OUTPUT)fuzzers/%$(EXESUF): LDFLAGS += -fsanitize=fuzzer --coverage
123+
124+
# Binder fuzzer is special: built with C++ toolchain and linked with libprotobuf-mutator
125+
$(OUTPUT)fuzzers/binder%$(EXESUF): $(OUTPUT)fuzzers/binder%-in.o $(OUTPUT)liblkl.a
126+
$(QUIET_LINK)$(CXX) $(LDFLAGS) $(LDFLAGS_$*-y) -o $@ $^ $(LDLIBS) $(LDLIBS_$*-y)
127+
128+
# Track all the protoc generated files for 'clean' target
129+
PROTOC_GENERATED_FILES :=
130+
131+
read_proto_deps = \
132+
$(strip $(shell grep PROTOBUF_MUTATOR_PROTO $(1) | sed 's/^.*= //g'))
133+
134+
define gen_protobuf_deps =
135+
$(eval FUZZER_SRC_DIR := $(dir $(srctree)/tools/lkl/$(1)))
136+
$(eval FUZZER_PROTO_FILES := $(call read_proto_deps,$(FUZZER_SRC_DIR)Build))
137+
$(eval FUZZER_PROTO_FILES := $(FUZZER_PROTO_FILES:.proto=.pb.cpp) \
138+
$(FUZZER_PROTO_FILES:.proto=.pb.h))
139+
$(eval FUZZER_PROTO_FILES := \
140+
$(addprefix $(FUZZER_SRC_DIR),$(FUZZER_PROTO_FILES)))
141+
PROTOC_GENERATED_FILES += $(FUZZER_PROTO_FILES)
142+
$(OUTPUT)$(1)-in.o: $(FUZZER_PROTO_FILES)
143+
endef
144+
145+
# Add generated .pb.cc and pb.h files for libprotobuf-mutator as prerequisites
146+
# for the corresponding fuzz targets to have them made using the rule below.
147+
$(foreach fuzzer,$(fuzzers-y),$(eval $(call gen_protobuf_deps,$(fuzzer))))
148+
149+
# TODO: Cannot depend on the corresponding $(srctree)/tools/lkl/%.proto file
150+
# due to the pattern rule
151+
# '$(OUTPUT)%$(EXESUF): $(OUTPUT)%-in.o $(OUTPUT)liblkl.a' above. For POSIX
152+
# target $(EXESUF) is an empty string, thus, target $(OUTPUT)%$(EXESUF) would
153+
# match any source file and will try to make it.
154+
# Update once https://github.com/lkl/linux/issues/573 is fixed.
155+
$(srctree)/tools/lkl/%.pb.cpp $(srctree)/tools/lkl/%.pb.h&: FORCE
156+
$(PROTOC_PATH) --cpp_out=$(@D) --proto_path=$(@D) $(@F:pb.cpp=proto)
157+
mv $(@:.cpp=.cc) $@
158+
159+
# END: fuzzing-related build-rules
160+
117161
clean:
118162
$(call QUIET_CLEAN, vmlinux)$(MAKE) -C ../.. ARCH=lkl $(KOPT) clean
119163
$(call QUIET_CLEAN, objects)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd'\
120164
-delete -o -name '\.*.d' -delete
121165
$(call QUIET_CLEAN, headers)$(RM) -r $(OUTPUT)/include/lkl/
122166
$(call QUIET_CLEAN, liblkl.a)$(RM) $(OUTPUT)/liblkl.a
123-
$(call QUIET_CLEAN, targets)$(RM) $(TARGETS) bin/stat
167+
$(call QUIET_CLEAN, targets)$(RM) $(TARGETS) $(FUZZ_TARGETS) bin/stat
168+
$(call QUIET_CLEAN, gen_protos)$(RM) $(PROTOC_GENERATED_FILES)
124169

125170
mrproper: clean
126171
$(call QUIET_CLEAN, vmlinux)$(MAKE) -C ../.. ARCH=lkl $(KOPT) mrproper
@@ -153,12 +198,6 @@ install: headers_install libraries_install programs_install
153198
run-tests:
154199
./tests/run.py $(tests)
155200

156-
# Enable libFuzzer fuzzing instrumentation for the LKL fuzzers
157-
$(OUTPUT)fuzzers/%$(EXESUF): LDFLAGS += -fsanitize=fuzzer --coverage
158-
159-
FUZZ_TARGETS := $(fuzzers-y:%=$(OUTPUT)%$(EXESUF))
160-
fuzzers: $(FUZZ_TARGETS)
161-
162201
FORCE: ;
163202
.PHONY: all clean clean-conf mrproper FORCE run-tests
164203
.PHONY: headers_install libraries_install programs_install install

tools/lkl/Makefile.autoconf

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,89 @@ define do_autoconf_llvm
169169
$(eval LLVM_SUFFIX := $(if $(filter -%,$(LLVM)),$(LLVM)))
170170
export CLANG_TARGET_FLAGS_lkl := $(CROSS_COMPILE)
171171
export CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
172+
export CXX := $(LLVM_PREFIX)clang++$(LLVM_SUFFIX)
172173
export LD := $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)
173174
export AR := $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)
174175
$(eval LD := $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
175176
$(eval CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX))
176177
$(eval LD_FMT := $(call llvm_target_to_ld_fmt))
177178
endef
178179

180+
define define_libprotobuf_mutator
181+
$(eval PROTOC_PATH := $(PROTOBUF_MUTATOR_DIR)/build/external.protobuf/bin/protoc)
182+
export PROTOC_PATH := $(PROTOC_PATH)
183+
184+
# Tell compiler where to find libprotobuf-mutator-related headers
185+
export LIBPROTOBUF_MUTATOR_INCLUDES_DIR := -I$(PROTOBUF_MUTATOR_DIR) \
186+
-I$(PROTOBUF_MUTATOR_DIR)/build/external.protobuf/include
187+
188+
# Tell linker where to find libprotobuf-mutator-related static libs
189+
export LIBPROTOBUF_MUTATOR_LIBS_DIR := -L$(PROTOBUF_MUTATOR_DIR)/build/src \
190+
-L$(PROTOBUF_MUTATOR_DIR)/build/src/libfuzzer \
191+
-L$(PROTOBUF_MUTATOR_DIR)/build/external.protobuf/lib
192+
193+
# The same list of absl dependencies as in libprotobuf-mutator cmake config:
194+
# https://github.com/google/libprotobuf-mutator/blob/master/cmake/external/protobuf.cmake
195+
$(eval LIBPROTOBUF_LIBS := protobufd \
196+
absl_bad_any_cast_impl absl_bad_optional_access absl_bad_variant_access \
197+
absl_base absl_city absl_civil_time absl_cord absl_cord_internal \
198+
absl_cordz_functions absl_cordz_handle absl_cordz_info \
199+
absl_cordz_sample_token absl_crc_cord_state absl_crc_cpu_detect \
200+
absl_crc_internal absl_crc32c absl_debugging_internal \
201+
absl_demangle_internal absl_die_if_null absl_examine_stack \
202+
absl_exponential_biased absl_failure_signal_handler \
203+
absl_flags_commandlineflag absl_flags_commandlineflag_internal \
204+
absl_flags_config absl_flags_internal absl_flags_marshalling \
205+
absl_flags_parse absl_flags_private_handle_accessor \
206+
absl_flags_program_name absl_flags_reflection absl_flags_usage \
207+
absl_flags_usage_internal absl_graphcycles_internal absl_hash \
208+
absl_hashtablez_sampler absl_int128 absl_kernel_timeout_internal \
209+
absl_leak_check absl_log_entry absl_log_flags absl_log_globals \
210+
absl_log_initialize absl_log_internal_check_op \
211+
absl_log_internal_conditions absl_log_internal_format \
212+
absl_log_internal_globals absl_log_internal_log_sink_set \
213+
absl_log_internal_message absl_log_internal_nullguard \
214+
absl_log_internal_proto absl_log_severity \
215+
absl_log_sink absl_low_level_hash absl_malloc_internal \
216+
absl_periodic_sampler absl_random_distributions \
217+
absl_random_internal_distribution_test_util absl_random_internal_platform \
218+
absl_random_internal_pool_urbg absl_random_internal_randen \
219+
absl_random_internal_randen_hwaes absl_random_internal_randen_hwaes_impl \
220+
absl_random_internal_randen_slow absl_random_internal_seed_material \
221+
absl_random_seed_gen_exception absl_random_seed_sequences \
222+
absl_raw_hash_set absl_raw_logging_internal absl_scoped_set_env \
223+
absl_spinlock_wait absl_stacktrace absl_status \
224+
absl_statusor absl_str_format_internal absl_strerror \
225+
absl_string_view absl_strings absl_strings_internal \
226+
absl_symbolize absl_synchronization absl_throw_delegate \
227+
absl_time absl_time_zone utf8_validity)
228+
229+
export LIBPROTOBUF_MUTATOR_LIBS := \
230+
-lprotobuf-mutator-libfuzzer -lprotobuf-mutator \
231+
$(addprefix -l,$(LIBPROTOBUF_LIBS))
232+
233+
# Libprotobuf-mutator build safety checks
234+
$(if $(wildcard $(PROTOC_PATH)),,\
235+
$(error Cannot find protoc binary at $(PROTOC_PATH). \
236+
Refer to documentation at tools/lkl/fuzzers/binder/README.md))
237+
238+
$(if $(wildcard $(PROTOBUF_MUTATOR_DIR)/build/src/libprotobuf-mutator.a),,\
239+
$(error Cannot find libprotobuf-mutator.a in \
240+
$(abspath $(PROTOBUF_MUTATOR_DIR)/build/src/). \
241+
Refer to documentation at tools/lkl/fuzzers/binder/README.md))
242+
243+
$(if $(wildcard $(PROTOBUF_MUTATOR_DIR)/build/src/libfuzzer/libprotobuf-mutator-libfuzzer.a),,\
244+
$(error Cannot find libprotobuf-mutator-libfuzzer.a in \
245+
$(abspath $(PROTOBUF_MUTATOR_DIR)/build/src/libfuzzer/). \
246+
Refer to documentation at tools/lkl/fuzzers/binder/README.md))
247+
248+
$(foreach protobuf_lib,$(LIBPROTOBUF_LIBS),\
249+
$(if $(wildcard $(PROTOBUF_MUTATOR_DIR)/build/external.protobuf/lib/lib$(protobuf_lib).a),,\
250+
$(error Cannot find lib$(protobuf_lib).a in \
251+
$(PROTOBUF_MUTATOR_DIR)/build/external.protobuf/lib/. \
252+
Refer to documentation at tools/lkl/fuzzers/binder/README.md)))
253+
endef
254+
179255
define do_autoconf_fuzzing
180256
export KCONFIG := fuzzing_defconfig
181257
export LLVM := 1
@@ -185,6 +261,9 @@ define do_autoconf_fuzzing
185261
$(eval kasan := yes)
186262
$(call set_kernel_config,LKL_FUZZING,y)
187263
$(if $(LKL_LINE_COV),$(call set_kernel_config,LKL_LINE_COV,y))
264+
$(if $(MMU),$(call set_kernel_config,ANDROID_BINDER_IPC,y))
265+
$(if $(PROTOBUF_MUTATOR_DIR),$(call define_libprotobuf_mutator))
266+
LDFLAGS += -fuse-ld=lld
188267
endef
189268

190269
define mmu_test_enable

tools/lkl/Targets

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,7 @@ endif
4242

4343
# LKL fuzzers
4444
fuzzers-y += fuzzers/hid/hid-fuzzer
45+
fuzzers-$(LKL_HOST_CONFIG_MMU) += fuzzers/binder/binder-fuzzer
4546

47+
LDFLAGS_/binder-fuzzer-$(LKL_HOST_CONFIG_MMU) += $(LIBPROTOBUF_MUTATOR_LIBS_DIR)
48+
LDLIBS_/binder-fuzzer-$(LKL_HOST_CONFIG_MMU) += $(LIBPROTOBUF_MUTATOR_LIBS)

tools/lkl/fuzzers/binder/Build

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CXXFLAGS += $(CFLAGS) $(LIBPROTOBUF_MUTATOR_INCLUDES_DIR)
2+
3+
CXXFLAGS_binder.pb.o += -DNDEBUG
4+
5+
PROTOBUF_MUTATOR_PROTO := binder.proto
6+
7+
binder-fuzzer-y += binder-fuzzer.o binder.o binder.pb.o
8+

0 commit comments

Comments
 (0)