diff mbox series

[1/2] Add libfuzzer target to fuzz/x86_instruction_emulator

Message ID 20240621191434.5046-1-tamas@tklengyel.com (mailing list archive)
State Superseded
Headers show
Series [1/2] Add libfuzzer target to fuzz/x86_instruction_emulator | expand

Commit Message

Tamas K Lengyel June 21, 2024, 7:14 p.m. UTC
This target enables integration into oss-fuzz.

Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
---
 tools/fuzz/x86_instruction_emulator/Makefile    | 10 ++++++++--
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c |  6 ++----
 2 files changed, 10 insertions(+), 6 deletions(-)

Comments

Jan Beulich June 24, 2024, 3:55 p.m. UTC | #1
On 21.06.2024 21:14, Tamas K Lengyel wrote:
> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
>  	$(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
>  
> +libfuzzer-harness: $(OBJS) cpuid.o
> +	$(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@

What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
tree anywhere.

I'm further surprised you get away here without wrappers.o.

Finally, despite its base name the lack of an extension suggest to me
this isn't actually a library. Can you help me bring both aspects together?

> @@ -67,7 +70,7 @@ distclean: clean
>  
>  .PHONY: clean
>  clean:
> -	rm -f *.a *.o $(DEPS_RM) afl-harness afl-harness-cov *.gcda *.gcno *.gcov
> +	rm -f *.a *.o $(DEPS_RM) afl-harness afl-harness-cov *.gcda *.gcno *.gcov libfuzzer-harness

I'm inclined to suggest it's time to split this line (e.g. keeping all the
wildcard patterns together and moving the rest to a new rm invocation).

> --- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
> +++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
> @@ -906,14 +906,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
>  
>      if ( size <= DATA_OFFSET )
>      {
> -        printf("Input too small\n");
> -        return 1;
> +        return -1;
>      }
>  
>      if ( size > FUZZ_CORPUS_SIZE )
>      {
> -        printf("Input too large\n");
> -        return 1;
> +        return -1;
>      }
>  
>      memcpy(&input, data_p, size);

This part of the change clearly needs explaining in the description.
It's not even clear to me in how far this is related to the purpose
of the patch here (iow it may want to be a separate change, depending
on why the change is needed).

Jan
Tamas K Lengyel June 24, 2024, 9:23 p.m. UTC | #2
On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 21.06.2024 21:14, Tamas K Lengyel wrote:
> > @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
> >  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
> >       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
> >
> > +libfuzzer-harness: $(OBJS) cpuid.o
> > +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
>
> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
> tree anywhere.

It's used by oss-fuzz, otherwise it's not doing anything.

>
> I'm further surprised you get away here without wrappers.o.

Wrappers.o was actually breaking the build for oss-fuzz at the linking
stage. It works just fine without it.

>
> Finally, despite its base name the lack of an extension suggest to me
> this isn't actually a library. Can you help me bring both aspects together?

Libfuzzer is the the name of the fuzzing engine, like afl:
https://llvm.org/docs/LibFuzzer.html

>
> > @@ -67,7 +70,7 @@ distclean: clean
> >
> >  .PHONY: clean
> >  clean:
> > -     rm -f *.a *.o $(DEPS_RM) afl-harness afl-harness-cov *.gcda *.gcno *.gcov
> > +     rm -f *.a *.o $(DEPS_RM) afl-harness afl-harness-cov *.gcda *.gcno *.gcov libfuzzer-harness
>
> I'm inclined to suggest it's time to split this line (e.g. keeping all the
> wildcard patterns together and moving the rest to a new rm invocation).

Sure.

>
> > --- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
> > +++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
> > @@ -906,14 +906,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
> >
> >      if ( size <= DATA_OFFSET )
> >      {
> > -        printf("Input too small\n");
> > -        return 1;
> > +        return -1;
> >      }
> >
> >      if ( size > FUZZ_CORPUS_SIZE )
> >      {
> > -        printf("Input too large\n");
> > -        return 1;
> > +        return -1;
> >      }
> >
> >      memcpy(&input, data_p, size);
>
> This part of the change clearly needs explaining in the description.
> It's not even clear to me in how far this is related to the purpose
> of the patch here (iow it may want to be a separate change, depending
> on why the change is needed).

The printf simply produces a ton of unnecessary output while the
fuzzer is running, slowing it down. It's also not useful at all, even
for debugging. Switching the return -1 is necessary because beside
0/-1 values are reserved by libfuzzer for "future use". No issue about
putting this info into the commit message.

Tamas
Jan Beulich June 25, 2024, 6 a.m. UTC | #3
On 24.06.2024 23:23, Tamas K Lengyel wrote:
> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
>>>
>>> +libfuzzer-harness: $(OBJS) cpuid.o
>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
>>
>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
>> tree anywhere.
> 
> It's used by oss-fuzz, otherwise it's not doing anything.
> 
>>
>> I'm further surprised you get away here without wrappers.o.
> 
> Wrappers.o was actually breaking the build for oss-fuzz at the linking
> stage. It works just fine without it.

I'm worried here, to be honest. The wrappers serve a pretty important
role, and I'm having a hard time seeing why they shouldn't be needed
here when they're needed both for the test and afl harnesses. Could
you add some more detail on the build issues you encountered?

Jan
Tamas K Lengyel June 25, 2024, 11:12 a.m. UTC | #4
On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 24.06.2024 23:23, Tamas K Lengyel wrote:
> > On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>
> >> On 21.06.2024 21:14, Tamas K Lengyel wrote:
> >>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
> >>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
> >>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
> >>>
> >>> +libfuzzer-harness: $(OBJS) cpuid.o
> >>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
> >>
> >> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
> >> tree anywhere.
> >
> > It's used by oss-fuzz, otherwise it's not doing anything.
> >
> >>
> >> I'm further surprised you get away here without wrappers.o.
> >
> > Wrappers.o was actually breaking the build for oss-fuzz at the linking
> > stage. It works just fine without it.
>
> I'm worried here, to be honest. The wrappers serve a pretty important
> role, and I'm having a hard time seeing why they shouldn't be needed
> here when they're needed both for the test and afl harnesses. Could
> you add some more detail on the build issues you encountered?

With wrappers.o included doing the build in the oss-fuzz docker
(ubuntu 20.04 base) fails with:

...
clang -O1 -fno-omit-frame-pointer -gline-tables-only
-Wno-error=enum-constexpr-conversion
-Wno-error=incompatible-function-pointer-types
-Wno-error=int-conversion -Wno-error=deprecated-declarations
-Wno-error=implicit-function-declaration -Wno-error=implicit-int
-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
-fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
-DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
-Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
-Og -fno-omit-frame-pointer
-D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
-MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
-I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
-D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
-Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
-Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
-Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
-Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
/usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
/usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
__locale_struct*, char const*, ...)':
cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
undefined reference to `__wrap_vsnprintf'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:62: libfuzzer-harness] Error 1
rm x86-emulate.c wrappers.c cpuid.c
make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
ERROR:__main__:Building fuzzers failed.
Jan Beulich June 25, 2024, 11:52 a.m. UTC | #5
On 25.06.2024 13:12, Tamas K Lengyel wrote:
> On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 24.06.2024 23:23, Tamas K Lengyel wrote:
>>> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>
>>>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
>>>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
>>>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
>>>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
>>>>>
>>>>> +libfuzzer-harness: $(OBJS) cpuid.o
>>>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
>>>>
>>>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
>>>> tree anywhere.
>>>
>>> It's used by oss-fuzz, otherwise it's not doing anything.
>>>
>>>>
>>>> I'm further surprised you get away here without wrappers.o.
>>>
>>> Wrappers.o was actually breaking the build for oss-fuzz at the linking
>>> stage. It works just fine without it.
>>
>> I'm worried here, to be honest. The wrappers serve a pretty important
>> role, and I'm having a hard time seeing why they shouldn't be needed
>> here when they're needed both for the test and afl harnesses. Could
>> you add some more detail on the build issues you encountered?
> 
> With wrappers.o included doing the build in the oss-fuzz docker
> (ubuntu 20.04 base) fails with:
> 
> ...
> clang -O1 -fno-omit-frame-pointer -gline-tables-only
> -Wno-error=enum-constexpr-conversion
> -Wno-error=incompatible-function-pointer-types
> -Wno-error=int-conversion -Wno-error=deprecated-declarations
> -Wno-error=implicit-function-declaration -Wno-error=implicit-int
> -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
> -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
> -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
> -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
> -Og -fno-omit-frame-pointer
> -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
> -MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> -I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
> -D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
> -Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
> -Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
> -Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
> -Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
> x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
> x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
> /usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
> /usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
> in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
> __locale_struct*, char const*, ...)':
> cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
> undefined reference to `__wrap_vsnprintf'
> clang: error: linker command failed with exit code 1 (use -v to see invocation)
> make: *** [Makefile:62: libfuzzer-harness] Error 1
> rm x86-emulate.c wrappers.c cpuid.c
> make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
> ERROR:__main__:Building fuzzers failed.

Hmm, yes, means we'll need an actual vsnprintf() wrapper, not just a
declaration thereof.

Jan
Tamas K Lengyel June 25, 2024, 12:40 p.m. UTC | #6
On Tue, Jun 25, 2024 at 7:52 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 25.06.2024 13:12, Tamas K Lengyel wrote:
> > On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>
> >> On 24.06.2024 23:23, Tamas K Lengyel wrote:
> >>> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>
> >>>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
> >>>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
> >>>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
> >>>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
> >>>>>
> >>>>> +libfuzzer-harness: $(OBJS) cpuid.o
> >>>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
> >>>>
> >>>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
> >>>> tree anywhere.
> >>>
> >>> It's used by oss-fuzz, otherwise it's not doing anything.
> >>>
> >>>>
> >>>> I'm further surprised you get away here without wrappers.o.
> >>>
> >>> Wrappers.o was actually breaking the build for oss-fuzz at the linking
> >>> stage. It works just fine without it.
> >>
> >> I'm worried here, to be honest. The wrappers serve a pretty important
> >> role, and I'm having a hard time seeing why they shouldn't be needed
> >> here when they're needed both for the test and afl harnesses. Could
> >> you add some more detail on the build issues you encountered?
> >
> > With wrappers.o included doing the build in the oss-fuzz docker
> > (ubuntu 20.04 base) fails with:
> >
> > ...
> > clang -O1 -fno-omit-frame-pointer -gline-tables-only
> > -Wno-error=enum-constexpr-conversion
> > -Wno-error=incompatible-function-pointer-types
> > -Wno-error=int-conversion -Wno-error=deprecated-declarations
> > -Wno-error=implicit-function-declaration -Wno-error=implicit-int
> > -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
> > -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
> > -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
> > -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
> > -Og -fno-omit-frame-pointer
> > -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
> > -MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> > -I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
> > -D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
> > -Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
> > -Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
> > -Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
> > -Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
> > x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
> > x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
> > /usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
> > /usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
> > in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
> > __locale_struct*, char const*, ...)':
> > cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
> > undefined reference to `__wrap_vsnprintf'
> > clang: error: linker command failed with exit code 1 (use -v to see invocation)
> > make: *** [Makefile:62: libfuzzer-harness] Error 1
> > rm x86-emulate.c wrappers.c cpuid.c
> > make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
> > ERROR:__main__:Building fuzzers failed.
>
> Hmm, yes, means we'll need an actual vsnprintf() wrapper, not just a
> declaration thereof.

I don't really get what this wrapper accomplishes and as I said,
fuzzing works with oss-fuzz just fine without it.

Tamas
Jan Beulich June 25, 2024, 1:15 p.m. UTC | #7
On 25.06.2024 14:40, Tamas K Lengyel wrote:
> On Tue, Jun 25, 2024 at 7:52 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 25.06.2024 13:12, Tamas K Lengyel wrote:
>>> On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>
>>>> On 24.06.2024 23:23, Tamas K Lengyel wrote:
>>>>> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>
>>>>>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
>>>>>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
>>>>>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
>>>>>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
>>>>>>>
>>>>>>> +libfuzzer-harness: $(OBJS) cpuid.o
>>>>>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
>>>>>>
>>>>>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
>>>>>> tree anywhere.
>>>>>
>>>>> It's used by oss-fuzz, otherwise it's not doing anything.
>>>>>
>>>>>>
>>>>>> I'm further surprised you get away here without wrappers.o.
>>>>>
>>>>> Wrappers.o was actually breaking the build for oss-fuzz at the linking
>>>>> stage. It works just fine without it.
>>>>
>>>> I'm worried here, to be honest. The wrappers serve a pretty important
>>>> role, and I'm having a hard time seeing why they shouldn't be needed
>>>> here when they're needed both for the test and afl harnesses. Could
>>>> you add some more detail on the build issues you encountered?
>>>
>>> With wrappers.o included doing the build in the oss-fuzz docker
>>> (ubuntu 20.04 base) fails with:
>>>
>>> ...
>>> clang -O1 -fno-omit-frame-pointer -gline-tables-only
>>> -Wno-error=enum-constexpr-conversion
>>> -Wno-error=incompatible-function-pointer-types
>>> -Wno-error=int-conversion -Wno-error=deprecated-declarations
>>> -Wno-error=implicit-function-declaration -Wno-error=implicit-int
>>> -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
>>> -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
>>> -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
>>> -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
>>> -Og -fno-omit-frame-pointer
>>> -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
>>> -MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
>>> -I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
>>> -D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
>>> -Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
>>> -Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
>>> -Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
>>> -Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
>>> x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
>>> x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
>>> /usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
>>> /usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
>>> in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
>>> __locale_struct*, char const*, ...)':
>>> cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
>>> undefined reference to `__wrap_vsnprintf'
>>> clang: error: linker command failed with exit code 1 (use -v to see invocation)
>>> make: *** [Makefile:62: libfuzzer-harness] Error 1
>>> rm x86-emulate.c wrappers.c cpuid.c
>>> make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
>>> ERROR:__main__:Building fuzzers failed.
>>
>> Hmm, yes, means we'll need an actual vsnprintf() wrapper, not just a
>> declaration thereof.
> 
> I don't really get what this wrapper accomplishes

