microsoft / microsoft/ebpf-for-windows

Linux compatibility: IPv4-mapped AF_INET6 connect invokes cgroup/connect4 instead of connect6

Open
#5,536 5 comments 0 reactions 1 assignee Claimed by @saxena-anurag View on GitHub
linux_compatibility triaged
Dominant language
C
Stars
3.6k
Forks
311
Avg merge
6d 10h
Merged PRs (30d)
21

Description

## Describe the bug

An `AF_INET6` dual-stack socket (`IPV6_V6ONLY=0`) connecting to an IPv4 destination through an IPv4-mapped IPv6 address, for example `[::ffff:169.254.169.254]`, invokes `BPF_CGROUP_INET4_CONNECT` (`cgroup/connect4`) on eBPF for Windows.

Linux invokes `BPF_CGROUP_INET6_CONNECT` (`cgroup/connect6`) for the same socket API operation because the hook runs from the IPv6 protocol `pre_connect` path before the IPv4-mapped destination is translated for IPv4 transport.

This is a source-semantics compatibility issue: a portable policy attached only to `cgroup/connect6` observes this request on Linux but misses it on Windows. For security policies, this can create an unintended policy gap.

The current Windows behavior appears intentional and is covered by the `v4_mapped` IPv4 test groups, but it differs from Linux hook selection semantics.

## OS information

All Windows versions supported by the current implementation. This is a code-level behavior in `netebpfext`, not an OS-version-specific observation.

## Steps taken to reproduce bug

1. Create an `AF_INET6` TCP or UDP socket.
2. Set `IPV6_V6ONLY` to `0` (dual-stack).
3. Attach one counter program to `cgroup/connect4` and another to `cgroup/connect6`.
4. Call `connect()` with a `sockaddr_in6` destination such as `[::ffff:169.254.169.254]:80`.
5. Compare which counter increments on Windows and Linux.

## Expected behavior

Match Linux semantics:

- Invoke `cgroup/connect6`, since the user supplied an `AF_INET6` / `sockaddr_in6` request.
- Present `ctx->family == AF_INET6`.
- Preserve the IPv4-mapped address in `ctx->user_ip6`.
- Do not invoke `cgroup/connect4` for this request.

Internal WFP processing may still translate the destination to IPv4 after the eBPF hook runs.

## Actual outcome

Windows invokes `cgroup/connect4`.

At `FWPM_LAYER_ALE_CONNECT_REDIRECT_V6`, `net_ebpf_extension_sock_addr_redirect_connection_classify()` detects the IPv4-mapped address. `_net_ebpf_extension_sock_addr_should_invoke_ebpf_program()` selects the IPv4 attach type and skips the IPv6 attach type. `_convert_ipv4_mapped_to_ipv4()` then changes the public context to `AF_INET`, clears the 16-byte `user_ip6` union storage, and writes the destination to `user_ip4` before invoking the eBPF program.

Consequently, the program cannot determine from the public `bpf_sock_addr_t` whether the request originated as native IPv4 or as an IPv4-mapped `AF_INET6` request. The implementation retains a private `v4_mapped` bit in `net_ebpf_sock_addr_t`, but it is not exposed to the program.

## Additional details

Relevant implementation:

- `netebpfext/net_ebpf_ext_sock_addr.c`: `_net_ebpf_extension_sock_addr_should_invoke_ebpf_program()`
- `netebpfext/net_ebpf_ext_sock_addr.c`: `_convert_ipv4_mapped_to_ipv4()`
- `netebpfext/net_ebpf_ext_sock_addr.c`: `_cgroup_inet4_connect_filter_parameters` installs an IPv6 redirect-layer filter specifically for dual-stack processing
- `tests/connect_redirect/connect_redirect_tests.cpp`: `v4_mapped` cases are declared as IPv4 authorization and redirection test groups

Linux reference behavior:

- `tcp_v6_pre_connect()` invokes `BPF_CGROUP_RUN_PROG_INET6_CONNECT()` before `tcp_v6_connect()` converts a mapped destination and calls `tcp_v4_connect()`.
- `udpv6_pre_connect()` similarly invokes `BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK()` for an `AF_INET6` address before `__ip6_datagram_connect()` handles the mapped destination.

A behavior change may require compatibility planning because existing Windows programs and tests can depend on the current `connect4` dispatch. At minimum, the mismatch should be explicitly documented; preferably, hook dispatch and context semantics should match Linux.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.