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

ebpf-kernel/length_ebpf.p4 test fails to pass eBPF verifier #4158

Closed
thomascalvert-xlnx opened this issue Sep 14, 2023 · 6 comments
Closed
Labels
bug This behavior is unintended and should be fixed. ebpf Topics related to the eBPF back end

Comments

@thomascalvert-xlnx
Copy link
Member

With p4c 555029d03, running Ubuntu 20.04 with kernel 5.4.0-144, I see the above test fail:

0: (61) r2 = *(u32 *)(r1 +80)
1: (61) r1 = *(u32 *)(r1 +76)
2: (bc) w3 = w2
3: (1c) w3 -= w1
last_idx 3 first_idx 0
regs=8 stack=0 before 2: (bc) w3 = w2
regs=4 stack=0 before 1: (61) r1 = *(u32 *)(r1 +76)
regs=4 stack=0 before 0: (61) r2 = *(u32 *)(r1 +80)
R3 32-bit pointer arithmetic prohibited

Note that kernel tests need to be run by root, and are skipped otherwise. The simplest way to reproduce is, from your build directory:

sudo ctest --output-on-failure -R 'ebpf-kernel/testdata/p4_16_samples/length_ebpf.p4'

The actual C instruction which causes the issue is:

u32 ebpf_pkt_len = ebpf_packetEnd - ebpf_packetStart;

which I believe is used to support the packet.length() call used in the program's parser. I suspect that, since no other test program uses this method, the variable is usually optimised out. (The only other uses are for trace messages which again are generally disabled.)

@fruffy fruffy added the bug This behavior is unintended and should be fixed. label Sep 14, 2023
@fruffy
Copy link
Collaborator

fruffy commented Sep 14, 2023

I believe the eBPF back end has no dedicated maintainer. It might take some time until this bug is fixed.

@fruffy fruffy added the ebpf Topics related to the eBPF back end label Sep 14, 2023
@mihaibudiu
Copy link
Contributor

The ebpf backend contributors have been usually very responsive.

@fruffy
Copy link
Collaborator

fruffy commented Sep 14, 2023

The ebpf backend contributors have been usually very responsive.

This bug is in the classic eBPF kernel tests, not sure whether it extends to the PSA eBPF portion.

@tatry @osinstom

Is this a bug in parts of the code that you depend on?

@tatry
Copy link
Contributor

tatry commented Sep 15, 2023

I believe the problem is related to classic eBPF only (filter model). Packet length is calculated here:

builder->appendFormat("u32 %s = %s - %s", lengthVar.c_str(), packetEndVar.c_str(),
packetStartVar.c_str());

which generates aforementioned problematic code. This is not used for PSA architecture.

As a side note, PSA architecture has its own method to calculate packet length here:

void EBPFPipeline::emitPacketLength(CodeBuilder *builder) {
if (this->is<XDPIngressPipeline>() || this->is<XDPEgressPipeline>()) {
builder->appendFormat("%s->data_end - %s->data", this->contextVar.c_str(),
this->contextVar.c_str());
} else {
builder->appendFormat("%s->len", this->contextVar.c_str());
}
}

@thomascalvert-xlnx
Copy link
Member Author

It's not immediately apparent to me why the PSA target backend seems to duplicate so much logic. Probably because I'm not very familiar with the compiler.

In any case the fix is fairly straightforward by just copying the strategy which @tatry helpfully points out. With the patch in PR #4159 the test is now passing.

jafingerhut pushed a commit that referenced this issue Sep 24, 2023
* backends/ebpf: Change packet length calc to pass kernel verifier (#4158)

* backends/ebpf: Fix #4098 by renaming conflicting write_partial macro.

* backends/bmv2: Only run test using sudo if not already root.

This avoids the 'root is not in the sudoers file' error.

* gtestp4c: Don't assume that build/ is in the p4c source dir.

* backends/ebpf: Don't emit duplicate 'goto start' instruction.

The same instruction is already emitted in EBPFParser::emit().

* backends/ebpf: Don't emit deparsing writes twice.

As things stand, when using the ebpf backend (not PSA or TC), the emitDeparserExternCalls()
causes the deparsing code to be emitted before any variables are initialised.
This is obviously incorrect however wasn't noticed since the only users of the
deparser code currently override this method.

* backends/ebpf: Support XDP hook in kernel tests.

* testdata: Golden outputs for new XDP tests.

* backends/ebpf: Add support for XDP model.

* [fixup] lint python code too

* [fixup] use BUG for invalid model.arch values

Should fix macOS compilation error.
@thomascalvert-xlnx
Copy link
Member Author

Fix pushed. Copying this from the PR for reference:

After some more digging I found this patch, which seems to suggest that the kernel verifier accepts this construct as of kernel 5.9. This is consistent with the observed behaviour.

In summary: this patch only applies to kernels versions prior to 5.9. At a glance, the CI runs all seem to be running more recent kernels (Ubuntu20: 5.15.0-1046-azure; all others: 6.2.0-1011-azure)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This behavior is unintended and should be fixed. ebpf Topics related to the eBPF back end
Projects
None yet
Development

No branches or pull requests

4 participants