They guard against clobbering of in-register state (SIMD registers in
particular, but going forward maybe also eGRP-s as introduced by APX)
by library functions called between emulation of individual insns (or,
especially possible for fuzzing instrumented code, I think) even from
in the middle of emulating an insn. (Something as simple as the
compiler inserting a call to memcpy() or memset() somewhere in the
translation of the emulator source code could also clobber state.)

> and as I said, fuzzing works with oss-fuzz just fine without it.

I'm inclined to take this as "it appears to work just fine". Fuzzed
input register state may be lost by doing a library call somewhere,
rendering the fuzzing results less useful. This would pretty
certainly stop being tolerable the moment you compared results of
native execution of a sequence of instructions with the emulated
counterpart.

Jan
Tamas K Lengyel June 25, 2024, 1:40 p.m. UTC | #8
On Tue, Jun 25, 2024 at 9:15 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 25.06.2024 14:40, Tamas K Lengyel wrote:
> > On Tue, Jun 25, 2024 at 7:52 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>
> >> On 25.06.2024 13:12, Tamas K Lengyel wrote:
> >>> On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>
> >>>> On 24.06.2024 23:23, Tamas K Lengyel wrote:
> >>>>> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>>>
> >>>>>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
> >>>>>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
> >>>>>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
> >>>>>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
> >>>>>>>
> >>>>>>> +libfuzzer-harness: $(OBJS) cpuid.o
> >>>>>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
> >>>>>>
> >>>>>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
> >>>>>> tree anywhere.
> >>>>>
> >>>>> It's used by oss-fuzz, otherwise it's not doing anything.
> >>>>>
> >>>>>>
> >>>>>> I'm further surprised you get away here without wrappers.o.
> >>>>>
> >>>>> Wrappers.o was actually breaking the build for oss-fuzz at the linking
> >>>>> stage. It works just fine without it.
> >>>>
> >>>> I'm worried here, to be honest. The wrappers serve a pretty important
> >>>> role, and I'm having a hard time seeing why they shouldn't be needed
> >>>> here when they're needed both for the test and afl harnesses. Could
> >>>> you add some more detail on the build issues you encountered?
> >>>
> >>> With wrappers.o included doing the build in the oss-fuzz docker
> >>> (ubuntu 20.04 base) fails with:
> >>>
> >>> ...
> >>> clang -O1 -fno-omit-frame-pointer -gline-tables-only
> >>> -Wno-error=enum-constexpr-conversion
> >>> -Wno-error=incompatible-function-pointer-types
> >>> -Wno-error=int-conversion -Wno-error=deprecated-declarations
> >>> -Wno-error=implicit-function-declaration -Wno-error=implicit-int
> >>> -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
> >>> -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
> >>> -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
> >>> -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
> >>> -Og -fno-omit-frame-pointer
> >>> -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
> >>> -MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> >>> -I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
> >>> -D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
> >>> -Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
> >>> -Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
> >>> -Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
> >>> -Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
> >>> x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
> >>> x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
> >>> /usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
> >>> /usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
> >>> in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
> >>> __locale_struct*, char const*, ...)':
> >>> cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
> >>> undefined reference to `__wrap_vsnprintf'
> >>> clang: error: linker command failed with exit code 1 (use -v to see invocation)
> >>> make: *** [Makefile:62: libfuzzer-harness] Error 1
> >>> rm x86-emulate.c wrappers.c cpuid.c
> >>> make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
> >>> ERROR:__main__:Building fuzzers failed.
> >>
> >> Hmm, yes, means we'll need an actual vsnprintf() wrapper, not just a
> >> declaration thereof.
> >
> > I don't really get what this wrapper accomplishes
>
> They guard against clobbering of in-register state (SIMD registers in
> particular, but going forward maybe also eGRP-s as introduced by APX)
> by library functions called between emulation of individual insns (or,
> especially possible for fuzzing instrumented code, I think) even from
> in the middle of emulating an insn. (Something as simple as the
> compiler inserting a call to memcpy() or memset() somewhere in the
> translation of the emulator source code could also clobber state.)
>
> > and as I said, fuzzing works with oss-fuzz just fine without it.
>
> I'm inclined to take this as "it appears to work just fine". Fuzzed
> input register state may be lost by doing a library call somewhere,
> rendering the fuzzing results less useful. This would pretty
> certainly stop being tolerable the moment you compared results of
> native execution of a sequence of instructions with the emulated
> counterpart.

Yea, that may be. Any suggested way to fix the linking issue though?
I'm not even sure why the problem only appears in the oss-fuzz build,
when I just run make normally it seems to work.

Tamas
Jan Beulich June 25, 2024, 2:56 p.m. UTC | #9
On 25.06.2024 15:40, Tamas K Lengyel wrote:
> On Tue, Jun 25, 2024 at 9:15 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 25.06.2024 14:40, Tamas K Lengyel wrote:
>>> On Tue, Jun 25, 2024 at 7:52 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>
>>>> On 25.06.2024 13:12, Tamas K Lengyel wrote:
>>>>> On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>
>>>>>> On 24.06.2024 23:23, Tamas K Lengyel wrote:
>>>>>>> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>>>
>>>>>>>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
>>>>>>>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
>>>>>>>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
>>>>>>>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
>>>>>>>>>
>>>>>>>>> +libfuzzer-harness: $(OBJS) cpuid.o
>>>>>>>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
>>>>>>>>
>>>>>>>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
>>>>>>>> tree anywhere.
>>>>>>>
>>>>>>> It's used by oss-fuzz, otherwise it's not doing anything.
>>>>>>>
>>>>>>>>
>>>>>>>> I'm further surprised you get away here without wrappers.o.
>>>>>>>
>>>>>>> Wrappers.o was actually breaking the build for oss-fuzz at the linking
>>>>>>> stage. It works just fine without it.
>>>>>>
>>>>>> I'm worried here, to be honest. The wrappers serve a pretty important
>>>>>> role, and I'm having a hard time seeing why they shouldn't be needed
>>>>>> here when they're needed both for the test and afl harnesses. Could
>>>>>> you add some more detail on the build issues you encountered?
>>>>>
>>>>> With wrappers.o included doing the build in the oss-fuzz docker
>>>>> (ubuntu 20.04 base) fails with:
>>>>>
>>>>> ...
>>>>> clang -O1 -fno-omit-frame-pointer -gline-tables-only
>>>>> -Wno-error=enum-constexpr-conversion
>>>>> -Wno-error=incompatible-function-pointer-types
>>>>> -Wno-error=int-conversion -Wno-error=deprecated-declarations
>>>>> -Wno-error=implicit-function-declaration -Wno-error=implicit-int
>>>>> -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
>>>>> -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
>>>>> -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
>>>>> -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
>>>>> -Og -fno-omit-frame-pointer
>>>>> -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
>>>>> -MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
>>>>> -I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
>>>>> -D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
>>>>> -Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
>>>>> -Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
>>>>> -Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
>>>>> -Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
>>>>> x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
>>>>> x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
>>>>> /usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
>>>>> /usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
>>>>> in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
>>>>> __locale_struct*, char const*, ...)':
>>>>> cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
>>>>> undefined reference to `__wrap_vsnprintf'
>>>>> clang: error: linker command failed with exit code 1 (use -v to see invocation)
>>>>> make: *** [Makefile:62: libfuzzer-harness] Error 1
>>>>> rm x86-emulate.c wrappers.c cpuid.c
>>>>> make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
>>>>> ERROR:__main__:Building fuzzers failed.
>>>>
>>>> Hmm, yes, means we'll need an actual vsnprintf() wrapper, not just a
>>>> declaration thereof.
>>>
>>> I don't really get what this wrapper accomplishes
>>
>> They guard against clobbering of in-register state (SIMD registers in
>> particular, but going forward maybe also eGRP-s as introduced by APX)
>> by library functions called between emulation of individual insns (or,
>> especially possible for fuzzing instrumented code, I think) even from
>> in the middle of emulating an insn. (Something as simple as the
>> compiler inserting a call to memcpy() or memset() somewhere in the
>> translation of the emulator source code could also clobber state.)
>>
>>> and as I said, fuzzing works with oss-fuzz just fine without it.
>>
>> I'm inclined to take this as "it appears to work just fine". Fuzzed
>> input register state may be lost by doing a library call somewhere,
>> rendering the fuzzing results less useful. This would pretty
>> certainly stop being tolerable the moment you compared results of
>> native execution of a sequence of instructions with the emulated
>> counterpart.
> 
> Yea, that may be. Any suggested way to fix the linking issue though?

