Normalize and correct sock_addr verdict handling - #5546
Normalize and correct sock_addr verdict handling#5546D. Michael Agun (mikeagun) wants to merge 3 commits into
Conversation
Centralize sock_addr classify preconditions and translate verdicts to WFP actions only at each exit path. Preserve connect-authorization cache cleanup and connect-redirect's specialized action semantics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f80bc76a-92b4-4658-9ce2-ca11c31b615c
There was a problem hiding this comment.
🔵 Needs a closer look
It changes kernel networking classification logic (verdict/action/right handling) and warrants careful human validation despite only minor nits found.
Pull request overview
This PR normalizes sock_addr WFP classify callback behavior in netebpfext by standardizing default verdicts, write-right handling, and program-invocation result mapping, then translating final verdicts to WFP actions in a consistent exit path.
Changes:
- Introduces shared helpers to centralize
FWPS_RIGHT_ACTION_WRITEchecks, active filter-context validation, and program-result→verdict normalization. - Updates
sock_addrclassify callbacks to default toBPF_SOCK_ADDR_VERDICT_PROCEED_SOFT, skip program invocation without write rights, and apply verdicts via common exit logic. - Refactors CONNECT_REDIRECT to apply action decisions via a dedicated helper and prevents verdict-cache operations before the socket context is initialized.
File summaries
| File | Description |
|---|---|
| netebpfext/net_ebpf_ext_sock_addr.c | Centralizes sock_addr verdict/action handling and normalizes classification behavior across callbacks. |
Review details
Suppressed comments (2)
netebpfext/net_ebpf_ext_sock_addr.c:2541
- incoming_metadata_values is used later (e.g., transportEndpointHandle and field copy), so UNREFERENCED_PARAMETER(incoming_metadata_values) is inaccurate and should be removed to avoid confusion.
UNREFERENCED_PARAMETER(incoming_metadata_values);
netebpfext/net_ebpf_ext_sock_addr.c:2353
- incoming_metadata_values is referenced later (e.g., used for transportEndpointHandle logging and passed into _net_ebpf_extension_sock_addr_copy_wfp_connection_fields), so UNREFERENCED_PARAMETER(incoming_metadata_values) is inaccurate and should be removed to avoid confusion.
UNREFERENCED_PARAMETER(incoming_metadata_values);
- Files reviewed: 1/1 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
doxygen fix and remove incorrect `UNREFERENCED_PARAMETER` Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Replace the write-right and filter-context helpers with bail macros, and perform connect-authorization cache cleanup before the no-write exit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f80bc76a-92b4-4658-9ce2-ca11c31b615c
There was a problem hiding this comment.
🔵 Needs a closer look
Moderate regression-test gaps remain for write-right handling and fail-closed listen errors.
Review details
Suppressed comments (2)
netebpfext/net_ebpf_ext_sock_addr.c:30
- These new gates implement the PR's key FWPS_RIGHT_ACTION_WRITE behavior, but the existing netebpfext_unit coverage never supplies a classify output with the write right revoked (the tests explicitly note that this state cannot be inspected). There is therefore no regression test that dispatch is skipped and the pre-existing action is preserved, especially for connect-authorization cache cleanup; add a simulator or integration case covering both outcomes.
#define BAIL_ON_NO_WRITE_RIGHT(classify_output, action_write_allowed) \
do { \
(action_write_allowed) = (((classify_output)->rights & FWPS_RIGHT_ACTION_WRITE) != 0); \
if (!(action_write_allowed)) { \
EBPF_EXT_LOG_MESSAGE( \
netebpfext/net_ebpf_ext_sock_addr.c:2280
- The new failure mapping for the listen callback is not covered by the existing sock_addr tests:
sock_addr_listen_invokeexercises soft permit, reject, and hard permit, but unlikesock_addr_invokeit never setsSOCK_ADDR_TEST_ACTION_FAILURE. Add IPv4/IPv6 assertions that a listen program invocation failure becomes a block with the write right revoked, so this required fail-closed behavior cannot regress.
program_result = net_ebpf_extension_hook_expand_stack_and_invoke_programs(
sock_addr_ctx, &filter_context->base, &program_verdict);
verdict = _net_ebpf_extension_sock_addr_get_program_verdict(program_result, program_verdict, verdict);
- Files reviewed: 1/1 changed files
- Comments generated: 0 new
- Review effort level: Lite
| } | ||
|
|
||
| #define BAIL_ON_NO_WRITE_RIGHT(classify_output, action_write_allowed) \ | ||
| do { \ |
There was a problem hiding this comment.
nit: should we preserve / add a comment here, something like below:
// A callout with higher weight has revoked the write permission. Bail out without
// invoking any eBPF program and without touching classify_output->actionType.
| (action_write_allowed) = (((classify_output)->rights & FWPS_RIGHT_ACTION_WRITE) != 0); \ | ||
| if (!(action_write_allowed)) { \ | ||
| EBPF_EXT_LOG_MESSAGE( \ | ||
| EBPF_EXT_TRACELOG_LEVEL_VERBOSE, EBPF_EXT_TRACELOG_KEYWORD_SOCK_ADDR, "No \"write\" right; exiting."); \ |
There was a problem hiding this comment.
nit: add __ FUNCTION __ also in the trace.
| EBPF_EXT_LOG_MESSAGE_NTSTATUS( \ | ||
| EBPF_EXT_TRACELOG_LEVEL_ERROR, \ | ||
| EBPF_EXT_TRACELOG_KEYWORD_SOCK_ADDR, \ | ||
| "filter_context is NULL.", \ |
There was a problem hiding this comment.
nit: add __ FUNCTION __
| } | ||
|
|
||
| static inline uint32_t | ||
| _net_ebpf_extension_sock_addr_get_program_verdict( |
There was a problem hiding this comment.
nit: maybe add comment description / comment for this function
| return; | ||
| } | ||
|
|
||
| // CONNECT_REDIRECT never blocks directly. Redirects and rejected connections terminate this layer; rejections |
There was a problem hiding this comment.
nit: should it be terminate this **sublayer**?
| NULL, | ||
| result, | ||
| compartment_id); | ||
| if (program_result == EBPF_SUCCESS) { |
There was a problem hiding this comment.
Should we not add a trace when program invocation failed?
| { | ||
| EBPF_EXT_LOG_ENTRY(); | ||
| uint32_t result; | ||
| uint32_t verdict = BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT; |
There was a problem hiding this comment.
nit: effective_verdict or final_verdict?
| _Inout_ FWPS_CLASSIFY_OUT* classify_output, | ||
| uint32_t verdict, | ||
| bool action_write_allowed, | ||
| bool reauthorization, |
There was a problem hiding this comment.
question: do we need special handling for reauthorization only in case of connect_redirect?
| EBPF_EXT_LOG_ENTRY(); | ||
| uint32_t ignored_result; | ||
| uint32_t verdict; | ||
| uint32_t ignored_result = BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT; |
There was a problem hiding this comment.
Other functions are using verdict and program_verdict and some use ignored_verdict. Is it possible to make them all use the same pattern.
| // set original_context to point at a pristine snapshot of bpf_sock_addr_t | ||
| // before invoking any program. | ||
| static bool | ||
| _net_ebpf_extension_sock_addr_accumulate_verdict(_Inout_ void* program_context, int program_verdict) |
There was a problem hiding this comment.
nit (non-blocking): There are 2 versions of process_verdict callbacks -- _net_ebpf_extension_sock_addr_accumulate_verdict and _net_ebpf_extension_sock_addr_process_verdict. Is it possible to merge them too?
Description
Normalize verdict and WFP action handling across all
sock_addrclassify callbacks.BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT.FWPS_RIGHT_ACTION_WRITEis absent, preserving the existing WFP action rather than issuing a veto.EBPF_SUCCESSuses the returned or accumulated program verdict.EBPF_OBJECT_NOT_FOUNDpreserves the current verdict.BPF_SOCK_ADDR_VERDICT_REJECT.PROCEED_SOFTreturnsFWP_ACTION_PERMITwhile retaining the write right.PROCEED_HARDreturnsFWP_ACTION_PERMITand clears the write right.FWP_ACTION_BLOCKand clear the write right.CONTINUE, while redirects and cached rejections return terminatingPERMIT.Closes #5544.
Testing
drivers\netebpfextbuild.tests\netebpfext_unitbuild.netebpfext_unit: 494 assertions in 25 test cases.