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

fix(driver): fix bpf probe verifier on linux 5.14 and llvm 12.0.1 #81

Merged
merged 6 commits into from Sep 22, 2021

Conversation

FedeDP
Copy link
Contributor

@FedeDP FedeDP commented Sep 14, 2021

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com>

What type of PR is this?

/kind bug

Any specific area of the project related to this PR?

/area driver-ebpf

What this PR does / why we need it:

So far, the eBPF probe needs to be compiled with clang 7. Although newer versions of clang can successfully compile the probe, it then gets rejected by the kernel verifier. This has been an open issue for a while.

This PR applies a small set of fixes that allow our eBPF probe to be accepted by the kernel verifier even when compiled with recent versions of clang.
So far, we tested this on various versions of the linux kernel and of clang.
These are the results of our test grid, which we ran on amd64 architecture:

Kernel Ver. 5.14 5.11 5.8 5.4 4.19 4.17 4.15
clang-7 -- OK OK OK OK OK OK
clang-8 -- OK OK OK OK OK OK
clang-9 -- OK OK OK OK OK OK
clang-10 -- OK OK OK OK OK OK
clang-11 -- OK OK OK OK OK OK
clang-12 OK OK OK OK OK OK OK
clang-14 -- OK OK OK OK OK KO

Additional context

At a high level, the kernel verifier rejects the eBPF for three main reasons:

  1. Unclear exit conditions in bounded loops. In some cases where the exit condition of a unrolled loop is a little ambiguous, the verifier is not able to predict if some memory accesses can go out of bounds. An example is visible here. In this case, a check on the off variable is required because it is used to access memory inside data->buf[off & ...]. We solved the error by checking the value of off at the beginning of the loop.
  2. Unprotected memory accesses. Accessing memory with patterns like &buf[off & SCRATCH_SIZE_HALF], visible here, is often rejected if compiled with newest clang versions. This is due to an optimization applied during the compilation. If a check such as if (off > SCRATCH_SIZE_HALF) /* fail /* appears before a memory access such as &buf[off & SCRATCH_SIZE_HALF], the compiler avoids performing the & SCRATCH_SIZE_HALF operation by assuming that the value of off is already bounded because it is checked inside the if statement. However, the compiled eBPF bytecode gets then rejected by the kernel verifier because it has no way to predict the value of off when accessing the memory buffer. We fixed this by storing the result of off & SCRATCH_SIZE_HALF in an additional variable, so that the compiler is forced to perform the bitwise bounding operation.
  3. Passing long integers to eBPF helpers. Helpers such as bpf_probe_read, accept a size argument that is defined as a signed integer. However, in multiple instances (such as here) we pass unsigned long variables as size arguments. We assume the safety of this operation by checking that the value does not go beyond a certain threshold, or by bouding its value through a bitwise and operation, but this is not sufficient. The kernel verifier recognizes an attempt of converting an u64 to a s32, and predicts the possibility of the value to become negative due to the potential bit overflow. We solved this problem by defining the passed value as u16, which was quite sufficient to cover our use cases (our max value fits in 16 bits comfortably).

Which issue(s) this PR fixes:
Fixes #58

Special notes for your reviewer:

Does this PR introduce a user-facing change?:

NONE

…parse_readv_writev_bufs() on recent kernel and llvm (linux 5.14.2 and llvm 12.0.1).

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>

Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com>
@poiana
Copy link
Contributor

poiana commented Sep 14, 2021

Hi @FedeDP. Thanks for your PR.

I'm waiting for a falcosecurity member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

driver/bpf/fillers.h Outdated Show resolved Hide resolved
@ghost
Copy link

ghost commented Sep 14, 2021

Does it finally fix this issue? #58 It's been around for a while!

@FedeDP
Copy link
Contributor Author

FedeDP commented Sep 14, 2021

In my case, it fixed the issue.
I think #58 is related as it talks about bpf_sys_readv_preadv_x that internally calls bpf_parse_readv_writev_bufs, that is one of the two fixed functions in this PR.

@leogr
Copy link
Member

leogr commented Sep 15, 2021

/ok-to-test

FedeDP and others added 2 commits September 16, 2021 12:10
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>

Co-authored-by: Michele Zuccala <michele@zuccala.com>
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
@FedeDP
Copy link
Contributor Author

FedeDP commented Sep 16, 2021

Sorry, i had to force push because we missed a Signed-off in the commit suggested by @zuc and committed via github.

Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
driver/bpf/filler_helpers.h Outdated Show resolved Hide resolved
driver/bpf/filler_helpers.h Outdated Show resolved Hide resolved
Copy link
Member

@leogr leogr left a comment

Choose a reason for hiding this comment

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

Just found two unneeded whitespaces (see suggestions below), otherwise looks awesome 🤩

I reserve some time to test it before the definitive approval.

Thank you!

FedeDP and others added 2 commits September 16, 2021 17:12
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>

Co-authored-by: Leonardo Grasso <me@leonardograsso.com>

Co-authored-by: Leonardo Grasso <me@leonardograsso.com>
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
@leogr
Copy link
Member

leogr commented Sep 21, 2021

/cc @leodido
/cc @fntlnz

Copy link
Member

@leogr leogr left a comment

Choose a reason for hiding this comment

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

LGTM 🥳
Btw, many thanks for the detailed explanation, and congrats: these fixes are excellent! 👏

/approve

@poiana
Copy link
Contributor

poiana commented Sep 21, 2021

LGTM label has been added.

Git tree hash: 336f3b3282f27ca9335d1a6c6190881c358f1a16

@poiana
Copy link
Contributor

poiana commented Sep 21, 2021

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: FedeDP, leogr

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ldegio ldegio self-requested a review September 22, 2021 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Probe built with clang 10/11/12/13 does not load for 5.10/5.11/5.12 kernels
6 participants