As said before, we need to gain a real wrapper for vsnprintf(). Right
now we only have a declaration thereof, for use by the wrapper for
snprintf().

> I'm not even sure why the problem only appears in the oss-fuzz build,
> when I just run make normally it seems to work.

Sounds a little odd indeed. Yet I have no idea towards the differences
between the two.

Jan
Tamas K Lengyel June 25, 2024, 3:20 p.m. UTC | #10
On Tue, Jun 25, 2024 at 10:56 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 25.06.2024 15:40, Tamas K Lengyel wrote:
> > On Tue, Jun 25, 2024 at 9:15 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>
> >> On 25.06.2024 14:40, Tamas K Lengyel wrote:
> >>> On Tue, Jun 25, 2024 at 7:52 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>
> >>>> On 25.06.2024 13:12, Tamas K Lengyel wrote:
> >>>>> On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>>>
> >>>>>> On 24.06.2024 23:23, Tamas K Lengyel wrote:
> >>>>>>> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>>>>>
> >>>>>>>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
> >>>>>>>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
> >>>>>>>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
> >>>>>>>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
> >>>>>>>>>
> >>>>>>>>> +libfuzzer-harness: $(OBJS) cpuid.o
> >>>>>>>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
> >>>>>>>>
> >>>>>>>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
> >>>>>>>> tree anywhere.
> >>>>>>>
> >>>>>>> It's used by oss-fuzz, otherwise it's not doing anything.
> >>>>>>>
> >>>>>>>>
> >>>>>>>> I'm further surprised you get away here without wrappers.o.
> >>>>>>>
> >>>>>>> Wrappers.o was actually breaking the build for oss-fuzz at the linking
> >>>>>>> stage. It works just fine without it.
> >>>>>>
> >>>>>> I'm worried here, to be honest. The wrappers serve a pretty important
> >>>>>> role, and I'm having a hard time seeing why they shouldn't be needed
> >>>>>> here when they're needed both for the test and afl harnesses. Could
> >>>>>> you add some more detail on the build issues you encountered?
> >>>>>
> >>>>> With wrappers.o included doing the build in the oss-fuzz docker
> >>>>> (ubuntu 20.04 base) fails with:
> >>>>>
> >>>>> ...
> >>>>> clang -O1 -fno-omit-frame-pointer -gline-tables-only
> >>>>> -Wno-error=enum-constexpr-conversion
> >>>>> -Wno-error=incompatible-function-pointer-types
> >>>>> -Wno-error=int-conversion -Wno-error=deprecated-declarations
> >>>>> -Wno-error=implicit-function-declaration -Wno-error=implicit-int
> >>>>> -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
> >>>>> -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
> >>>>> -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
> >>>>> -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
> >>>>> -Og -fno-omit-frame-pointer
> >>>>> -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
> >>>>> -MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> >>>>> -I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
> >>>>> -D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
> >>>>> -Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
> >>>>> -Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
> >>>>> -Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
> >>>>> -Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
> >>>>> x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
> >>>>> x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
> >>>>> /usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
> >>>>> /usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
> >>>>> in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
> >>>>> __locale_struct*, char const*, ...)':
> >>>>> cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
> >>>>> undefined reference to `__wrap_vsnprintf'
> >>>>> clang: error: linker command failed with exit code 1 (use -v to see invocation)
> >>>>> make: *** [Makefile:62: libfuzzer-harness] Error 1
> >>>>> rm x86-emulate.c wrappers.c cpuid.c
> >>>>> make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
> >>>>> ERROR:__main__:Building fuzzers failed.
> >>>>
> >>>> Hmm, yes, means we'll need an actual vsnprintf() wrapper, not just a
> >>>> declaration thereof.
> >>>
> >>> I don't really get what this wrapper accomplishes
> >>
> >> They guard against clobbering of in-register state (SIMD registers in
> >> particular, but going forward maybe also eGRP-s as introduced by APX)
> >> by library functions called between emulation of individual insns (or,
> >> especially possible for fuzzing instrumented code, I think) even from
> >> in the middle of emulating an insn. (Something as simple as the
> >> compiler inserting a call to memcpy() or memset() somewhere in the
> >> translation of the emulator source code could also clobber state.)
> >>
> >>> and as I said, fuzzing works with oss-fuzz just fine without it.
> >>
> >> I'm inclined to take this as "it appears to work just fine". Fuzzed
> >> input register state may be lost by doing a library call somewhere,
> >> rendering the fuzzing results less useful. This would pretty
> >> certainly stop being tolerable the moment you compared results of
> >> native execution of a sequence of instructions with the emulated
> >> counterpart.
> >
> > Yea, that may be. Any suggested way to fix the linking issue though?
>
> As said before, we need to gain a real wrapper for vsnprintf(). Right
> now we only have a declaration thereof, for use by the wrapper for
> snprintf().

Where is this wrapper for snprintf? I can't find anything in
fuzz/x86_instruction_emulator. If I can see an example for one that's
implemented already I may be able to decipher what's needed here. At
the moment I don't really know what "a real wrapper" would look like.

Tamas
Jan Beulich June 25, 2024, 4:12 p.m. UTC | #11
On 25.06.2024 17:20, Tamas K Lengyel wrote:
> On Tue, Jun 25, 2024 at 10:56 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 25.06.2024 15:40, Tamas K Lengyel wrote:
>>> On Tue, Jun 25, 2024 at 9:15 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>
>>>> On 25.06.2024 14:40, Tamas K Lengyel wrote:
>>>>> On Tue, Jun 25, 2024 at 7:52 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>
>>>>>> On 25.06.2024 13:12, Tamas K Lengyel wrote:
>>>>>>> On Tue, Jun 25, 2024 at 2:00 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>>>
>>>>>>>> On 24.06.2024 23:23, Tamas K Lengyel wrote:
>>>>>>>>> On Mon, Jun 24, 2024 at 11:55 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>>>>>
>>>>>>>>>> On 21.06.2024 21:14, Tamas K Lengyel wrote:
>>>>>>>>>>> @@ -58,6 +58,9 @@ afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
>>>>>>>>>>>  afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
>>>>>>>>>>>       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
>>>>>>>>>>>
>>>>>>>>>>> +libfuzzer-harness: $(OBJS) cpuid.o
>>>>>>>>>>> +     $(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
>>>>>>>>>>
>>>>>>>>>> What is LIB_FUZZING_ENGINE? I don't think we have any use of that in the
>>>>>>>>>> tree anywhere.
>>>>>>>>>
>>>>>>>>> It's used by oss-fuzz, otherwise it's not doing anything.
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I'm further surprised you get away here without wrappers.o.
>>>>>>>>>
>>>>>>>>> Wrappers.o was actually breaking the build for oss-fuzz at the linking
>>>>>>>>> stage. It works just fine without it.
>>>>>>>>
>>>>>>>> I'm worried here, to be honest. The wrappers serve a pretty important
>>>>>>>> role, and I'm having a hard time seeing why they shouldn't be needed
>>>>>>>> here when they're needed both for the test and afl harnesses. Could
>>>>>>>> you add some more detail on the build issues you encountered?
>>>>>>>
>>>>>>> With wrappers.o included doing the build in the oss-fuzz docker
>>>>>>> (ubuntu 20.04 base) fails with:
>>>>>>>
>>>>>>> ...
>>>>>>> clang -O1 -fno-omit-frame-pointer -gline-tables-only
>>>>>>> -Wno-error=enum-constexpr-conversion
>>>>>>> -Wno-error=incompatible-function-pointer-types
>>>>>>> -Wno-error=int-conversion -Wno-error=deprecated-declarations
>>>>>>> -Wno-error=implicit-function-declaration -Wno-error=implicit-int
>>>>>>> -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address
>>>>>>> -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -m64
>>>>>>> -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes
>>>>>>> -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -g3 -Werror
>>>>>>> -Og -fno-omit-frame-pointer
>>>>>>> -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MP
>>>>>>> -MF .libfuzzer-harness.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
>>>>>>> -I/src/xen/tools/fuzz/x86_instruction_emulator/../../../tools/include
>>>>>>> -D__XEN_TOOLS__ -iquote . -fsanitize=fuzzer -fsanitize=fuzzer
>>>>>>> -Wl,--wrap=fwrite -Wl,--wrap=memcmp -Wl,--wrap=memcpy
>>>>>>> -Wl,--wrap=memset -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts
>>>>>>> -Wl,--wrap=snprintf -Wl,--wrap=strstr -Wl,--wrap=vprintf
>>>>>>> -Wl,--wrap=vsnprintf fuzz-emul.o x86-emulate.o x86_emulate/0f01.o
>>>>>>> x86_emulate/0fae.o x86_emulate/0fc7.o x86_emulate/decode.o
>>>>>>> x86_emulate/fpu.o cpuid.o wrappers.o -o libfuzzer-harness
>>>>>>> /usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
>>>>>>> /usr/local/lib/clang/18/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a(fuzzer.o):
>>>>>>> in function `std::__Fuzzer::__libcpp_snprintf_l(char*, unsigned long,
>>>>>>> __locale_struct*, char const*, ...)':
>>>>>>> cxa_noexception.cpp:(.text._ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz[_ZNSt8__Fuzzer19__libcpp_snprintf_lEPcmP15__locale_structPKcz]+0x9a):
>>>>>>> undefined reference to `__wrap_vsnprintf'
>>>>>>> clang: error: linker command failed with exit code 1 (use -v to see invocation)
>>>>>>> make: *** [Makefile:62: libfuzzer-harness] Error 1
>>>>>>> rm x86-emulate.c wrappers.c cpuid.c
>>>>>>> make: Leaving directory '/src/xen/tools/fuzz/x86_instruction_emulator'
>>>>>>> ERROR:__main__:Building fuzzers failed.
>>>>>>
>>>>>> Hmm, yes, means we'll need an actual vsnprintf() wrapper, not just a
>>>>>> declaration thereof.
>>>>>
>>>>> I don't really get what this wrapper accomplishes
>>>>
>>>> They guard against clobbering of in-register state (SIMD registers in
>>>> particular, but going forward maybe also eGRP-s as introduced by APX)
>>>> by library functions called between emulation of individual insns (or,
>>>> especially possible for fuzzing instrumented code, I think) even from
>>>> in the middle of emulating an insn. (Something as simple as the
>>>> compiler inserting a call to memcpy() or memset() somewhere in the
>>>> translation of the emulator source code could also clobber state.)
>>>>
>>>>> and as I said, fuzzing works with oss-fuzz just fine without it.
>>>>
>>>> I'm inclined to take this as "it appears to work just fine". Fuzzed
>>>> input register state may be lost by doing a library call somewhere,
>>>> rendering the fuzzing results less useful. This would pretty
>>>> certainly stop being tolerable the moment you compared results of
>>>> native execution of a sequence of instructions with the emulated
>>>> counterpart.
>>>
>>> Yea, that may be. Any suggested way to fix the linking issue though?
>>
>> As said before, we need to gain a real wrapper for vsnprintf(). Right
>> now we only have a declaration thereof, for use by the wrapper for
>> snprintf().
> 
> Where is this wrapper for snprintf? I can't find anything in
> fuzz/x86_instruction_emulator.

The fuzzing stuff reuses files from the test harness, i.e.
tools/tests/x86_emulator/wrappers.c in this case. Much like cpuid.c
is coming from elsewhere, too.

Jan
diff mbox series

Patch

diff --git a/tools/fuzz/x86_instruction_emulator/Makefile b/tools/fuzz/x86_instruction_emulator/Makefile
index 1e4c6b37f5..de5f1e7e30 100644
--- a/tools/fuzz/x86_instruction_emulator/Makefile
+++ b/tools/fuzz/x86_instruction_emulator/Makefile
@@ -3,7 +3,7 @@  include $(XEN_ROOT)/tools/Rules.mk
 
 .PHONY: x86-insn-fuzz-all
 ifeq ($(CONFIG_X86_64),y)
-x86-insn-fuzz-all: x86-insn-fuzzer.a fuzz-emul.o afl
+x86-insn-fuzz-all: x86-insn-fuzzer.a fuzz-emul.o afl libfuzzer
 else
 x86-insn-fuzz-all:
 endif
@@ -58,6 +58,9 @@  afl-harness: afl-harness.o $(OBJS) cpuid.o wrappers.o
 afl-harness-cov: afl-harness-cov.o $(patsubst %.o,%-cov.o,$(OBJS)) cpuid.o wrappers.o
 	$(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
 
+libfuzzer-harness: $(OBJS) cpuid.o
+	$(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -fsanitize=fuzzer $^ -o $@
+
 # Common targets
 .PHONY: all
 all: x86-insn-fuzz-all
@@ -67,7 +70,7 @@  distclean: clean
 
 .PHONY: clean
 clean:
-	rm -f *.a *.o $(DEPS_RM) afl-harness afl-harness-cov *.gcda *.gcno *.gcov
+	rm -f *.a *.o $(DEPS_RM) afl-harness afl-harness-cov *.gcda *.gcno *.gcov libfuzzer-harness
 	rm -rf x86_emulate x86-emulate.c x86-emulate.h wrappers.c cpuid.c
 
 .PHONY: install
@@ -81,4 +84,7 @@  afl: afl-harness
 .PHONY: afl-cov
 afl-cov: afl-harness-cov
 
+.PHONY: libfuzzer
+libfuzzer: libfuzzer-harness
+
 -include $(DEPS_INCLUDE)
diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index eeeb6931f4..2ba9ca9e0b 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -906,14 +906,12 @@  int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
 
     if ( size <= DATA_OFFSET )
     {
-        printf("Input too small\n");
-        return 1;
+        return -1;
     }
 
     if ( size > FUZZ_CORPUS_SIZE )
     {
-        printf("Input too large\n");
-        return 1;
+        return -1;
     }
 
     memcpy(&input, data_p, size);