Skip to content

Enforce map-function compatibility checks#1127

Merged
elazarg merged 3 commits into
mainfrom
map-func-compat
May 26, 2026
Merged

Enforce map-function compatibility checks#1127
elazarg merged 3 commits into
mainfrom
map-func-compat

Conversation

@elazarg
Copy link
Copy Markdown
Collaborator

@elazarg elazarg commented May 26, 2026

Summary

  • Add allowed_map_types bitmask to EbpfHelperPrototype and CallContract
  • New ValidMapType assertion emitted when a helper with restricted map types receives a map fd argument
  • Checker rejects mismatches at verification time
  • Populated for 34 helpers matching the kernel v6.18 check_map_func_compatibility function→map direction

Details

The kernel enforces bidirectional map-function compatibility: certain map types may only be used with specific helpers, and certain helpers may only receive specific map types. Prevail had no such check — any map type was accepted by any helper with a PTR_TO_MAP argument (except tail_call, which uses PTR_TO_MAP_OF_PROGRAMS).

This PR encodes the function→map direction. Map type UNSPEC (0) is treated as unknown and silently allowed to avoid false positives from incomplete ELF metadata. The reverse direction (map→function, e.g., "PERF_EVENT_ARRAY may not be passed to map_update_elem") is left for a follow-up.

Test plan

  • Full test suite passes (1559 cases, 225 expected failures, 0 regressions)
  • New assertion visible in printed output for affected helpers (e.g., valid_map_type(r1, ringbuf_output))

Closes #1123
Ref: #68

🤖 Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

Review Change Stack

Warning

Review limit reached

@elazarg, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 21 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1e51ad8b-c218-4e1b-95d5-6db2adcc092c

📥 Commits

Reviewing files that changed from the base of the PR and between ec5d2cf and e77e5e1.

📒 Files selected for processing (1)
  • src/crab/ebpf_checker.cpp
📝 Walkthrough

Walkthrough

This PR implements bidirectional map-function compatibility enforcement for eBPF helpers. New type contracts define which map types each helper permits, prototypes are populated with these restrictions, and assertions extracted during call analysis are validated during abstract interpretation to reject invalid map accesses.

Changes

Map-Function Compatibility Validation

Layer / File(s) Summary
Contract and Type System
src/ir/syntax.hpp, src/spec/function_prototypes.hpp
ValidMapType assertion struct with map FD register, allowed types bitmask, and helper name. CallContract and EbpfHelperPrototype each gain allowed_map_types field. New map_type_bit() constexpr converts kernel map type IDs to bitmasks.
Helper Prototype Map Type Mappings
src/linux/gpl/spec_prototypes.cpp
Internal MT_* bitmask constants map kernel BPF_MAP_TYPE_* values. Forty-two helper prototypes populated: single-type restrictions (perf event, ringbuf, storage types) and multi-type permissions (redirect_map, queue/stack/bloom operations).
Contract Resolution and Assertion Extraction
src/ir/call_resolver.cpp, src/ir/assertions.cpp
allowed_map_types propagated from prototype to resolved call contract. ValidMapType assertions emitted during extraction when a call has a MAP_FD-typed register and non-zero allowed_map_types.
Map Type Validation During Analysis
src/crab/ebpf_checker.cpp
EbpfChecker visitor for ValidMapType extracts inferred map type from abstract domain. Skips validation when domain is bottom or type unresolved; otherwise checks inferred type against allowed_map_types, failing if type not permitted.
Output Formatting and Register Extraction
src/printing.cpp, src/result.cpp
AssertionPrinterVisitor renders ValidMapType as valid_map_type(map_fd_reg, helper_name). extract_assertion_registers returns map_fd_reg for backward slicing of map type assertions.

Possibly Related PRs

  • vbpf/prevail#1024: Both PRs extend AssertExtractor::operator()(const Call&) in src/ir/assertions.cpp to emit new assertion types based on call contracts, creating potential merge conflicts at the assertion emission point.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main objective of the PR: enforcing map-function compatibility checks, which matches the primary changes across all modified files.
