Validate LDDW second-half instruction fields#764
Validate LDDW second-half instruction fields#764ppx123-web wants to merge 2 commits intoiovisor:mainfrom
Conversation
Signed-off-by: GOD_PPX <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR tightens uBPF’s instruction validation to fully enforce the RFC 9669 requirements for the second half of an LDDW (64-bit immediate load), preventing malformed programs from loading successfully.
Changes:
- Add validation that the second half of
LDDWhasdst == 0,src == 0, andoffset == 0. - Add a new negative test case covering an
LDDWsecond-half instruction with a non-zerodstfield.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
vm/ubpf_vm.c |
Strengthens LDDW validation by enforcing zeroed register/offset fields in the second half. |
tests/errors/err-lddw-second-half-invalid.data |
Adds regression coverage ensuring malformed LDDW second halves are rejected with the expected error. |
| if (i + 1 >= num_insts || insts[i + 1].opcode != 0) { | ||
| *errmsg = ubpf_error("incomplete lddw at PC %d", i); | ||
| return false; | ||
| } | ||
| if (insts[i + 1].dst != 0 || insts[i + 1].src != 0 || insts[i + 1].offset != 0) { | ||
| *errmsg = ubpf_error("invalid lddw second half at PC %d", i + 1); |
There was a problem hiding this comment.
The incomplete lddw at PC %d error is also returned when insts[i+1].opcode != 0, which isn’t an “incomplete” LDDW but an invalid second-half instruction. Consider splitting the condition so the out-of-range case reports "incomplete lddw" while the opcode-mismatch case reports "invalid lddw second half" (at PC i+1) to make failures easier to diagnose and align with the expected semantics of the LDDW second half.
|
Thanks for this contribution, @ppx123-web! The fix looks correct and aligns well with RFC 9669 — nice work. 👍 One small ask: the current test covers the case where
No pressure at all — we're happy to merge as-is and add them ourselves if you'd prefer. Just wanted to flag it in case you'd like to round it out. Thanks again! |
|
I am sorry that I missed the reply, I will do this. |
Exercise each reserved field (dst, src, offset) individually and in combination per RFC 9669, ensuring the validator rejects non-zero values in the LDDW pseudo-instruction's second slot. New test cases: - invalid-src: src != 0 only - invalid-offset: offset != 0 only - invalid-dst-offset: dst != 0 + offset != 0 - invalid-src-offset: src != 0 + offset != 0 - invalid-all: dst != 0 + src != 0 + offset != 0 Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
I have added the test cases. LDDW first-half
|
| src_reg | pseudocode | type |
|---|---|---|
| 0x0 | dst = (next_imm << 32) | imm |
integer to integer |
| 0x1 | dst = map_by_fd(imm) |
map fd to map |
| 0x2 | dst = map_val(map_by_fd(imm)) + next_imm |
map fd to data address |
| 0x3 | dst = var_addr(imm) |
variable id to data address |
| 0x4 | dst = code_addr(imm) |
integer to code address |
| 0x5 | dst = map_by_idx(imm) |
map index to map |
| 0x6 | dst = map_val(map_by_idx(imm)) + next_imm |
map index to data address |
Values 0x7–0xF are undefined and should be rejected as invalid. Values 0x1–0x6 are valid per the spec but not implemented in ubpf (no kernel map infrastructure).
Problem
A program with src_reg=1 (a valid map_by_fd LDDW used by the Linux kernel loader) gets the same "invalid source register" error as a program with src_reg=15 (genuinely malformed). This is misleading — one is a well-formed program that ubpf doesn't support, the other is a broken program.
Suggested fix
Split the check into two:
case EBPF_OP_LDDW:
if (inst.src > 6) {
*errmsg = ubpf_error("invalid source register for LDDW at PC %d", i);
return false;
}
if (inst.src != 0) {
*errmsg = ubpf_error("unsupported LDDW variant (src=%d) at PC %d", inst.src, i);
return false;
}- src 7–15:
"invalid source register"— the program violates the RFC - src 1–6:
"unsupported LDDW variant"— the program is valid but ubpf can't run it
Both still reject at load time. No interpreter changes needed. The only difference is a more accurate error message.
References
- RFC 9669 Section 5.4: https://www.rfc-editor.org/rfc/rfc9669.html#section-5.4
- RFC 9669 Section 3.2 (wide instruction encoding): https://www.rfc-editor.org/rfc/rfc9669.html#section-3.2
Patch for issue 757
Fix the lddw instructon validation.