Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

wasi-sockets: restore UDP send address validation - #13631

#13631
Merged
alexcrichton merged 1 commit into
bytecodealliance:mainbytecodealliance/wasmtime:mainfrom
badeend:udp-send-unspecbadeend/wasmtime:udp-send-unspecCopy head branch name to clipboard
Jun 13, 2026
Merged

wasi-sockets: restore UDP send address validation#13631
alexcrichton merged 1 commit into
bytecodealliance:mainbytecodealliance/wasmtime:mainfrom
badeend:udp-send-unspecbadeend/wasmtime:udp-send-unspecCopy head branch name to clipboard

Conversation

@badeend

@badeend badeend commented Jun 13, 2026

Copy link
Copy Markdown
Member

Make the P3 implementation of UDP send perform the same validation as in P2

Fixes #12568
Relates to #12475

@badeend
badeend requested review from a team as code owners June 13, 2026 07:58
@badeend
badeend requested review from pchickey and removed request for a team June 13, 2026 07:58
@github-actions github-actions Bot added the wasi Issues pertaining to WASI label Jun 13, 2026
@alexcrichton
alexcrichton added this pull request to the merge queue Jun 13, 2026
Merged via the queue into bytecodealliance:main with commit ab4c623 Jun 13, 2026
51 checks passed
@badeend
badeend deleted the udp-send-unspec branch June 14, 2026 09:16
badeend added a commit to badeend/wasmtime that referenced this pull request Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after
the p2 interface, with p3 bindings papering over the differences, and
some functionality duplicated between p2/* and p3/*. This has already
caused bugs in the past (bytecodealliance#13631).

Since the p3 interface is strictly a superset of p2, invert that
relationship: the shared code becomes the canonical (p3-shaped)
implementation, and p3's bindings are now a thin wrapper around it.
All p2-only behavior & state moves into the p2 bindings layer instead
(artificial restrictions like disallowing implicit binds, and the
start/finish async bookkeeping).

Other notable changes:

- Each socket now stores its own copy of the WasiCtx's
  socket_addr_check at creation time, so all permission checks live in
  the shared socket code instead of being split across p2/p3. The p2
  Network resource is now just an unforgeable capability token.
- Removed the Bound state; whether a socket is bound is now determined
  lazily via getsockname/local_addr instead of tracked explicitly. This
  lets UdpSocket::send return a future that runs to completion
  independently, without needing to rendezvous back with the socket to
  update its state.
- Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive;
  replaced UdpConnect with UdpSend/UdpReceive checks, since connecting
  a UDP socket is just a local operation that sets the default remote
  address and does no I/O of its own. connect() now succeeds as long
  as either send or receive is permitted for the address.
- Tcp/UdpSocket::connect now also check the implicit bind the OS
  performs when connecting an unbound socket, matching the check
  already done for explicit binds.

Added test coverage for previously-untested behavior:

- test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP
  socket keeps it bound.
- test_udp_send_receive_multiple (p2): bulk send/receive of multiple
  datagrams in a single call over a connected stream().
- test_udp_receive_after_connect (p2): datagrams from other peers
  queued before connecting are filtered out once connected.
badeend added a commit to badeend/wasmtime that referenced this pull request Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after
the p2 interface, with p3 bindings papering over the differences, and
some functionality duplicated between p2/* and p3/*. This has already
caused bugs in the past (bytecodealliance#13631).

Since the p3 interface is strictly a superset of p2, invert that
relationship: the shared code becomes the canonical (p3-shaped)
implementation, and p3's bindings are now a thin wrapper around it.
All p2-only behavior & state moves into the p2 bindings layer instead
(artificial restrictions like disallowing implicit binds, and the
start/finish async bookkeeping).

Other notable changes:

- Each socket now stores its own copy of the WasiCtx's
  socket_addr_check at creation time, so all permission checks live in
  the shared socket code instead of being split across p2/p3. The p2
  Network resource is now just an unforgeable capability token.
- Removed the Bound state; whether a socket is bound is now determined
  lazily via getsockname/local_addr instead of tracked explicitly. This
  lets UdpSocket::send return a future that runs to completion
  independently, without needing to rendezvous back with the socket to
  update its state.
- Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive;
  replaced UdpConnect with UdpSend/UdpReceive checks, since connecting
  a UDP socket is just a local operation that sets the default remote
  address and does no I/O of its own. connect() now succeeds as long
  as either send or receive is permitted for the address.
- Tcp/UdpSocket::connect now also check the implicit bind the OS
  performs when connecting an unbound socket, matching the check
  already done for explicit binds.

Added test coverage for previously-untested behavior:

- test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP
  socket keeps it bound.
- test_udp_send_receive_multiple (p2): bulk send/receive of multiple
  datagrams in a single call over a connected stream().
- test_udp_receive_after_connect (p2): datagrams from other peers
  queued before connecting are filtered out once connected.
badeend added a commit to badeend/wasmtime that referenced this pull request Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after
the p2 interface, with p3 bindings papering over the differences, and
some functionality duplicated between p2/* and p3/*. This has already
caused bugs in the past (bytecodealliance#13631).

Since the p3 interface is strictly a superset of p2, invert that
relationship: the shared code becomes the canonical (p3-shaped)
implementation, and p3's bindings are now a thin wrapper around it.
All p2-only behavior & state moves into the p2 bindings layer instead
(artificial restrictions like disallowing implicit binds, and the
start/finish async bookkeeping).

Other notable changes:

- Each socket now stores its own copy of the WasiCtx's
  socket_addr_check at creation time, so all permission checks live in
  the shared socket code instead of being split across p2/p3. The p2
  Network resource is now just an unforgeable capability token.
- Removed the Bound state; whether a socket is bound is now determined
  lazily via getsockname/local_addr instead of tracked explicitly. This
  lets UdpSocket::send return a future that runs to completion
  independently, without needing to rendezvous back with the socket to
  update its state.
- Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive;
  replaced UdpConnect with UdpSend/UdpReceive checks, since connecting
  a UDP socket is just a local operation that sets the default remote
  address and does no I/O of its own. connect() now succeeds as long
  as either send or receive is permitted for the address.
- Tcp/UdpSocket::connect now also check the implicit bind the OS
  performs when connecting an unbound socket, matching the check
  already done for explicit binds.

Added test coverage for previously-untested behavior:

- test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP
  socket keeps it bound.
- test_udp_send_receive_multiple (p2): bulk send/receive of multiple
  datagrams in a single call over a connected stream().
- test_udp_receive_after_connect (p2): datagrams from other peers
  queued before connecting are filtered out once connected.
badeend added a commit to badeend/wasmtime that referenced this pull request Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after
the p2 interface, with p3 bindings papering over the differences, and
some functionality duplicated between p2/* and p3/*. This has already
caused bugs in the past (bytecodealliance#13631).

Since the p3 interface is strictly a superset of p2, invert that
relationship: the shared code becomes the canonical (p3-shaped)
implementation, and p3's bindings are now a thin wrapper around it.
All p2-only behavior & state moves into the p2 bindings layer instead
(artificial restrictions like disallowing implicit binds, and the
start/finish async bookkeeping).

Other notable changes:

- Each socket now stores its own copy of the WasiCtx's
  socket_addr_check at creation time, so all permission checks live in
  the shared socket code instead of being split across p2/p3. The p2
  Network resource is now just an unforgeable capability token.
- Removed the Bound state; whether a socket is bound is now determined
  lazily via getsockname/local_addr instead of tracked explicitly. This
  lets UdpSocket::send return a future that runs to completion
  independently, without needing to rendezvous back with the socket to
  update its state.
- Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive;
  replaced UdpConnect with UdpSend/UdpReceive checks, since connecting
  a UDP socket is just a local operation that sets the default remote
  address and does no I/O of its own. connect() now succeeds as long
  as either send or receive is permitted for the address.
- Tcp/UdpSocket::connect now also check the implicit bind the OS
  performs when connecting an unbound socket, matching the check
  already done for explicit binds.

Added test coverage for previously-untested behavior:

- test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP
  socket keeps it bound.
- test_udp_send_receive_multiple (p2): bulk send/receive of multiple
  datagrams in a single call over a connected stream().
- test_udp_receive_after_connect (p2): datagrams from other peers
  queued before connecting are filtered out once connected.
badeend added a commit to badeend/wasmtime that referenced this pull request Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after
the p2 interface, with p3 bindings papering over the differences, and
some functionality duplicated between p2/* and p3/*. This has already
caused bugs in the past (bytecodealliance#13631).

Since the p3 interface is strictly a superset of p2, invert that
relationship: the shared code becomes the canonical (p3-shaped)
implementation, and p3's bindings are now a thin wrapper around it.
All p2-only behavior & state moves into the p2 bindings layer instead
(artificial restrictions like disallowing implicit binds, and the
start/finish async bookkeeping).

Other notable changes:

- Each socket now stores its own copy of the WasiCtx's
  socket_addr_check at creation time, so all permission checks live in
  the shared socket code instead of being split across p2/p3. The p2
  Network resource is now just an unforgeable capability token.
- Removed the Bound state; whether a socket is bound is now determined
  lazily via getsockname/local_addr instead of tracked explicitly. This
  lets UdpSocket::send return a future that runs to completion
  independently, without needing to rendezvous back with the socket to
  update its state.
- Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive;
  replaced UdpConnect with UdpSend/UdpReceive checks, since connecting
  a UDP socket is just a local operation that sets the default remote
  address and does no I/O of its own. connect() now succeeds as long
  as either send or receive is permitted for the address.
- Tcp/UdpSocket::connect now also check the implicit bind the OS
  performs when connecting an unbound socket, matching the check
  already done for explicit binds.

Added test coverage for previously-untested behavior:

- test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP
  socket keeps it bound.
- test_udp_send_receive_multiple (p2): bulk send/receive of multiple
  datagrams in a single call over a connected stream().
- test_udp_receive_after_connect (p2): datagrams from other peers
  queued before connecting are filtered out once connected.
pull Bot pushed a commit to eduardomourar/wasmtime that referenced this pull request Jul 23, 2026
* Unify the p2 & p3 socket implementations

The shared socket code (crates/wasi/src/sockets/*) was modeled after
the p2 interface, with p3 bindings papering over the differences, and
some functionality duplicated between p2/* and p3/*. This has already
caused bugs in the past (bytecodealliance#13631).

Since the p3 interface is strictly a superset of p2, invert that
relationship: the shared code becomes the canonical (p3-shaped)
implementation, and p3's bindings are now a thin wrapper around it.
All p2-only behavior & state moves into the p2 bindings layer instead
(artificial restrictions like disallowing implicit binds, and the
start/finish async bookkeeping).

Other notable changes:

- Each socket now stores its own copy of the WasiCtx's
  socket_addr_check at creation time, so all permission checks live in
  the shared socket code instead of being split across p2/p3. The p2
  Network resource is now just an unforgeable capability token.
- Removed the Bound state; whether a socket is bound is now determined
  lazily via getsockname/local_addr instead of tracked explicitly. This
  lets UdpSocket::send return a future that runs to completion
  independently, without needing to rendezvous back with the socket to
  update its state.
- Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive;
  replaced UdpConnect with UdpSend/UdpReceive checks, since connecting
  a UDP socket is just a local operation that sets the default remote
  address and does no I/O of its own. connect() now succeeds as long
  as either send or receive is permitted for the address.
- Tcp/UdpSocket::connect now also check the implicit bind the OS
  performs when connecting an unbound socket, matching the check
  already done for explicit binds.

Added test coverage for previously-untested behavior:

- test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP
  socket keeps it bound.
- test_udp_send_receive_multiple (p2): bulk send/receive of multiple
  datagrams in a single call over a connected stream().
- test_udp_receive_after_connect (p2): datagrams from other peers
  queued before connecting are filtered out once connected.

* Give it one last poll before finishing up
yagehu pushed a commit to yagehu/wasmtime-x that referenced this pull request Jul 26, 2026
* Unify the p2 & p3 socket implementations

The shared socket code (crates/wasi/src/sockets/*) was modeled after
the p2 interface, with p3 bindings papering over the differences, and
some functionality duplicated between p2/* and p3/*. This has already
caused bugs in the past (bytecodealliance#13631).

Since the p3 interface is strictly a superset of p2, invert that
relationship: the shared code becomes the canonical (p3-shaped)
implementation, and p3's bindings are now a thin wrapper around it.
All p2-only behavior & state moves into the p2 bindings layer instead
(artificial restrictions like disallowing implicit binds, and the
start/finish async bookkeeping).

Other notable changes:

- Each socket now stores its own copy of the WasiCtx's
  socket_addr_check at creation time, so all permission checks live in
  the shared socket code instead of being split across p2/p3. The p2
  Network resource is now just an unforgeable capability token.
- Removed the Bound state; whether a socket is bound is now determined
  lazily via getsockname/local_addr instead of tracked explicitly. This
  lets UdpSocket::send return a future that runs to completion
  independently, without needing to rendezvous back with the socket to
  update its state.
- Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive;
  replaced UdpConnect with UdpSend/UdpReceive checks, since connecting
  a UDP socket is just a local operation that sets the default remote
  address and does no I/O of its own. connect() now succeeds as long
  as either send or receive is permitted for the address.
- Tcp/UdpSocket::connect now also check the implicit bind the OS
  performs when connecting an unbound socket, matching the check
  already done for explicit binds.

Added test coverage for previously-untested behavior:

- test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP
  socket keeps it bound.
- test_udp_send_receive_multiple (p2): bulk send/receive of multiple
  datagrams in a single call over a connected stream().
- test_udp_receive_after_connect (p2): datagrams from other peers
  queued before connecting are filtered out once connected.

* Give it one last poll before finishing up
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wasi Issues pertaining to WASI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasi-sockets] Inconsistency in udp/send with unspecified remote address

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.