Description check ✅ Passed The description accurately relates to the changeset, detailing the addition of allowed_map_types bitmask, ValidMapType assertion implementation, and population of 34 helpers with kernel compatibility rules.
Linked Issues check ✅ Passed The PR fully addresses issue #1123 objectives: adds allowed_map_types to prototypes/contracts, emits ValidMapType assertions for mismatches, implements checker verification, and populates 34 helpers from kernel v6.18 rules.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing map-function compatibility: helper prototypes, contract propagation, assertion creation/checking, and output formatting. No unrelated modifications present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch map-func-compat

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6f657b8d1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/crab/ebpf_checker.cpp
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/crab/ebpf_checker.cpp`:
- Around line 294-295: The bit-shift uses uint64_t{1} << *map_type which is UB
if *map_type >= 64 because EbpfMapDescriptor::type isn't clamped; before
performing the shift in the check around s.allowed_map_types, first validate
*map_type is less than 64 (or otherwise within the mask width) and throw_fail
with a clear message if out of range, or rewrite the condition to short-circuit
(e.g. require *map_type < 64 && (s.allowed_map_types & (1ULL << *map_type))) so
the shift never happens with an invalid value; update the check that currently
calls throw_fail("map type " + std::to_string(*map_type) + " is not allowed for
" + s.helper_name) accordingly.

In `@src/spec/function_prototypes.hpp`:
- Line 11: The helper map_type_bit performs a left shift that is UB when type >=
64; update map_type_bit to guard against out‑of‑range shifts (e.g. return 0 or
another sentinel when type >= 64) by checking the input before shifting so the
expression uint64_t{1} << type is only executed for type < 64; modify the
constexpr function map_type_bit(uint32_t type) to include that bounds check to
make it safe for runtime-derived map IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c23c0ce0-6582-4f6d-9ef0-136992c233b7

📥 Commits

Reviewing files that changed from the base of the PR and between 1c44e42 and 6f657b8.

📒 Files selected for processing (8)
  • src/crab/ebpf_checker.cpp
  • src/ir/assertions.cpp
  • src/ir/call_resolver.cpp
  • src/ir/syntax.hpp
  • src/linux/gpl/spec_prototypes.cpp
  • src/printing.cpp
  • src/result.cpp
  • src/spec/function_prototypes.hpp

Comment thread src/crab/ebpf_checker.cpp
Comment thread src/spec/function_prototypes.hpp Outdated
elazarg and others added 2 commits May 26, 2026 18:21
Add allowed_map_types bitmask to EbpfHelperPrototype, threaded through
CallContract and checked via a new ValidMapType assertion. This encodes
the function→map direction of the kernel's check_map_func_compatibility
(v6.18): each helper that requires specific map types now declares them,
and the checker rejects mismatches at verification time.

Covers 34 helpers across perf_event, ringbuf, storage, redirect, queue/
stack, cgroup, and reuseport families. Map type UNSPEC (0) is treated
as unknown and silently allowed to avoid false positives from incomplete
ELF metadata.

Closes #1123

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Elazar Gershuni <elazarg@gmail.com>
map_type_bit() and the ValidMapType checker now handle map types >= 64
without undefined behavior. map_type_bit returns 0 for out-of-range
types; the checker skips the check (same as UNSPEC).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Elazar Gershuni <elazarg@gmail.com>
@elazarg elazarg force-pushed the map-func-compat branch from 5d2afc0 to ec5d2cf Compare May 26, 2026 15:23
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/crab/ebpf_checker.cpp`:
- Around line 298-300: The check around map_type currently returns early for
missing/zero/>=64 values which silently accepts the path; change it to
fail-closed: when map_type is not present, ==0, or >=64 treat the call as
invalid and explicitly reject the path using the checker’s existing rejection
mechanism (e.g., return false / call the verifier-reject helper used elsewhere
in ebpf_checker.cpp) instead of just returning; ensure you update the branch
that references map_type to use this reject behavior so malformed or future map
IDs do not bypass verification.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9e10954e-9bbe-473f-bb43-e0efb2220585

📥 Commits

Reviewing files that changed from the base of the PR and between 6f657b8 and ec5d2cf.

📒 Files selected for processing (8)
  • src/crab/ebpf_checker.cpp
  • src/ir/assertions.cpp
  • src/ir/call_resolver.cpp
  • src/ir/syntax.hpp
  • src/linux/gpl/spec_prototypes.cpp
  • src/printing.cpp
  • src/result.cpp
  • src/spec/function_prototypes.hpp

Comment thread src/crab/ebpf_checker.cpp Outdated
Map types >= 64 now fail verification rather than skipping the
compatibility check, preventing malformed or future map IDs from
bypassing the constraint.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Elazar Gershuni <elazarg@gmail.com>
@elazarg
Copy link
Copy Markdown
Collaborator Author

elazarg commented May 26, 2026

Addressed CodeRabbit review: map types >= 64 now fail-closed (e77e5e1) instead of silently skipping the check.

@elazarg elazarg merged commit 474acee into main May 26, 2026
16 checks passed
@elazarg elazarg deleted the map-func-compat branch May 26, 2026 17:03
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.

Enforce map-function compatibility checks

1 participant