Skip to content

Normalize and correct sock_addr verdict handling - #5546

Open
D. Michael Agun (mikeagun) wants to merge 3 commits into
microsoft:mainfrom
mikeagun:mikeagun-investigate-sock-addr-verdicts
Open

Normalize and correct sock_addr verdict handling#5546
D. Michael Agun (mikeagun) wants to merge 3 commits into
microsoft:mainfrom
mikeagun:mikeagun-investigate-sock-addr-verdicts

Conversation

@mikeagun

@mikeagun D. Michael Agun (mikeagun) commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Description

Normalize verdict and WFP action handling across all sock_addr classify callbacks.

  • Initialize every callback with BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT.
  • Skip eBPF program invocation when FWPS_RIGHT_ACTION_WRITE is absent, preserving the existing WFP action rather than issuing a veto.
  • Use the soft-permit default for exits that occur before eBPF program invocation, including filter-context validation and classify-handle acquisition failures.
  • Normalize program invocation results:
    • EBPF_SUCCESS uses the returned or accumulated program verdict.
    • EBPF_OBJECT_NOT_FOUND preserves the current verdict.
    • Other invocation failures produce BPF_SOCK_ADDR_VERDICT_REJECT.
  • Centralize write-right checks, active filter-context validation, and program-result handling.
  • Keep classify callback bodies verdict-only and translate verdicts to WFP actions from their exit paths:
    • PROCEED_SOFT returns FWP_ACTION_PERMIT while retaining the write right.
    • PROCEED_HARD returns FWP_ACTION_PERMIT and clears the write right.
    • Reject and unknown verdicts return FWP_ACTION_BLOCK and clear the write right.
  • Ensure listen and receive-accept invocation failures produce a non-overridable block.
  • Preserve connect-authorization cache cleanup when write rights are absent and preserve cached hard/reject verdicts when no authorization program matches.
  • Preserve connect-redirect's specialized behavior: ordinary soft decisions return CONTINUE, while redirects and cached rejections return terminating PERMIT.
  • Only process the connect-redirect verdict cache after the socket context has been initialized, avoiding invalid zero-context cache operations on early exits.

Closes #5544.

Testing

  • Debug x64 drivers\netebpfext build.
  • Debug x64 tests\netebpfext_unit build.
  • netebpfext_unit: 494 assertions in 25 test cases.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 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_WRITE checks, active filter-context validation, and program-result→verdict normalization.
  • Updates sock_addr classify callbacks to default to BPF_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.

Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
doxygen fix and remove incorrect `UNREFERENCED_PARAMETER`

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
Comment thread netebpfext/net_ebpf_ext_sock_addr.c Outdated
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
Copilot AI review requested due to automatic review settings September 11, 2026 22:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 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_invoke exercises soft permit, reject, and hard permit, but unlike sock_addr_invoke it never sets SOCK_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 { \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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."); \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.", \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: add __ FUNCTION __

}

static inline uint32_t
_net_ebpf_extension_sock_addr_get_program_verdict(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: maybe add comment description / comment for this function

return;
}

// CONNECT_REDIRECT never blocks directly. Redirects and rejected connections terminate this layer; rejections

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: should it be terminate this **sublayer**?

NULL,
result,
compartment_id);
if (program_result == EBPF_SUCCESS) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: effective_verdict or final_verdict?

_Inout_ FWPS_CLASSIFY_OUT* classify_output,
uint32_t verdict,
bool action_write_allowed,
bool reauthorization,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Normalize and correct sock_addr verdict handling

4 participants