Skip to content

Android Binder fuzzer #564

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

Merged
merged 4 commits into from
Feb 28, 2025
Merged

Android Binder fuzzer #564

merged 4 commits into from
Feb 28, 2025

Conversation

rodionov
Copy link

Hi @tavip @thehajime,

Here is a couple of commits implementing @abcSup's Binder fuzzer.

@rodionov rodionov requested review from tavip and thehajime February 17, 2025 09:29
@rodionov rodionov force-pushed the binder_fuzzer branch 4 times, most recently from 485d1cc to 154aa2b Compare February 18, 2025 04:17
Copy link
Member

@tavip tavip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM. I am not sure how to handle the libprotobuf-mutator dependency as I a worry changes there will easily break the fuzzer. Maybe adding some build tests would help?


# The same list of absl dependencies as in libprotobuf-mutator cmake config:
# https://github.com/google/libprotobuf-mutator/blob/master/cmake/external/protobuf.cmake
LDLIBS_/binder-fuzzer-$(LKL_HOST_CONFIG_MMU) += \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it could be easy to break as libprotobuf-mutator evolves. Is there a better way to do it? Or perhaps do some validation in the "autoconf" part?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for flagging this, Tavi! Yeah, I see your concerns. I'm also not quite happy with libprotobuf-mutator integration. Tried to clean up things as much as possible but there is still some opportunity for the improvement, I guess. In this implementation we rely on a specific layout of libprotobuf-mutator build directory which is fragile. Some potential options in the order preference:

  1. Use as-is but pin libprotobuf-mutator to a specific commit. We will update the documentation accordingly and will use the exact libprotobuf-mutator commit in all the automation scripts. Updates to libprotobuf-mutator will be manually tested to ensure the currently implemented build config works fine or needs some changes. This way we would avoid potential breakages to builds due to the evolved libprotobuf-mutator at a cost of not following tip of the tree of libprotobuf-mutator (which I think is not a big deal here compared to added stability). Happy to add validation to autoconf part to enforce the libprotobuf-mutator is using the right commit

  2. Ship libprotobuf-mutator prebuilts inside LKL source tree. To build the fuzzer we would need (a) libprotobuf headers, (b) libprotobuf-mutator headers, (c) libprotobuf-mutator and librpotobuf static libc, (d) protoc protobuf compiler (needs to match the exact version of libprotobuf static libs and headers). We can potentially put the prebuilt objects somewhere under tools/lkl/fuzzers/prebuilts. The needed headers can be stored somewhere in LKL source tree too. Not 100% sure what license these headers should be under (currently they are not GPLv2).

  3. Completely get rid of libprotobuf-mutator :) Would make source tree cleaner but would require major refactoring of the fuzzer and probably reduce its performance (libprotobuf-mutator enables structure-aware fuzzing what improves code coverage). Using libprotobuf-mutator brings good benefits for fuzzing and I would like to use for future LKL-based fuzzing projects if possible.

@tavip @thehajime what do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rodionov although I don't think it's clean enough with the current state, we have similar dependent library, dpdk, which we put a detection under Makefile.autoconf with a supplemental script to prepare the library. that might be another option 4) for the protobuf integration.

https://github.com/lkl/linux/blob/master/tools/lkl/Makefile.autoconf#L46-L59
https://github.com/lkl/linux/blob/master/tools/lkl/scripts/dpdk-sdk-build.sh

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to what @thehajime suggested

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pointing this out! I see, libprotobuf-mutator is quite similar -- let me change the PR according to dpdk example.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tavip, @thehajime I did some changes to address your recommendations:

  1. Added tools/lkl/scripts/libprotobuf-mutator-build.sh supplemental script which downloads and builds libprotobuf-mutator project pinning it to v1.4 version.
  2. Added additional configuration and checks to tools/lkl/Makefile.autoconf file which verifies that libprotobuf-mutator has all the necessary dependencies built and located at the expected paths.

both 1 and 2 expect PROTOBUF_MUTATOR_DIR which provides path to the directory with libprotobuf-mutator. I originally wanted to provide a default option for this variable somewhere inside LKL source tree but make clean would remove all the built static *.a libs regardless of the location of folder inside LKL source tree. Thus, it might be inconvenient to download libprotobuf-mutator inside LKL source tree and the caller needs to explicitly provide location of the libprotobuf-mutator located somewhere else via PROTOBUF_MUTATOR_DIR.

Let me know what you think. Happy to address any further comments or suggestions regarding this topic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @rodionov, it looks like the PR is missing some files and some some temporary / debug commits. I am fine with not setting a default value for PROTOBUF_MUTATOR_DIR. I think we should also update the tests to build the binder fuzzer to make sure we don't break it and maybe even run the CVE repro if possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @tavip ! I'm sorry for pushing the wrong branch, just reuploaded the right one.

I think we should also update the tests to build the binder fuzzer to make sure we don't break it and maybe even run the CVE repro if possible.

+1 for adding a test to CI -- will be adding a new commit with the test shortly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added fuzzing build tests with libprotobuf-mutator to CI in 2f75d26

@rodionov rodionov force-pushed the binder_fuzzer branch 3 times, most recently from c8fd6f7 to 3a8bc33 Compare February 21, 2025 03:56
Copy link
Member

@tavip tavip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great work, thank you @rodionov and @abcSup ! I've left a couple questions inline.

Current implementation of install_headers.py doesn't handle enums which
contain complex expressions such as macro invocations. For example, in
include/uapi/linux/android/binder.h the following enums are incorrectly
parsed due to commas inside macro _IOW('c', 0, ...) in:

```
enum binder_driver_command_protocol {
	BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
	BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
        ...
}
```

This CL implements a workaround which detect presence of macros with
brackets and ignores commas in it.

As a limitation the proposed solution isn't generic engough to handle
nested macro invocations (i.e. MACRO1(MACRO2(...))) with unlimited depth
of brackets. However it offers an improvement over existing approach.

Signed-off-by: Zi Fan Tan <[email protected]>
Signed-off-by: Eugene Rodionov <[email protected]>
@rodionov rodionov force-pushed the binder_fuzzer branch 4 times, most recently from 51c8073 to 2f75d26 Compare February 27, 2025 07:18
abcSup and others added 3 commits February 27, 2025 08:07
The instructions on how to build the fuzzer are provided in
tools/lkl/fuzzers/binder/README.md

Signed-off-by: Zi Fan Tan <[email protected]>
Signed-off-by: Eugene Rodionov <[email protected]>
Currently Makefile.conf is included in tools/lkl/Makefile using
`-include` construct which won't generate an error if Makefile.conf is
not present which might happen due to an error while executing
Makefile.autoconf.

As Makefile.conf contains important LKL configuration options `make`
should not proceed with building targets.

Do the same for inclusion of Target and ../scripts/Makefile.include
files.

Signed-off-by: Eugene Rodionov <[email protected]>
Move lkl-fuzzing test from tests group into a dedicated entry. Building
fuzzers target generates fuzzer bineries and produces no test binaries
(e.g. boot, disk, etc).

Enable MMU and libprotobuf-mutator for testing LKL fuzzers in CI.

Signed-off-by: Eugene Rodionov <[email protected]>
@tavip tavip merged commit 9da40d4 into lkl:master Feb 28, 2025
13 of 14 checks passed
@rodionov rodionov deleted the binder_fuzzer branch February 28, 2025 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants